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 libraryElement = await buildStep.inputLibrary;
  final library = LibraryReader(libraryElement);

  try {
    final spec = SpecExtractor.extract(library);

    // ── Validate before generating ─────────────────────────────────────
    final issues = SpecValidator.validate(spec);
    for (final issue in issues) {
      if (issue.isError) {
        log.severe('nitrogen: ${buildStep.inputId.path}\n  $issue');
      } else {
        log.warning('nitrogen: ${buildStep.inputId.path}\n  $issue');
      }
    }
    if (issues.any((i) => i.isError)) {
      log.severe(
        'nitrogen: Aborting generation for ${buildStep.inputId.path} due to validation errors above.',
      );
      return;
    }

    // We can use buildStep.allowedOutputs to find the EXACT output paths
    // generated by build_runner based on our map.
    final outputs = buildStep.allowedOutputs;

    for (final outId in outputs) {
      if (outId.path.endsWith('.g.dart')) {
        final rawCode = DartFfiGenerator.generate(spec);
        String formattedCode;
        try {
          formattedCode = DartFormatter().format(rawCode);
        } catch (e) {
          log.warning('nitrogen: Could not format ${outId.path}:\n$e');
          formattedCode = rawCode;
        }
        await buildStep.writeAsString(outId, formattedCode);
      } else if (outId.path.endsWith('.bridge.g.kt')) {
        await buildStep.writeAsString(outId, KotlinGenerator.generate(spec));
      } else if (outId.path.endsWith('.bridge.g.swift')) {
        await buildStep.writeAsString(outId, SwiftGenerator.generate(spec));
      } else if (outId.path.endsWith('.bridge.g.h')) {
        await buildStep.writeAsString(outId, CppHeaderGenerator.generate(spec));
      } else if (outId.path.endsWith('.bridge.g.cpp')) {
        await buildStep.writeAsString(outId, CppBridgeGenerator.generate(spec));
      } else if (outId.path.endsWith('.CMakeLists.g.txt')) {
        await buildStep.writeAsString(outId, CMakeGenerator.generate(spec));
        // ── NativeImpl.cpp outputs ─────────────────────────────────────
      } else if (outId.path.endsWith('.native.g.h')) {
        await buildStep.writeAsString(outId, CppInterfaceGenerator.generate(spec));
      } else if (outId.path.endsWith('.mock.g.h')) {
        await buildStep.writeAsString(outId, CppMockGenerator.generateMockHeader(spec));
      } else if (outId.path.endsWith('.test.g.cpp')) {
        await buildStep.writeAsString(outId, CppMockGenerator.generateTestStarter(spec));
      }
    }
  } catch (e, st) {
    log.warning('nitrogen: Could not process ${buildStep.inputId}:\n$e\n$st');
  }
}