为什么我使用'build_runner'和'source_gen'生成的flutter代码不创建输出文件?

fdx2calv  于 2022-12-27  发布在  Flutter
关注(0)|答案(1)|浏览(269)

我正在尝试使用build_runnersource_gen包在Flutter中创建一个代码生成包。我已经查看了许多示例,但似乎找不到阻止创建输出文件的原因。我知道这可能是一些愚蠢的事情,但我已经尝试了几天,似乎找不到问题。
到目前为止,我已经得到了以下目录结构:

─┬ fletch
 ├── fletch_annotations
 ├── fletch_example
 └── fletch_generator

fletch_annotations具有如下注解类:

package:fletch_annotations/src/model/annotation/column.dart
import 'package:fletch_annotations/src/model/enum/enum.dart';

class Column {
  final FletchDataType dataType;
  final bool isNullable;
  final OnConflictAction onConflictAction;
  final OnDeleteAction onDeleteAction;
  final OnUpdateAction onUpdateAction;
  final bool isUnique;
  final String? columnName;
  final dynamic defaultValue;
  final String? check;

  const Column({
    required this.dataType,
    required this.isNullable,
    this.onConflictAction = OnConflictAction.abort,
    this.onDeleteAction = OnDeleteAction.setDefault,
    this.onUpdateAction = OnUpdateAction.setDefault,
    this.isUnique = false,
    this.columnName,
    this.defaultValue,
    this.check,
  });
}

fletch_generator中,我有以下pubspec.yaml文件:

fletch_generator/pubspec.yaml
name: fletch_generator
description: A new Flutter package project.
version: 0.0.1
homepage: https://example.com #! TODO: Replace this

environment:
  sdk: ">=2.18.4 <3.0.0"

dependencies:
  analyzer: ^5.3.1
  build: ^2.3.1
  collection: ^1.17.0
  fletch_annotations:
    path: ../fletch_annotations
  source_gen: ^1.2.6

dev_dependencies:
  build_config: ^1.1.1
  build_runner: ^2.3.2
  build_test: ^2.1.5
  flutter_lints: ^2.0.1
  test: ^1.22.1

fletch_generator有对应的模型类:

package:fletch_generator/src/model/column.dart
import 'package:fletch_annotations/fletch_annotations.dart';

class Column {
  final FletchDataType dataType;
  final bool isNullable;
  final OnConflictAction onConflictAction;
  final OnDeleteAction onDeleteAction;
  final OnUpdateAction onUpdateAction;
  final bool isUnique;
  final String? columnName;
  final dynamic defaultValue;
  final String? check;

