build method
Generates the outputs for a given BuildStep.
Implementation
@override
Future<void> build(BuildStep step) async {
assert(step.inputId.path == r'$lib$');
List<String> outLines = <String>[];
List<String> imports = <String>[];
List<ClassElement> allClasses = [];
List<ClassElement> foundParentOf = [];
Map<ClassElement, List<ClassElement>> childrenToParents = {};
Map<ClassElement, List<_ChildModelInfo>> childInfos = {};
await for (AssetId asset in step.findAssets($dartFilesInLib)) {
if (!await step.resolver.isLibrary(asset)) continue;
LibraryElement lib = await step.resolver.libraryFor(asset);
Iterable<ClassElement> classes = LibraryReader(lib).classes;
for (ClassElement cls in classes) {
if (!_hasModelCrudMixin(cls)) continue;
PropertyAccessorElement? childGetter = cls.lookUpGetter(
name: 'childModels',
library: cls.library,
);
if (childGetter == null) continue;
allClasses.add(cls);
AstNode? getterNode = await step.resolver.astNodeFor(
childGetter.firstFragment,
resolve: true,
);
if (getterNode is! MethodDeclaration) continue;
FunctionBody body = getterNode.body;
Expression? expr = switch (body) {
ExpressionFunctionBody(:final expression) => expression,
BlockFunctionBody(:final block) =>
block.statements.whereType<ReturnStatement>().first.expression,
_ => null,
};
if (expr is! ListLiteral) continue;
List<_ChildModelInfo> infos = _readFireModels(expr, cls.library);
childInfos[cls] = infos;
foundParentOf.addAll(infos.map((i) => i.element));
for (_ChildModelInfo info in infos) {
childrenToParents
.putIfAbsent(info.element, () => <ClassElement>[])
.add(cls);
}
}
}
List<Future<(String, String)>> work = [];
await for (AssetId asset in step.findAssets($dartFilesInLib)) {
if (!await step.resolver.isLibrary(asset)) continue;
LibraryElement lib = await step.resolver.libraryFor(asset);
Iterable<ClassElement> classes = LibraryReader(lib).classes;
for (ClassElement cls in classes) {
if (!_hasModelCrudMixin(cls)) continue;
if (!childInfos.containsKey(cls)) continue;
List<_ChildModelInfo> infos = childInfos[cls] ?? [];
imports.add("import '${cls.library.uri}';");
if ($artifactChecker.hasAnnotationOf(cls, throwOnUnresolved: false)) {
imports.add(
"import '${cls.library.uri.replace(path: "${cls.library.uri.pathSegments[0]}/gen/artifacts.gen.dart")}';",
);
}
work.add(_genCrudExtensions(
cls,
infos,
childrenToParents[cls] ?? [],
childrenToParents,
));
}
}
for ((String, String) o in await Future.wait(work)) {
imports.add(o.$1);
outLines.add(o.$2);
}
List<ClassElement> roots =
allClasses.where((c) => !foundParentOf.contains(c)).toList();
for (ClassElement i in roots) {
(String, String) o = _genRootCrudExtensions(i);
imports.add(o.$1);
outLines.add(o.$2);
}
AssetId out = AssetId(step.inputId.package, 'lib/gen/crud.gen.dart');
await step.writeAsString(
out,
'// GENERATED – do not modify.\n${(imports.join("\n").split("\n").map((i) => i.replaceAll("'", '"').trim()).toSet()..removeAll(["import '';", 'import "";'])).join("\n")}\n' +
outLines.join('\n'),
);
}