【问题标题】:Get name of undefined super type or interface with source_gen使用 source_gen 获取未定义的超类型或接口的名称
【发布时间】:2021-07-03 10:59:10
【问题描述】:

我正在开发一个构建器包,并希望访问定义为超级约束的类名。第一次构建时,它不会存在,所以我猜source_gen 只是将其排除在分析之外

例如,考虑到我要求用户定义

@fireproof
class User extends _$User {
  final UserBase data;

  User({
    required this.data,
    required DocumentSnapshot snapshot,
  }) : super(snapshot);

  factory User.fromSnapshot(DocumentSnapshot snapshot) =>
      _$UserFromSnapshot(snapshot);
}

如何获得尚未定义的类 _$User 的名称?我希望是动态的,所以即使用户决定将其命名为其他名称,我也可以适应该名称。

我已经尝试了元素上的大多数字段,但找不到任何可以给我的字段:

@override
FutureOr<String> generateForAnnotatedElement(
  Element element,
  ConstantReader annotation,
  BuildStep buildStep,
) async {
  final classElement = element as ClassElement;

  classElement.supertype; // Object
  classElement.displayName; // class User

  // I want _$User somehow
}

也许答案涉及到 ast,但我对此并不是很有经验。

【问题讨论】:

    标签: flutter code-generation


    【解决方案1】:

    我在freezed 附近闲逛,发现了一个帮助函数,可以让您获取元素的 ast 节点。

    Future<AstNode> tryGetAstNodeForElement(
      Element element,
      BuildStep buildStep,
    ) async {
      var library = element.library!;
    
      while (true) {
        try {
          return library.session
              .getParsedLibraryByElement(library)
              .getElementDeclaration(element)!
              .node;
        } on InconsistentAnalysisException {
          library = await buildStep.resolver.libraryFor(
            await buildStep.resolver.assetIdForElement(element.library!),
          );
        }
      }
    }
    

    使用该函数,您可以获得 ast 节点,然后您可以遍历其子节点以寻找您想要的模式。在freezed,是这样的

    Token? equalToken = ast.endToken;
    while (true) {
      if (equalToken == null ||
          equalToken.charOffset < constructor.nameOffset) {
        return null;
      }
      if (equalToken.stringValue == '=>') return null;
      if (equalToken.stringValue == '=') {
        break;
      }
    
      equalToken = equalToken.previous;
    }
    

    所以他们向后遍历令牌,直到他们发现令牌等于他们想要的令牌(然后他们用来获取重定向构造函数的相等令牌)。

    在我的例子中,我只是寻找类型的关闭和打开 &lt; &gt; 并将内部类型存储为字符串。 AST 不会忽略未定义的标记。

    所有功劳归于 Rémi Rousselet 和他的包裹

    【讨论】:

    • 如果您正在寻找 StringTokens,请确保使用 .lexeme 而不是 .stringValue
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    相关资源
    最近更新 更多