Flutter代码生成插件code_builder的使用

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

Flutter代码生成插件code_builder的使用

code_builder 是一个用于生成有效的Dart代码的流利、基于构建器的库。它具有窄而用户友好的API,可以轻松地创建类、方法、枚举等Dart代码结构。以下是关于如何使用 code_builder 的详细指南和示例。

使用示例

创建一个带有方法的类

下面的例子展示了如何使用 code_builder 创建一个继承自 OrganismAnimal 类,并为该类添加一个名为 eat 的方法。

import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';

void main() {
  final animal = Class((b) => b
    ..name = 'Animal'
    ..extend = refer('Organism')
    ..methods.add(Method.returnsVoid((b) => b
      ..name = 'eat'
      ..body = const Code("print('Yum!');"))));
  final emitter = DartEmitter();
  print(
    DartFormatter(languageVersion: DartFormatter.latestLanguageVersion)
        .format('${animal.accept(emitter)}'),
  );
}

输出结果:

class Animal extends Organism {
  void eat() => print('Yum!');
}

处理复杂的依赖关系

当生成的代码有复杂的依赖关系时,code_builder 支持自动作用域管理,以避免符号冲突。以下是一个例子:

import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';

void main() {
  final library = Library((b) => b.body.addAll([
        Method((b) => b
          ..body = const Code('')
          ..name = 'doThing'
          ..returns = refer('Thing', 'package:a/a.dart')),
        Method((b) => b
          ..body = const Code('')
          ..name = 'doOther'
          ..returns = refer('Other', 'package:b/b.dart')),
      ]));
  final emitter = DartEmitter.scoped();
  print(
    DartFormatter(languageVersion: DartFormatter.latestLanguageVersion)
        .format('${library.accept(emitter)}'),
  );
}

输出结果:

import 'package:a/a.dart' as _i1;
import 'package:b/b.dart' as _i2;

_i1.Thing doThing() {}
_i2.Other doOther() {}

生成带有注解的枚举

你可以使用 code_builder 来生成带有注解的枚举,例如 JSON 序列化的键值对。

import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';

final _dartfmt = DartFormatter(
  languageVersion: DartFormatter.latestLanguageVersion,
);

String jsonEnum() {
  final values = <EnumValue>[
    EnumValue((b) => b
      ..name = 'metric'
      ..annotations.addAll([
        refer('JsonKey').call([literalString('m')])
      ])),
    EnumValue((b) => b
      ..name = 'imperial'
      ..annotations.addAll([
        refer('JsonKey').call([literalString('i')])
      ])),
  ];
  final e = Enum((b) => b
    ..name = 'Unit'
    ..values.addAll(values));
  return _dartfmt.format('${e.accept(DartEmitter())}');
}

void main() {
  print('jsonEnum():\n${'=' * 40}\n${jsonEnum()}');
}

输出结果:

enum Unit {
  @JsonKey('m')
  metric,
  @JsonKey('i')
  imperial
}

完整示例Demo

为了更好地理解 code_builder 的用法,这里提供了一个完整的示例项目,包含了上述所有功能。

import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';

final _dartfmt = DartFormatter(
  languageVersion: DartFormatter.latestLanguageVersion,
);

void main() {
  print('animalClass():\n${'=' * 40}\n${animalClass()}');
  print('scopedLibrary():\n${'=' * 40}\n${scopedLibrary()}');
  print('jsonEnum():\n${'=' * 40}\n${jsonEnum()}');
}

/// Outputs:
///
/// ```dart
/// class Animal extends Organism {
///   void eat() => print('Yum!');
/// }
/// ```
String animalClass() {
  final animal = Class((b) => b
    ..name = 'Animal'
    ..extend = refer('Organism')
    ..methods.add(Method.returnsVoid((b) => b
      ..name = 'eat'
      ..body = refer('print').call([literalString('Yum!')]).code)));
  return _dartfmt.format('${animal.accept(DartEmitter())}');
}

