build method

  1. @override
Future<void> build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
Future<void> build(BuildStep buildStep) async {
  final inputId = buildStep.inputId;
  if (inputId.path.endsWith(_generatedExtension)) return;
  if (!await buildStep.resolver.isLibrary(inputId)) return;

  // The trigger library imports the not-yet-generated output, so tolerate the
  // resulting unresolved import while looking for the annotation.
  final entryLibrary =
      await buildStep.resolver.libraryFor(inputId, allowSyntaxErrors: true);
  // The trigger annotation lives on a top-level `const previews` variable;
  // scan every top-level element kind to remain robust to where it's placed.
  final topLevel = <Element>[
    ...entryLibrary.classes,
    ...entryLibrary.enums,
    ...entryLibrary.mixins,
    ...entryLibrary.extensions,
    ...entryLibrary.extensionTypes,
    ...entryLibrary.typeAliases,
    ...entryLibrary.topLevelFunctions,
    ...entryLibrary.topLevelVariables,
    ...entryLibrary.getters,
    ...entryLibrary.setters,
  ];
  final trigger = topLevel.firstWhereOrNull(
    (e) => previewRegistryChecker.hasAnnotationOf(e, throwOnUnresolved: false),
  );
  if (trigger == null) return;

  // The generated symbol mirrors the annotated variable's name: an
  // `@PreviewRegistry() final myPreviews = $myPreviews;` trigger yields a
  // `$myPreviews` field. Falls back to `$previews` for an unnamed element.
  final triggerName = trigger.name;
  final registryName =
      '\$${triggerName == null || triggerName.isEmpty ? 'previews' : triggerName}';

  // Scan every library under lib/ for previews.
  final detected = <DetectedPreview>[];
  await for (final assetId in buildStep.findAssets(Glob('lib/**.dart'))) {
    if (assetId.path.endsWith(_generatedExtension)) continue;
    if (!await buildStep.resolver.isLibrary(assetId)) continue;
    final library = await buildStep.resolver.libraryFor(
      assetId,
      allowSyntaxErrors: true,
    );
    detected.addAll(detectPreviews(library));
  }

  final source = _generate(detected, registryName);
  await buildStep.writeAsString(
    inputId.changeExtension(_generatedExtension),
    source,
  );
}