在做Dart代碼分析的時候,F(xiàn)lutter官方提供了analyzer庫,通過analyzer可以配置并分析代碼的規(guī)范性等脖卖;但analyzer不僅可以幫助開發(fā)者分析代碼的規(guī)范性弥奸,還可以把Dart代碼轉(zhuǎn)換成抽象語法樹(AST)盛泡,這個過程有點(diǎn)類似編譯器的分詞捺癞,可以把Dart代碼按關(guān)鍵詞分解成對應(yīng)的數(shù)據(jù)模型夷蚊,并進(jìn)一步轉(zhuǎn)換成我們熟悉的json或xml格式。官方版本為analyzer 0.41.1
我們先來看看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)換之前先來了解一下轉(zhuǎn)換過程中用到的一個重要的類——AstNode髓介,AstNode是AST轉(zhuǎn)換過程中各種語法類型轉(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)識符(beginToken/endToken)、子元素(childEntities)唐础、父節(jié)點(diǎn)(parent)箱歧、遍歷方法(accept)、子元素遍歷方法(visitChildren)等等一膨,幾乎所有的AST節(jié)點(diǎn)類型都繼承于它呀邢;通過解釋AstNode的衍生節(jié)點(diǎn)信息,我們可以把各種AST轉(zhuǎn)換成我們想要的格式豹绪。