buildSchema method

FutureOr<void> buildSchema(
  1. BuildStep buildStep,
  2. AssetId schemaId,
  3. Glob generatedFiles,
  4. List<Glob> excludeFiles,
)

Implementation

FutureOr<void> buildSchema(BuildStep buildStep, AssetId schemaId,
    Glob generatedFiles, List<Glob> excludeFiles) async {
  /// BuiltValue classes with serializers. These will be added automatically
  /// using `@SerializersFor`.
  final builtClasses =
      SplayTreeSet<ClassElement>((a, b) => a.name.compareTo(b.name));

  /// Non BuiltValue classes with serializers (i.e. inline fragment classes).
  /// These need to be added manually since `@SerializersFor` only recognizes
  /// BuiltValue classes.
  final nonBuiltClasses =
      SplayTreeSet<ClassElement>((a, b) => a.name.compareTo(b.name));

  final excludeFileIds = <String, AssetId>{};
  for (final excludeGlob in excludeFiles) {
    await for (final fileAssetId in buildStep.findAssets(excludeGlob)) {
      excludeFileIds[fileAssetId.path] = fileAssetId;
    }
  }

  await for (final input in buildStep.findAssets(generatedFiles)) {
    if (excludeFileIds.containsKey(input.path)) continue;
    final lib = await buildStep.resolver.libraryFor(input);
    final classes = extractClassesToGenerateSerializersFor(lib);
    builtClasses.addAll(classes.builtClasses);
    nonBuiltClasses.addAll(classes.nonBuiltClasses);
  }

  final additionalSerializers = <Expression>{
    // GraphQL Operation serializer
    refer(
      'OperationSerializer',
      'package:gql_code_builder_serializers/gql_code_builder_serializers.dart',
    ).call([]),
    // User-defined custom serializers
    ...config.customSerializers.map((ref) => ref.call([])),
    // Serializers from data classes that aren't caught by `@SerializersFor`
    ...nonBuiltClasses.map<Expression>(
      (c) => refer(c.name, c.source.uri.toString()).property('serializer'),
    ),
  };

  // if the schema is defined in a different package
  // we need to import the serializers from that package
  // and add them to the serializers of this package
  final isExternalSchema = schemaId.package != buildStep.inputId.package;

  final externalSerializersExpression = isExternalSchema
      ? refer('serializers',
              _externalSchemaSerializersImport(schemaId, config))
          .property('serializers')
      : null;

  if (isExternalSchema) {
    final externalSchemaId =
        outputAssetId(schemaId, schemaExtension, config.outputDir);

    final externalSchemaLibrary =
        await buildStep.resolver.libraryFor(externalSchemaId);

    final externalSchemaClasses =
        extractClassesToGenerateSerializersFor(externalSchemaLibrary);

    builtClasses.addAll(externalSchemaClasses.builtClasses);
    nonBuiltClasses.addAll(externalSchemaClasses.nonBuiltClasses);
  }

  final library = buildSerializerLibrary(
    builtClasses,
    outputFileName.replaceFirst('.gql.dart', '.gql.g.dart'),
    additionalSerializers,
    externalSerializers: externalSerializersExpression,
  );

  final allocator = PickAllocator(doNotPick: [
    'package:built_value/serializer.dart',
  ], include: [
    'package:built_collection/built_collection.dart',
    'package:ferry_exec/ferry_exec.dart',
    ...config.typeOverrides.values.map((ref) => ref.url).whereType<String>(),
  ], aliasedImports: {
    if (isExternalSchema)
      _externalSchemaSerializersImport(schemaId, config):
          '_\$external_serializers',
  });

  final outputId = AssetId(
    buildStep.inputId.package,
    p.joinAll(pathSegments(schemaId)),
  );

  await writeDocument(outputId, library, allocator, buildStep);
}