我正在使用build_runner
为Dart编写代码生成器,但是虽然我的构建器确实可以在类中使用注释,但并未在字段中使用我的生成器。
是否可以在字段(或与此相关的任何位置)处调用生成器进行注释?
例如,将为以下文件调用构建器:
import 'package:my_annotation/my_annotation.dart';
part 'example.g.dart';
@MyAnnotation()
class Fruit {
int number;
}
但不是这个:
import 'package:my_annotation/my_annotation.dart';
part 'example.g.dart';
class Fruit {
@MyAnnotation()
int number;
}
这是注释的定义:
class MyAnnotation {
const MyAnnotation();
}
这就是生成器的定义方式。目前,只要调用它,它就会中止,从而导致显示错误消息。
library my_annotation_generator;
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:my_annotation/my_annotation.dart';
import 'package:source_gen/source_gen.dart';
Builder generateAnnotation(BuilderOptions options) =>
SharedPartBuilder([MyAnnotationGenerator()], 'my_annotation');
class MyAnnotationGenerator extends GeneratorForAnnotation<MyAnnotation> {
@override
generateForAnnotatedElement(Element element, ConstantReader annotation, _) {
throw CodeGenError('Generating code for annotation is not implemented yet.');
}
这是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"]
答案 0 :(得分:0)
至少从我的经验来看,您的文件“ example.dart”至少需要在类定义上方至少有一个批注,才能通过GeneratorForAnnotation进行解析。
example.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;
}
}
注意:在此示例中,_generateSource返回注释的语句。没有注释,您将需要返回格式正确的dart源代码,否则,构建器将终止并显示错误。
有关更多信息,请参见: 源代码生成和编写自己的程序包(无聊的Flutter开发展,第22页)https://www.youtube.com/watch?v=mYDFOdl-aWM&t=459s
答案 1 :(得分:0)
内置GeneratorForAnnotation
使用LibraryElement
的{{1}}方法,该方法仅检查顶级注释。
要同时检测字段上的注释,您需要编写一些自定义内容。
这是我为我的项目写的annotatedWith(...)
:
Generator