build method

  1. @override
Future build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
Future build(BuildStep buildStep) async {
  var contexts = <BuildContext?>[];
  LibraryReader lib;

  try {
    lib = LibraryReader(await buildStep.inputLibrary);
  } catch (_) {
    return;
  }

  var elements = <AnnotatedElement>[];

  try {
    elements = lib
        .annotatedWith(const TypeChecker.fromRuntime(Serializable))
        .toList();
  } catch (_) {
    // Ignore error in source_gen/build_runner that has no explanation
  }

  for (var element in elements) {
    if (element.element.kind != ElementKind.CLASS) {
      throw 'Only classes can be annotated with a @Serializable() annotation.';
    }

    var annotation = element.annotation;

    var serializers = annotation.peek('serializers')?.listValue ?? [];

    if (serializers.isEmpty) continue;

    // Check if TypeScript serializer is supported
    if (!serializers.any((s) => s.toIntValue() == Serializers.typescript)) {
      continue;
    }

    contexts.add(await buildContext(
        element.element as ClassElement,
        element.annotation,
        buildStep,
        buildStep.resolver,
        autoSnakeCaseNames != false));
  }

  if (contexts.isEmpty) return;

  var refs = <String>[];
  var buf = CodeBuffer(
    trailingNewline: true,
    sourceUrl: buildStep.inputId.uri,
  );

  buf.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND');

  // declare module `foo` {
  buf
    ..writeln("declare module '${buildStep.inputId.package}' {")
    ..indent();

  for (var ctx in contexts) {
    // interface Bar { ... }
    buf
      ..writeln('interface ${ctx!.modelClassNameRecase.pascalCase} {')
      ..indent();

    var ext = <CodeBuffer>[];

    for (var field in ctx.fields) {
      // Skip excluded fields
      if (ctx.excluded[field.name]?.canSerialize == false) continue;

      var alias = ctx.resolveFieldName(field.name);
      var typeScriptType = await compileToTypeScriptType(ctx, field.name,
          ctx.resolveSerializedFieldType(field.name), refs, ext, buildStep);

      // foo: string;
      if (!ctx.requiredFields.containsKey(field.name)) {
        if (alias != null) {
          alias += '?';
        }
      }
      buf.writeln('$alias: $typeScriptType;');
    }

    buf
      ..outdent()
      ..writeln('}');

    for (var b in ext) {
      b.copyInto(buf);
    }
  }

  buf
    ..outdent()
    ..writeln('}');
  var finalBuf = CodeBuffer();
  refs.forEach(finalBuf.writeln);
  buf.copyInto(finalBuf);

  await buildStep.writeAsString(
    buildStep.inputId.changeExtension('.d.ts'),
    finalBuf.toString(),
  );
}