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

1 回复

更多关于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);
}
回到顶部