Flutter抽象语法树操作插件flutter_ast的使用
Flutter抽象语法树操作插件flutter_ast的使用
Dart/Flutter AST Generator
flutter_ast
是一个用于解析 Dart 或 Flutter 文件并返回有意见的抽象语法树(AST)的插件。该 AST 可用于动态生成小部件或运行时。它可以在浏览器或原生环境中运行。
使用方式
通过命令行调用
你可以通过命令行传递文件或目录作为输入:
$ dart ./bin/generator.dart -p samples/example.dart
$ dart ./bin/generator.dart -p samples
直接调用方法
你也可以直接在代码中调用该方法:
final DartResult result = parseSource("Dart Code Here");
print(result.toJson());
特性
- ✅ 类
- ✅ 枚举
- ✅ 逻辑树
- ✅ Flutter 支持
- ✅ 顶级方法和变量
- ✅ 方法
- ✅ 字段
- ✅ 构造函数
示例
以下是一个示例输入:
import 'package:flutter/material.dart';
enum MyEnum { one, type, three }
const int kGlobalField = 1;
/// 这是一个文档注释
class MyScreen extends StatelessWidget {
const MyScreen(this.position, {Key key, this.myField = false, this.mySecondField = 1,
this.numField = 3,
this.mapField = const {},
this.dateField,
this.listField = const [],
}) : super(key: key);
const MyScreen.alt(this.position, {Key key, this.mySecondField = double.infinity,
this.numField = 3,
this.mapField = const {},
this.listField = const [],
this.dateField,
}) : this.myField = true, super(key: key);
static const String routeName = '/my_route';
final bool myField;
final double mySecondField;
final num numField;
final Map mapField;
final DateTime dateField;
final List listField;
final int position;
// 这是一个普通注释
Map<String, dynamic> toJson() {
return {};
}
@override
Widget build(BuildContext context) {
if (myField) {
return mySecondField == 1 ? Container(color: Colors.red) : Container(color: Colors.blue);
}
return Container(
color: Colors.red,
width: 20,
child: Center(
child: Builder((context) {
return Text('Hello World');
}),
),
);
}
}
void myGlobalMethod() {
}
// 忽略这个简单的注释
class Simple {
String value;
}
上述代码将生成如下的输出:
{
"file": {
"name": null,
"imports": [
"package:flutter/material.dart"
],
"classes": [
{
"name": "MyScreen",
"comments": [
"这是一个文档注释"
],
"fields": [
{
"name": "routeName",
"type": "String"
},
{
"name": "myField",
"type": "bool"
},
{
"name": "mySecondField",
"type": "double"
},
{
"name": "numField",
"type": "num"
},
{
"name": "mapField",
"type": "Map"
},
{
"name": "dateField",
"type": "DateTime"
},
{
"name": "listField",
"type": "List"
},
{
"name": "position",
"type": "int"
}
],
"constructors": [
{
"name": "MyScreen",
"properties": [
{
"value": null,
"name": "key",
"type": "Key",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "false",
"name": "myField",
"type": "bool",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "1",
"name": "mySecondField",
"type": "double",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "3",
"name": "numField",
"type": "num",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "const {}",
"name": "mapField",
"type": "Map",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": null,
"name": "dateField",
"type": "DateTime",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "const []",
"name": "listField",
"type": "List",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
}
]
},
{
"name": "alt",
"properties": [
{
"value": null,
"name": "key",
"type": "Key",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": null,
"name": "mySecondField",
"type": "double",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "3",
"name": "numField",
"type": "num",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "const {}",
"name": "mapField",
"type": "Map",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": "const []",
"name": "listField",
"type": "List",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
},
{
"value": null,
"name": "dateField",
"type": "DateTime",
"isConst": false,
"isFinal": false,
"isNamed": true,
"isOptional": true,
"isPositional": false,
"isRequired": false,
"isRequiredPositional": false,
"isSynthetic": false,
"isRequiredNamed": false,
"isOptionalNamed": true
}
]
}
],
"methods": [
{
"name": "toJson",
"body": {
"name": "method_declaration",
"values": [
{
"name": "type",
"props": {
"0": "Map<String, dynamic>"
}
},
{
"name": "declaration",
"values": []
},
{
"name": "block_body",
"values": [
{
"name": "block",
"values": [
{
"name": "return",
"values": [
{
"name": "value",
"props": {
"0": {
"type": "Map",
"value": "{}"
}
}
}
]
}
]
}
]
}
]
},
"parameters": []
},
{
"name": "build",
"body": {
"name": "method_declaration",
"values": [
{
"name": "type",
"props": {
"0": "Widget"
}
},
{
"name": "declaration",
"values": []
},
{
"name": "block_body",
"values": [
{
"name": "block",
"values": [
{
"name": "if",
"values": [
{
"name": "name",
"props": {
"0": "myField"
}
},
{
"name": "block",
"values": [
{
"name": "return",
"values": [
{
"name": "conditional",
"values": [
{
"name": "binary",
"left": {
"name": "name",
"props": {
"0": "mySecondField"
}
},
"right": {
"name": "value",
"props": {
"0": {
"type": "int",
"value": "1"
}
}
},
"operation": "=="
},
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null
}
},
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null
}
}
]
}
]
}
]
}
]
},
{
"name": "return",
"values": [
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null,
"width": {
"name": "value",
"props": {
"0": {
"type": "int",
"value": "20"
}
}
},
"child": {
"name": "constructor",
"value": "Center",
"arguments": {
"child": {
"name": "constructor",
"value": "Builder",
"arguments": {}
}
}
}
}
}
]
}
]
}
]
}
]
},
"parameters": []
}
],
"tree": {
"name": null,
"body": {
"name": "block_body",
"values": [
{
"name": "block",
"values": [
{
"name": "if",
"values": [
{
"name": "name",
"props": {
"0": "myField"
}
},
{
"name": "block",
"values": [
{
"name": "return",
"values": [
{
"name": "conditional",
"values": [
{
"name": "binary",
"left": {
"name": "name",
"props": {
"0": "mySecondField"
}
},
"right": {
"name": "value",
"props": {
"0": {
"type": "int",
"value": "1"
}
}
},
"operation": "=="
},
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null
}
},
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null
}
}
]
}
]
}
]
}
]
},
{
"name": "return",
"values": [
{
"name": "constructor",
"value": "Container",
"arguments": {
"color": null,
"width": {
"name": "value",
"props": {
"0": {
"type": "int",
"value": "20"
}
}
},
"child": {
"name": "constructor",
"value": "Center",
"arguments": {
"child": {
"name": "constructor",
"value": "Builder",
"arguments": {}
}
}
}
}
}
]
}
]
}
]
},
"parameters": []
}
},
{
"name": "Simple",
"comments": [],
"fields": [
{
"name": "value",
"type": "String"
}
],
"constructors": [],
"methods": []
}
],
"enums": [
{
"name": "MyEnum",
"values": [
"one",
"type",
"three"
]
}
],
"fields": [
{
"name": "kGlobalField",
"type": "int"
}
],
"methods": [
{
"name": "myGlobalMethod",
"body": {
"name": "function_declaration",
"values": [
{
"name": "type",
"props": {
"0": "void"
}
},
{
"name": "declaration",
"values": []
},
{
"name": "function",
"values": [
{
"name": "block_body",
"values": [
{
"name": "block",
"values": []
}
]
}
]
}
]
},
"parameters": []
}
]
},
"errors": []
}
更多关于Flutter抽象语法树操作插件flutter_ast的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter抽象语法树操作插件flutter_ast的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_ast
是一个用于操作 Flutter 抽象语法树(AST)的插件。它允许开发者分析和修改 Flutter 代码的语法树结构,从而实现代码生成、转换、优化等高级功能。以下是如何使用 flutter_ast
插件的基本指南。
1. 安装 flutter_ast
首先,你需要在 pubspec.yaml
文件中添加 flutter_ast
依赖:
dependencies:
flutter_ast: ^0.0.1 # 请根据实际情况使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入 flutter_ast
在你的 Dart 文件中导入 flutter_ast
:
import 'package:flutter_ast/flutter_ast.dart';
3. 解析代码为 AST
使用 flutter_ast
解析 Dart 代码为 AST:
void main() {
String code = '''
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!'),
);
}
}
''';
AstNode ast = FlutterAst.parse(code);
print(ast);
}
4. 遍历和修改 AST
你可以遍历 AST 并对其进行修改。例如,找到所有的 Text
节点并将其内容改为大写:
void main() {
String code = '''
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!'),
);
}
}
''';
AstNode ast = FlutterAst.parse(code);
ast.visitChildren((node) {
if (node is InstanceCreationExpression && node.constructorName.type.name == 'Text') {
ArgumentList args = node.argumentList;
if (args.arguments.isNotEmpty && args.arguments.first is StringLiteral) {
StringLiteral literal = args.arguments.first as StringLiteral;
literal.value = literal.value.toUpperCase();
}
}
});
print(FlutterAst.generate(ast));
}
5. 生成代码
使用 FlutterAst.generate
将修改后的 AST 转换回 Dart 代码:
void main() {
String code = '''
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, World!'),
);
}
}
''';
AstNode ast = FlutterAst.parse(code);
ast.visitChildren((node) {
if (node is InstanceCreationExpression && node.constructorName.type.name == 'Text') {
ArgumentList args = node.argumentList;
if (args.arguments.isNotEmpty && args.arguments.first is StringLiteral) {
StringLiteral literal = args.arguments.first as StringLiteral;
literal.value = literal.value.toUpperCase();
}
}
});
String modifiedCode = FlutterAst.generate(ast);
print(modifiedCode);
}