build method
Generates the outputs for a given BuildStep.
Implementation
@override
Future<void> build(BuildStep buildStep) async {
if (!await buildStep.resolver.isLibrary(buildStep.inputId)) return;
final lib = await buildStep.inputLibrary;
final reader = LibraryReader(lib);
final pages = reader.annotatedWith(_pageChecker);
if (pages.isEmpty) return;
for (final page in pages) {
final element = page.element;
if (element is! ClassElement) continue;
// Use getGetter to check if the class declares the getter
final componentsGetter = element.getGetter('components');
// Ensure it's not inherited from SparkPage (actually getGetter returns declared one primarily,
// but checking enclosingName is safe)
final hasComponents =
componentsGetter != null &&
componentsGetter.enclosingElement.name != 'SparkPage';
if (!hasComponents) continue;
final session = element.session;
if (session == null) continue;
final parsedLib = await session.getResolvedLibraryByElement(
element.library,
);
if (parsedLib is! ResolvedLibraryResult) continue;
MethodDeclaration? getterNode;
// Search all units for the getter declaration (avoiding Element.source usage)
for (final unitResult in parsedLib.units) {
for (final decl in unitResult.unit.declarations) {
if (decl is ClassDeclaration &&
decl.namePart.typeName.lexeme ==
componentsGetter.enclosingElement.name) {
for (final member in (decl.body as BlockClassBody).members) {
if (member is MethodDeclaration &&
member.isGetter &&
member.name.lexeme == 'components') {
getterNode = member;
break;
}
}
}
if (getterNode != null) break;
}
if (getterNode != null) break;
}
if (getterNode == null) continue;
final body = getterNode.body;
if (body is! ExpressionFunctionBody) continue;
final list = body.expression;
if (list is! ListLiteral) continue;
if (list.elements.isEmpty) continue;
final componentImports = <String>{};
final components = <MapEntry<String, String>>[];
for (final item in list.elements) {
final referencedClasses = _findReferencedClasses(item);
for (final componentElement in referencedClasses) {
final tagField = componentElement.getField('tag');
if (tagField == null || !tagField.isStatic) continue;
final constant = tagField.computeConstantValue();
if (constant == null) continue;
final tagValue = constant.toStringValue();
if (tagValue == null) continue;
// Use library identifier as import URI (definingCompilationUnit is missing)
final importUri = componentElement.library.identifier;
componentImports.add(importUri);
final name = componentElement.name;
if (name == null) continue;
components.add(MapEntry(tagValue, name));
}
}
if (components.isEmpty) continue;
final outputId = buildStep.allowedOutputs.single;
final content = _generateWebEntry(componentImports, components);
await buildStep.writeAsString(
outputId,
DartFormatter(
languageVersion: DartFormatter.latestLanguageVersion,
).format(content),
);
}
}