Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在字段处为注释生成Dart代码?_Dart_Build Runner - Fatal编程技术网

如何在字段处为注释生成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源代码生成的人的文档。元数据不包括字段注释,这是有意的吗?如果不是,我们如何访问字段注释?当我尝试此操作时,
元数据
总是空的。后来我意识到我是安诺塔