I am trying to create a code generation package within Flutter using the build_runner
and source_gen
packages. I've looked over numerous examples but cannot seem to find what is preventing my output files from being created. I know it's probably something stupid, but I've been trying for days and cannot seem to find the problem.
So far, I've got the following directory structure:
─┬ fletch
├── fletch_annotations
├── fletch_example
└── fletch_generator
fletch_annotations
has annotation classes like the following:
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,
});
}
In fletch_generator
, I have the following pubspec.yaml
file:
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
has corresponding model classes:
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'
')';
}
}
My build.yaml
file in fletch_generator
:
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
, also in fletch_generator
(in the lib
directory):
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');
And finally, the fletch_generator
definition for ColumnGenerator
:
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!';
}
}
In fletch_example
, I have a sample_class
that utilizes the Column
annotation:
`package:fletch_example/src/model/entity/sample_class.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,
});
}
As well as the appropriate dependencies in the pubspec.yaml
file for fletch_example
:
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
In my fletch_example
directory, I run the following commands:
flutter clean
flutter pub get
flutter packages pub run build_runner build --delete-conflicting-outputs
This generates the following console output:
[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)
It also creates the following fletch_example/.dart_tool/build/entrypoint/build.dart
file:
// 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;
}
My expectation is that a fletch_example/lib/src/model/dao/sample_class.g.dart
file would be created containing the following:
// ColumnProcessor works!
If anyone could point me in the right direction, it would be so, incredibly appreciated!