I have a bunch of cells and a file that registers all of them at once, this works fine but i have to maintain this and remember to add the new entries every time, so i'm trying to create this file using code generation, i have my cells annotated with @cell and iterating over them with:
class CellRegisterGenerator extends GeneratorForAnnotation<CellAnnotation> {
@override
String generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) {
final visitor = ModelVisitor();
element.visitChildren(visitor);
final clazz = visitor.className;
final name = clazz.replaceAll("Cell", "");
final cellName = StringUtils.camelCaseToLowerUnderscore(name);
final builder = "${clazz[0].toLowerCase()}${clazz.substring(1)}Builder";
return '..registerCell("$cellName", builder: $builder)\n';
}
}
class ModelVisitor extends SimpleElementVisitor<void> {
late String className;
final fields = <String, dynamic>{};
@override
void visitConstructorElement(ConstructorElement element) {
final elementReturnType = element.type.returnType.toString();
className = elementReturnType.replaceFirst('*', '');
}
@override
void visitFieldElement(FieldElement element) {
final elementType = element.type.toString();
fields[element.name] = elementType.replaceFirst('*', '');
}
}
And a builder to generate the final file:
Builder generateCellRegister(BuilderOptions options) =>
SharedPartBuilder([CellRegisterGenerator()], 'cell');
Builder cellBuilder(BuilderOptions options) {
return CellBuilder(options);
}
const _partFiles = '.g.part';
const partIdRegExpLiteral = r'[A-Za-z_\d-]+';
class CellBuilder implements Builder {
CellBuilder(this.builderOptions);
final BuilderOptions builderOptions;
final _generatedFileName = 'lib/support/board_cell_builder_config.g.dart';
@override
Map<String, List<String>> get buildExtensions {
return {
r'$package$': [_generatedFileName],
//r'.dart': [_generatedFileName],
//r'.dart': [ '.g.dart' ],
};
}
@override
FutureOr<void> build(BuildStep buildStep) async {
final outputId = AssetId(
buildStep.inputId.package,
_generatedFileName,
);
final code = """
// GENERATED CODE - DO NOT MODIFY BY HAND
// GENERATED CODE - DO NOT MODIFY BY HAND
// GENERATED CODE - DO NOT MODIFY BY HAND
// GENERATED CODE - DO NOT MODIFY BY HAND
part of "cell_builder_config.dart";
class \$CellBuilderConfig {
void setup() {
final cells = CellBuilder.instance;
cells
Add code generated from CellRegisterGenerator here
;
}
}
""";
final formattedCode = DartFormatter().format(code);
await buildStep.writeAsString(outputId, formattedCode);
}
}
build.yaml
builders:
cell_builder:
import: "package:<app_name>/generators/cell_builder.dart"
builder_factories: [ "cellBuilder" ]
build_extensions: { ".dart": [ ".g.dart" ] }
auto_apply: root_package
build_to: source
applies_builders: [ "<app_name>:cell_register" ]
cell_register:
import: "package:<app_name>/generators/cell_builder.dart"
builder_factories: [ "generateCellRegister" ]
build_extensions: { ".dart": [ ".g.part" ] }
auto_apply: dependents
build_to: cache
runs_before: [ "<app_name>:cell_builder" ]
But i don't know how to connect them, i've read that i could generate the code from CellRegisterGenerator to cache and read it from the CellBuilder, but i can't find how...
I've tryed to tweak things on the build.yaml (build to source/cache), read the freezed, build_runner and src_gen to see how they work in search for information on how do this all work and or Streams to yield the results and write them to the builder...
It may very well be that the code doesn't make sense to what i'm trying to achieve, i'm trying to piece together every bit of information i find, if there's anything wrong, please do point it out