Flutter動(dòng)態(tài)特性調(diào)研之——AstNode

在做Dart代碼分析的時(shí)候,F(xiàn)lutter官方提供了analyzer庫(kù),通過(guò)analyzer可以配置并分析代碼的規(guī)范性等;但analyzer不僅可以幫助開(kāi)發(fā)者分析代碼的規(guī)范性,還可以把Dart代碼轉(zhuǎn)換成抽象語(yǔ)法樹(shù)(AST),這個(gè)過(guò)程有點(diǎn)類似編譯器的分詞,可以把Dart代碼按關(guān)鍵詞分解成對(duì)應(yīng)的數(shù)據(jù)模型,并進(jìn)一步轉(zhuǎn)換成我們熟悉的json或xml格式。官方版本為analyzer 0.41.1
我們先來(lái)看看Dart的類Class轉(zhuǎn)換后的最終效果:

  {
    "type": "ClassDeclaration",
    "id": {
      "type": "Identifier",
      "name": "AnalyzerDemo"
    },
    "superClause": {
      "type": "TypeName",
      "name": "SuperClass"
    },
    "implementsClause": {
      "type": "ImplementsClause",
      "implements": [
        {
          "type": "TypeName",
          "name": "ImplementClass"
        }
      ]
    },
    "mixinClause": null,
    "metadata": [],
    "body": []
  }

轉(zhuǎn)換之前先來(lái)了解一下轉(zhuǎn)換過(guò)程中用到的一個(gè)重要的類——AstNode,AstNode是AST轉(zhuǎn)換過(guò)程中各種語(yǔ)法類型轉(zhuǎn)換后數(shù)據(jù)模型的父節(jié)點(diǎn),定義了該節(jié)點(diǎn)的基本信息:

abstract class AstNode implements SyntacticEntity {
  /// A comparator that can be used to sort AST nodes in lexical order.
  ///
  /// In other words, `compare` will return a negative value if the offset of
  /// the first node is less than the offset of the second node, zero (0) if
  /// the nodes have the same offset, and a positive value if the offset of the
  /// first node is greater than the offset of the second node.
  static Comparator<AstNode> LEXICAL_ORDER =
      (AstNode first, AstNode second) => first.offset - second.offset;

  /// Return the first token included in this node's source range.
  Token get beginToken;

  /// Return an iterator that can be used to iterate through all the entities
  /// (either AST nodes or tokens) that make up the contents of this node,
  /// including doc comments but excluding other comments.
  Iterable<SyntacticEntity> get childEntities;

  /// Return the offset of the character immediately following the last
  /// character of this node's source range.
  ///
  /// This is equivalent to `node.getOffset() + node.getLength()`. For a
  /// compilation unit this will be equal to the length of the unit's source.
  /// For synthetic nodes this will be equivalent to the node's offset (because
  /// the length is zero (0) by definition).
  @override
  int get end;

  /// Return the last token included in this node's source range.
  Token get endToken;

  /// Return `true` if this node is a synthetic node.
  ///
  /// A synthetic node is a node that was introduced by the parser in order to
  /// recover from an error in the code. Synthetic nodes always have a length
  /// of zero (`0`).
  bool get isSynthetic;

  @override
  int get length;

  @override
  int get offset;

  /// Return this node's parent node, or `null` if this node is the root of an
  /// AST structure.
  ///
  /// Note that the relationship between an AST node and its parent node may
  /// change over the lifetime of a node.
  AstNode get parent;

  /// Return the node at the root of this node's AST structure.
  ///
  /// Note that this method's performance is linear with respect to the depth
  /// of the node in the AST structure (O(depth)).
  AstNode get root;

  /// Use the given [visitor] to visit this node.
  ///
  /// Return the value returned by the visitor as a result of visiting this
  /// node.
  E accept<E>(AstVisitor<E> visitor);

  /// Return the token before [target] or `null` if it cannot be found.
  Token findPrevious(Token target);

  /// Return the value of the property with the given [name], or `null` if this
  /// node does not have a property with the given name.
  E getProperty<E>(String name);

  /// Set the value of the property with the given [name] to the given [value].
  /// If the value is `null`, the property will effectively be removed.
  void setProperty(String name, Object value);

  /// Return either this node or the most immediate ancestor of this node for
  /// which the [predicate] returns `true`, or `null` if there is no such node.
  E thisOrAncestorMatching<E extends AstNode>(Predicate<AstNode> predicate);

  /// Return either this node or the most immediate ancestor of this node that
  /// has the given type, or `null` if there is no such node.
  E thisOrAncestorOfType<E extends AstNode>();

  /// Return a textual description of this node in a form approximating valid
  /// source.
  ///
  /// The returned string will not be valid source primarily in the case where
  /// the node itself is not well-formed.
  String toSource();

  /// Use the given [visitor] to visit all of the children of this node.
  ///
  /// The children will be visited in lexical order.
  void visitChildren(AstVisitor visitor);
}

AstNode描述了AST節(jié)點(diǎn)的基本信息:包括標(biāo)識(shí)符(beginToken/endToken)、子元素(childEntities)、父節(jié)點(diǎn)(parent)、遍歷方法(accept)、子元素遍歷方法(visitChildren)等等,幾乎所有的AST節(jié)點(diǎn)類型都繼承于它;通過(guò)解釋AstNode的衍生節(jié)點(diǎn)信息,我們可以把各種AST轉(zhuǎn)換成我們想要的格式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容