如何在字段处为注释生成Dart代码?
我正在使用如何在字段处为注释生成Dart代码?,dart,build-runner,Dart,Build Runner,我正在使用build\u runner为Dart编写一个代码生成器,但是我的生成器不会在字段中调用注释,尽管它在类中可以用于注释 也可以在字段(或任何地方)调用生成器进行注释吗 例如,为以下文件调用生成器: import'package:my_annotation/my_annotation.dart'; “示例g.省道”部分; @MyAnnotation() 等级水果{ 整数; } 但这一次不行: import'package:my_annotation/my_annotation.dart
build\u runner
为Dart编写一个代码生成器,但是我的生成器不会在字段中调用注释,尽管它在类中可以用于注释
也可以在字段(或任何地方)调用生成器进行注释吗
例如,为以下文件调用生成器:
import'package:my_annotation/my_annotation.dart';
“示例g.省道”部分;
@MyAnnotation()
等级水果{
整数;
}
但这一次不行:
import'package:my_annotation/my_annotation.dart';
“示例g.省道”部分;
等级水果{
@MyAnnotation()
整数;
}
以下是注释的定义:
class注释{
常量MyAnnotation();
}
这就是生成器的定义。目前,只要调用它,它就会中止,从而打印错误消息
库我的注释\u生成器;
导入“package:analyzer/dart/element/element.dart”;
导入“包:build/build.dart”;
导入“package:my_annotation/my_annotation.dart”;
导入“包:源代码/源代码.省道”;
生成器生成符号(生成器选项选项)=>
SharedPartBuilder([MyAnnotationGenerator()],'my_annotation');
类MyAnnotationGenerator扩展了GeneratorForAnnotation{
@凌驾
GenerateForNotatedElement(Element元素,ConstantTreader注释,41;{
throw CodeGenError('尚未实现为注释生成代码');
}
以下是build.yaml
配置:
targets:
$default:
builders:
my_annotation_generator|my_annotation:
enabled: true
builders:
my_annotation:
target: ":my_annotation_generator"
import: "package:my_annotation/my_annotation.dart"
builder_factories: ["generateAnnotation"]
build_extensions: { ".dart": [".my_annotation.g.part"] }
auto_apply: dependents
build_to: cache
applies_builders: ["source_gen|combining_builder"]
至少根据我的经验,您的文件“example.dart”需要在类定义上方至少有一个注释才能由GeneratorForAnnotation解析 示例.dart:
import 'package:my_annotation/my_annotation.dart';
part 'example.g.dart';
@MyAnnotation()
class Fruit {
@MyFieldAnnotation()
int number;
}
要访问类字段或类方法上方的注释,可以使用访问者“访问”每个子元素并提取源代码信息。
例如,要获取有关类字段的信息,可以重写visitFieldElement方法,然后使用getter:element.metadata访问任何注释
builder.dart:
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:build/src/builder/build_step.dart';
import 'package:source_gen/source_gen.dart';
import 'package:my_annotation/my_annotation.dart';
class MyAnnotationGenerator extends
GeneratorForAnnotation<MyAnnotation> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,){
return _generateSource(element);
}
String _generateSource(Element element) {
var visitor = ModelVisitor();
element.visitChildren(visitor);
return '''
// ${visitor.className}
// ${visitor.fields}
// ${visitor.metaData}
''';
}
}
class ModelVisitor extends SimpleElementVisitor {
DartType className;
Map<String, DartType> fields = {};
Map<String, dynamic> metaData = {};
@override
visitConstructorElement(ConstructorElement element) {
className = element.type.returnType;
}
@override
visitFieldElement(FieldElement element) {
fields[element.name] = element.type;
metaData[element.name] = element.metadata;
}
}
导入'dart:async';
导入“package:analyzer/dart/element/element.dart”;
导入“package:analyzer/dart/element/visitor.dart”;
导入“package:analyzer/dart/element/type.dart”;
导入“package:build/src/builder/build_step.dart”;
导入“包:源代码/源代码.省道”;
导入“package:my_annotation/my_annotation.dart”;
类MyAnnotationGenerator扩展
注释生成器{
@凌驾
未注元素的未来生成器(
元素元素,
康斯坦德雷德尔注释,
BuildStep BuildStep,){
返回_generateSource(元素);
}
字符串_generateSource(元素){
var visitor=ModelVisitor();
元素。访问儿童(访问者);
返回“”'
//${visitor.className}
//${visitor.fields}
//${visitor.metaData}
''';
}
}
类ModelVisitor扩展了SimpleElementVisitor{
DartType类名称;
映射字段={};
地图元数据={};
@凌驾
visitConstructorElement(ConstructorElement元素){
className=element.type.returnType;
}
@凌驾
visitFieldElement(字段元素){
字段[element.name]=element.type;
元数据[element.name]=element.metaData;
}
}
注意:在本例中,_generateSource返回一条注释语句。如果没有注释,则需要返回格式良好的dart源代码,否则,生成器将以错误终止
有关更多信息,请参阅:
源代码生成和编写您自己的包(无聊的颤振开发秀,第22页)内置的
注释生成器使用LibraryElement
的注释方法(…)
只检查顶级注释。
要同时检测字段上的注释,您需要编写一些自定义内容
以下是我为我的项目编写的生成器
:
abstract class GeneratorForAnnotatedField<AnnotationType> extends Generator {
/// Returns the annotation of type [AnnotationType] of the given [element],
/// or [null] if it doesn't have any.
DartObject getAnnotation(Element element) {
final annotations =
TypeChecker.fromRuntime(AnnotationType).annotationsOf(element);
if (annotations.isEmpty) {
return null;
}
if (annotations.length > 1) {
throw Exception(
"You tried to add multiple @$AnnotationType() annotations to the "
"same element (${element.name}), but that's not possible.");
}
return annotations.single;
}
@override
String generate(LibraryReader library, BuildStep buildStep) {
final values = <String>{};
for (final element in library.allElements) {
if (element is ClassElement && !element.isEnum) {
for (final field in element.fields) {
final annotation = getAnnotation(field);
if (annotation != null) {
values.add(generateForAnnotatedField(
field,
ConstantReader(annotation),
));
}
}
}
}
return values.join('\n\n');
}
String generateForAnnotatedField(
FieldElement field, ConstantReader annotation);
}
NanotatedField的抽象类生成器扩展了生成器{
///返回给定[element]的[AnnotationType]类型的批注,
///如果没有,则为[null]。
DartObject getAnnotation(元素){
最后注释=
TypeChecker.fromRuntime(AnnotationType).annotationsOf(元素);
if(annotations.isEmpty){
返回null;
}
如果(annotations.length>1){
抛出异常(
“您试图将多个@$AnnotationType()批注添加到”
“相同的元素(${element.name}),但这是不可能的。”;
}
返回注释。单个;
}
@凌驾
字符串生成(LibraryReader库,BuildStep BuildStep){
最终值={};
for(库中的最后一个元素。等位基因){
if(元素是ClassElement&!element.isEnum){
for(element.fields中的最后一个字段){
最终注释=getAnnotation(字段);
if(注释!=null){
添加(GenerateForNotatedField(
领域
康斯坦特雷德(注释),
));
}
}
}
}
返回值。join('\n\n');
}
字符串生成器ForNotatedField(
FieldElement字段,ConstantTreader注释);
}
Great,谢谢你,而不是使用一个只能检测顶级注释的<代码>泛指-注释>代码,我最终解决了一个自定义的<代码>生成器<代码>,它解析了所有字段。你可以在这里看到它:“马塞尔,谢谢你包括一个链接到你的项目。请考虑简短地回答你自己的问题。问题在这里。虽然代码生成的示例可以在github.com上找到,但仍然缺乏针对那些刚开始Dart源代码生成的人的文档。元数据不包括字段注释,这是有意的吗?如果不是,我们如何访问字段注释?当我尝试此操作时,元数据
总是空的。后来我意识到我是安诺塔