作者:工农大路店NOKIA客户服务中心 | 来源:互联网 | 2023-07-15 14:08
在做Dart代码分析的时候,Flutter官方提供了analyzer库,通过analyzer可以配置并分析代码的规范性等;但analyzer不仅可以帮助开发者分析代码的规范性,还可以把Dar
在做Dart代码分析的时候,Flutter官方提供了analyzer库,通过analyzer可以配置并分析代码的规范性等;但analyzer不仅可以帮助开发者分析代码的规范性,还可以把Dart代码转换成抽象语法树(AST),这个过程有点类似编译器的分词,可以把Dart代码按关键词分解成对应的数据模型,并进一步转换成我们熟悉的json或xml格式。官方版本为analyzer 0.41.1
我们先来看看Dart的类Class转换后的最终效果:
{
"type": "ClassDeclaration",
"id": {
"type": "Identifier",
"name": "AnalyzerDemo"
},
"superClause": {
"type": "TypeName",
"name": "SuperClass"
},
"implementsClause": {
"type": "ImplementsClause",
"implements": [
{
"type": "TypeName",
"name": "ImplementClass"
}
]
},
"mixinClause": null,
"metadata": [],
"body": []
}
转换之前先来了解一下转换过程中用到的一个重要的类——AstNode,AstNode是AST转换过程中各种语法类型转换后数据模型的父节点,定义了该节点的基本信息:
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 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 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(AstVisitor 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(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(Predicate 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();
/// 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节点的基本信息:包括标识符(beginToken/endToken)、子元素(childEntities)、父节点(parent)、遍历方法(accept)、子元素遍历方法(visitChildren)等等,几乎所有的AST节点类型都继承于它;通过解释AstNode的衍生节点信息,我们可以把各种AST转换成我们想要的格式。