dart - 如何为字段的注释生成 Dart 代码?
问题描述
我正在使用 为 Dart 编写代码生成器build_runner
,但我的构建器不会被调用以在字段中进行注释,尽管它确实适用于类中的注释。
是否也可以在字段(或在任何地方)调用注释生成器?
例如,为以下文件调用构建器:
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"]
解决方案
至少根据我的经验,您的文件“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;
}
}
注意:在本例中,_generateSource 返回一个注释语句。如果没有注释,您将需要返回格式良好的 dart 源代码,否则,构建器将因错误而终止。
有关更多信息,请参阅:源代码生成和编写自己的包(无聊的 Flutter 开发秀,第 22 集)https://www.youtube.com/watch?v=mYDFOdl-aWM&t=459s
推荐阅读
- git - 如何通过保留我更改的文件版本来解决 git 合并冲突?
- javascript - 第三方 iframe HTML 的 SameSite 错误
- kotlin - 获取对 class.field_1 的访问权限,将其属性名称与字符串“field_”和“1”结合起来
- python - 我在课堂外的函数调用在 Scrapy / Python 中不起作用
- python - 在 Python 中保存绘图对象
- php - 通过 PHP 中的分隔符过滤 CSV 文件中的行
- python - 尝试使用 discord.py 机器人在语音通道之间移动用户
- python - 尝试通过 pip 和命令提示符安装 pyinstaller 时出错
- javascript - node.js 将数据写入已连接的网络套接字
- python - 没有名为“请求”的模块,请求显示它已安装