  Column({
    required this.dataType,
    required this.isNullable,
    this.onConflictAction = OnConflictAction.abort,
    this.onDeleteAction = OnDeleteAction.setDefault,
    this.onUpdateAction = OnUpdateAction.setDefault,
    this.isUnique = false,
    this.columnName,
    this.defaultValue,
    this.check,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Column &&
          runtimeType == other.runtimeType &&
          dataType == other.dataType &&
          isNullable == other.isNullable &&
          onConflictAction == other.onConflictAction &&
          onDeleteAction == other.onDeleteAction &&
          onUpdateAction == other.onUpdateAction &&
          isUnique == other.isUnique &&
          columnName == other.columnName &&
          defaultValue == other.defaultValue &&
          check == other.check;

  @override
  int get hashCode {
    return Object.hash(dataType, columnName, defaultValue, check);
  }

  @override
  String toString() {
    return 'Column('
        'dataType: $dataType, '
        'isNullable: $isNullable ,'
        'onConflictAction: $onConflictAction ,'
        'onDeleteAction: $onDeleteAction ,'
        'onUpdateAction: $onUpdateAction ,'
        'isUnique: $isUnique ,'
        'columnName: $columnName, '
        'defaultValue: $defaultValue, '
        'check: $check'
        ')';
  }
}

我在fletch_generator中的build.yaml文件:

一米十一分
targets:
  $default:
    builders:
      fletch_generator:
        enabled: true
      source_gen|combining_builder:
        enabled: true
        options:
          ignore_for_file:
            - lines_longer_than_80_chars
            - lint_alpha
            - lint_beta
          build_extensions: '"{{dir}}/entity/{{file}}.dart": "{{dir}}/dao/{{file}}.g.dart"'

builders:
  fletch_generator:
    import: "package:fletch_generator/builder.dart"
    builder_factories: ["fletchBuilder"]
    build_extensions: { ".dart": [".fletch.g.part"] }
    auto_apply: dependents
    build_to: cache
    applies_builders: ["source_gen|combining_builder"]

build.dart,也在fletch_generator中(在lib目录中):

package:fletch_generator/build.dart
import 'package:build/build.dart';
import 'package:fletch_generator/src/generator/column.dart';
import 'package:source_gen/source_gen.dart';

Builder fletchBuilder(final BuilderOptions _) =>
    SharedPartBuilder([ColumnGenerator()], 'fletch');

最后是ColumnGeneratorfletch_generator定义:

package:fletch_generator/src/generator/column.dart
import 'dart:async';

import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:fletch_annotations/fletch_annotations.dart' as annotations;
import 'package:source_gen/source_gen.dart';

class ColumnGenerator extends GeneratorForAnnotation<annotations.Column> {
  @override
  FutureOr<String> generateForAnnotatedElement(
    Element element,
    ConstantReader annotation,
    BuildStep buildStep,
  ) {
    return '// ColumnProcessor works!';
  }
}

fletch_example中,我有一个使用Column注解的sample_class

'软件包:fletch_example/源代码/模型/实体/样本类. dart
import 'package:fletch_annotations/fletch_annotations.dart';

part '../dao/sample_class.g.dart';

class SampleClass {
  @Column(
    dataType: FletchDataType.bigInt,
    isNullable: false,
  )
  final int? sampleClassIndex;

  SampleClass({
    this.sampleClassIndex,
  });
}

以及fletch_examplepubspec.yaml文件中的相应依赖项:

name: fletch_example
description: A starting point for Dart libraries or applications.
version: 1.0.0
# homepage: https://www.example.com

environment:
  sdk: ">=2.18.4 <3.0.0"

dependencies:
  fletch_annotations:
    path: ../fletch_annotations

dev_dependencies:
  build_runner: ^2.3.2
  fletch_generator:
    path: ../fletch_generator
  flutter_lints: ^2.0.1
  lints: ^2.0.0
  test: ^1.16.0

fletch_example目录中,运行以下命令:

flutter clean
flutter pub get
flutter packages pub run build_runner build --delete-conflicting-outputs

这将生成以下控制台输出:

[INFO] Generating build script...
[INFO] Generating build script completed, took 525ms

[INFO] Precompiling build script......
[INFO] Precompiling build script... completed, took 9.5s

[INFO] Initializing inputs
[INFO] Building new asset graph...
[INFO] Building new asset graph completed, took 1.3s

[INFO] Checking for unexpected pre-existing outputs....
[INFO] Checking for unexpected pre-existing outputs. completed, took 1ms

[INFO] Running build...
[INFO] Generating SDK summary...
[INFO] 2.8s elapsed, 0/1 actions completed.
[INFO] 5.3s elapsed, 0/1 actions completed.
[INFO] Generating SDK summary completed, took 6.2s

[INFO] Running build completed, took 6.3s

[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 40ms

[INFO] Succeeded after 6.4s with 0 outputs (2 actions)

它还会创建以下fletch_example/.dart_tool/build/entrypoint/build.dart文件:

// ignore_for_file: directives_ordering
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:build_runner_core/build_runner_core.dart' as _i1;
import 'package:fletch_generator/builder.dart' as _i2;
import 'package:source_gen/builder.dart' as _i3;
import 'dart:isolate' as _i4;
import 'package:build_runner/build_runner.dart' as _i5;
import 'dart:io' as _i6;

final _builders = <_i1.BuilderApplication>[
  _i1.apply(
    r'fletch_generator:fletch_generator',
    [_i2.fletchBuilder],
    _i1.toDependentsOf(r'fletch_generator'),
    hideOutput: true,
    appliesBuilders: const [r'source_gen:combining_builder'],
  ),
  _i1.apply(
    r'source_gen:combining_builder',
    [_i3.combiningBuilder],
    _i1.toNoneByDefault(),
    hideOutput: false,
    appliesBuilders: const [r'source_gen:part_cleanup'],
  ),
  _i1.applyPostProcess(
    r'source_gen:part_cleanup',
    _i3.partCleanup,
  ),
];
void main(
  List<String> args, [
  _i4.SendPort? sendPort,
]) async {
  var result = await _i5.run(
    args,
    _builders,
  );
  sendPort?.send(result);
  _i6.exitCode = result;
}

我期望创建一个包含以下内容的fletch_example/lib/src/model/dao/sample_class.g.dart文件:

// ColumnProcessor works!

如果有人能给我指出正确的方向,那将是如此,难以置信的感激!

7bsow1i6

7bsow1i61#

GeneratorForAnnotation只对库中的顶级元素(如类、顶级字段或方法)运行,在您的示例中,@Column注解被添加到一个示例成员,该成员不会触发生成器。
如果可以的话,解决这个问题的最简单的方法是对生成器进行特殊的更改,以便字段上带有@Column注解的类也需要在类声明上添加注解。
或者,您也可以使用类似于下面的代码来考虑类成员中的列注解:

class ColumnGenerator extends Generator {
  static const _checker = TypeChecker.fromRuntime(annotations.Column);

  @override
  Future<String> generate(LibraryReader library, BuildStep buildStep) async {
    final values = <String>{};

    for (final classMember in library.classes) {
      for (final child in classMember.children) {
        final annotation = _checker.firstAnnotationOf(child);

        if (annotation != null) {
          values.add(await generateForAnnotatedElement(
              child, ConstantReader(annotation), buildStep));
        }
      }
    }

    return values.join('\n\n');
  }

  FutureOr<String> generateForAnnotatedElement(
    Element element,
    ConstantReader annotation,
    BuildStep buildStep,
  ) {
    return '// ColumnProcessor works!';
  }
}

相关问题