Flutter抽象语法树探索插件ast_explorer_cli的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter抽象语法树探索插件ast_explorer_cli的使用

Pub Version Pub Points License: MIT

一个用于探索Flutter/Dart简化抽象语法树(AST)的命令行界面。

目标是获取类型、名称、值、偏移量和文件结束位置。


获取开始 🚀

如果CLI应用程序在pub上可用,可以通过以下方式全局激活:

dart pub global activate ast_explorer_cli

使用

要检查未使用的翻译,可以使用以下命令:

ast_explorer tree <folder-of-app>

本地运行

要本地运行,可以使用以下命令:

dart pub global activate --source=path . && ast_explorer tree example/main.dart

测试覆盖率运行 🧪

要运行所有单元测试并生成覆盖率报告,可以使用以下命令:

dart pub global activate coverage
dart test --coverage=coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info

查看生成的覆盖率报告可以使用lcov

# 生成覆盖率报告
genhtml coverage/lcov.info -o coverage/

# 打开覆盖率报告
open coverage/index.html

构建版本

要构建版本,可以使用以下命令:

dart run build_runner build

示例

示例1

首先,激活Very Good CLI

dart pub global activate ast_explorer_cli

查看可用命令列表:

ast_explorer --help

创建一个名为main.dart的Dart文件,并添加以下代码:

// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  double _counterDouble = 0.0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

运行以下命令生成输出文件ouput.json

ast_explorer tree main.dart > output.json

生成的output.json文件内容如下:

{
  "childEntities": [
    {
      "offset": 217,
      "end": 256,
      "type": "ImportDirectiveImpl",
      "childEntities": [
        {
          "offset": 224,
          "end": 255,
          "type": "SimpleStringLiteralImpl",
          "value": "package:flutter/material.dart"
        }
      ]
    },
    {
      "offset": 258,
      "end": 289,
      "type": "FunctionDeclarationImpl",
      "childEntities": [
        {
          "offset": 258,
          "end": 262,
          "type": "NamedTypeImpl",
          "childEntities": [
            {
              "offset": 258,
              "end": 262,
              "type": "SimpleIdentifierImpl",
              "token": "void"
            }
          ]
        },
        {
          "offset": 267,
          "end": 289,
          "type": "FunctionExpressionImpl",
          "childEntities": [
            { "offset": 267, "end": 269, "type": "FormalParameterListImpl" },
            {
              "offset": 270,
              "end": 289,
              "type": "ExpressionFunctionBodyImpl",
              "childEntities": [
                {
                  "offset": 273,
                  "end": 288,
                  "type": "MethodInvocationImpl",
                  "childEntities": [
                    {
                      "offset": 273,
                      "end": 279,
                      "type": "SimpleIdentifierImpl",
                      "token": "runApp"
                    },
                    {
                      "offset": 279,
                      "end": 288,
                      "type": "ArgumentListImpl",
                      "childEntities": [
                        {
                          "offset": 280,
                          "end": 287,
                          "type": "MethodInvocationImpl",
                          "childEntities": [
                            {
                              "offset": 280,
                              "end": 285,
                              "type": "SimpleIdentifierImpl",
                              "token": "MyApp"
                            },
                            {
                              "offset": 285,
                              "end": 287,
                              "type": "ArgumentListImpl"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    // ...省略部分代码...
  ],
  "end": 1717,
  "offset": 0,
  "type": "CompilationUnitImpl"
}

更多关于Flutter抽象语法树探索插件ast_explorer_cli的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter抽象语法树探索插件ast_explorer_cli的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用 ast_explorer_cli 插件来探索 Flutter 抽象语法树(AST)的代码案例。ast_explorer_cli 是一个命令行工具,它可以帮助开发者分析和理解 Dart 源代码的 AST。

安装 ast_explorer_cli

首先,你需要全局安装 ast_explorer_cli。你可以使用 Dart 的包管理工具 pub 来完成这个操作。打开你的终端或命令行工具,然后运行以下命令:

dart pub global activate ast_explorer_cli

使用 ast_explorer_cli 分析 Flutter/Dart 代码

假设你有一个简单的 Flutter/Dart 文件,例如 example.dart,内容如下:

void main() {
  print('Hello, World!');
}

你可以使用 ast_explorer_cli 来分析这个文件的 AST。运行以下命令:

ast_explorer example.dart

这个命令会启动一个交互式终端界面,显示 example.dart 文件的 AST 结构。你可以在界面中导航和查看 AST 的不同节点。

不过,如果你更希望在代码中直接处理 AST,而不是使用交互式界面,你可以使用 Dart 的 analyzer 包来编写一个自定义的 AST 分析工具。以下是一个简单的示例代码,展示如何使用 analyzer 包来解析并打印 AST:

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';

void main() {
  // 创建一个 AnalysisContextCollection 实例
  var contextCollection = AnalysisContextCollection(
    includedPaths: ['path/to/your/flutter/project'], // 替换为你的 Flutter 项目路径
    excludedPaths: [],
  );

  // 获取 AnalysisContext 实例
  var context = contextCollection.contextForPath('path/to/your/flutter/project/lib/example.dart'); // 替换为你的 Dart 文件路径

  // 解析文件并获取解析结果
  var result = context.resolveFile('lib/example.dart'); // 同样替换为你的 Dart 文件路径相对于项目根目录的部分

  // 获取 AST 节点
  var unit = result.unit;

  // 创建一个 ASTVisitor 来遍历 AST 节点
  class MyAstVisitor extends RecursiveAstVisitor<void> {
    @override
    void visitNode(AstNode node) {
      // 打印节点类型和行号(可选)
      print('Node type: ${node.runtimeType}, Line: ${node.beginToken.line}');
      super.visitNode(node);
    }
  }

  // 使用访客模式遍历 AST 并打印节点信息
  unit.accept(MyAstVisitor());
}

运行代码

将上述代码保存为一个 Dart 文件(例如 ast_explorer.dart),然后在终端中运行:

dart ast_explorer.dart

确保你已经将 path/to/your/flutter/projectlib/example.dart 替换为你的实际项目路径和 Dart 文件路径。

这个示例代码会解析指定的 Dart 文件,并打印出 AST 中每个节点的类型和行号。你可以根据需要扩展 MyAstVisitor 类来处理不同类型的 AST 节点。

虽然这个示例没有直接使用 ast_explorer_cli 插件的交互式功能,但它展示了如何使用 Dart 的 analyzer 包来分析 AST,这在构建自定义 AST 分析工具时非常有用。

回到顶部