/// Outputs:
///
/// ```dart
/// import 'package:a/a.dart' as _i1;
/// import 'package:b/b.dart' as _i2;
///
/// _i1.Thing doThing() {}
/// _i2.Other doOther() {}
/// ```
String scopedLibrary() {
  final methods = [
    Method((b) => b
      ..body = const Code('')
      ..name = 'doThing'
      ..returns = refer('Thing', 'package:a/a.dart')),
    Method((b) => b
      ..body = const Code('')
      ..name = 'doOther'
      ..returns = refer('Other', 'package:b/b.dart')),
  ];
  final library = Library((b) => b.body.addAll(methods));
  return _dartfmt.format('${library.accept(DartEmitter.scoped())}');
}

/// Outputs:
///
/// ```dart
/// enum Unit {
///  @JsonKey('m')
///  metric,
///  @JsonKey('i')
///  imperial
/// }
/// ```
String jsonEnum() {
  final values = <EnumValue>[
    EnumValue((b) => b
      ..name = 'metric'
      ..annotations.addAll([
        refer('JsonKey').call([literalString('m')])
      ])),
    EnumValue((b) => b
      ..name = 'imperial'
      ..annotations.addAll([
        refer('JsonKey').call([literalString('i')])
      ])),
  ];
  final e = Enum((b) => b
    ..name = 'Unit'
    ..values.addAll(values));
  return _dartfmt.format('${e.accept(DartEmitter())}');
}

通过这个完整的示例,你可以看到 code_builder 如何帮助你快速生成复杂的 Dart 代码结构,同时保持代码的可读性和可维护性。希望这些示例能帮助你更好地理解和使用 code_builder 插件。


更多关于Flutter代码生成插件code_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter代码生成插件code_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用code_builder插件来生成Dart代码的示例。code_builder是一个强大的Dart库,它允许你以编程方式生成Dart源代码。这在自动化代码生成、构建DSL(领域特定语言)或者生成重复代码时特别有用。

首先,你需要在你的pubspec.yaml文件中添加code_builder依赖:

dependencies:
  flutter:
    sdk: flutter
  code_builder: ^4.0.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

下面是一个简单的例子,演示如何使用code_builder来生成一个Dart类,并包含一些方法和字段:

import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';

void main() {
  // 创建一个类
  ClassBuilder classBuilder = ClassBuilder('GeneratedClass')
    ..addModifiers([Modifier.public])
    ..addField(Field((f) => f
      ..name = 'generatedField'
      ..type = refer('String')
      ..modifier = Modifier.public
      ..assignment = Code('"Initial Value"')
    ))
    ..addMethod(Method((m) => m
      ..name = 'generatedMethod'
      ..returnType = refer('void')
      ..modifiers = [Modifier.public]
      ..body = CodeBlock()
        ..addStatement(Code('print("Hello from generated method!");'))
    ));

  // 生成Dart代码
  DartFile dartFile = DartFile((file) => file
    ..addImports([
      Import('dart:core', ['String']),
    ])
    ..addType(classBuilder.build())
  );

  // 格式化并打印生成的代码
  String formattedCode = DartFormatter().format(dartFile.accept(DartEmitter()).toString());
  print(formattedCode);
}

这个示例做了以下几件事:

  1. 使用ClassBuilder创建了一个名为GeneratedClass的类。
  2. 添加了一个公共字段generatedField,类型为String,并初始化为"Initial Value"
  3. 添加了一个公共方法generatedMethod,该方法打印一条消息。
  4. 使用DartFile将生成的类包裹在一个Dart文件中,并添加了必要的导入。
  5. 使用DartFormatter格式化生成的代码,并打印出来。

运行这个Dart脚本(确保它是你的Flutter项目的根目录中的一个独立脚本,或者你可以将其集成到你的Flutter应用的某个逻辑部分中,尽管这通常不是最佳实践),你将看到类似下面的输出:

import 'dart:core';

class GeneratedClass {
  String generatedField = "Initial Value";

  void generatedMethod() {
    print("Hello from generated method!");
  }
}

这就是使用code_builder生成Dart代码的基本方法。你可以根据需要扩展这个示例,生成更复杂的代码结构。

回到顶部