Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for serialize_nulls build config option #403

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions codegen/end_to_end_test/test/operation/variables_test.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import "package:test/test.dart";

import 'package:end_to_end_test/graphql/__generated__/schema.schema.gql.dart';
import 'package:end_to_end_test/variables/__generated__/human_with_args.var.gql.dart';
import 'package:end_to_end_test/variables/__generated__/create_review.var.gql.dart';
import 'package:end_to_end_test/variables/__generated__/human_with_args.var.gql.dart';
import "package:test/test.dart";

void main() {
group("Basic Args", () {
Expand Down
3 changes: 1 addition & 2 deletions codegen/end_to_end_test/test/schema/input_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import "package:test/test.dart";

import 'package:end_to_end_test/graphql/__generated__/schema.schema.gql.dart';
import "package:test/test.dart";

void main() {
group("Inputs", () {
Expand Down
7 changes: 3 additions & 4 deletions codegen/end_to_end_test/test/schema/scalars_test.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import "package:test/test.dart";

import 'package:end_to_end_test/custom_field.dart';
import 'package:end_to_end_test/custom_field_serializer.dart';
import 'package:end_to_end_test/graphql/__generated__/schema.schema.gql.dart';
import 'package:end_to_end_test/graphql/__generated__/serializers.gql.dart';
import 'package:end_to_end_test/scalars/__generated__/review_with_date.data.gql.dart';
import 'package:end_to_end_test/scalars/__generated__/review_with_date.var.gql.dart';
import 'package:end_to_end_test/custom_field.dart';
import 'package:end_to_end_test/custom_field_serializer.dart';
import "package:test/test.dart";

void main() {
group("Custom scalars from non-standard dart types", () {
Expand Down
14 changes: 14 additions & 0 deletions codegen/gql_build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ new enum values are added to the schema and the client has not updated to the ne
`global_enum_fallbacks`: \[bool\] Add a generated fallback value for each enum value (except for ones that have a custom fallback value specified in the enum_fallbacks map).
Defaults to false.

`when_extensions`: [Map\] whether to enable the `when`/`maybeWhen` extension on the generated data classes
from inline fragment spreads with type conditions.
Supported keys are `when` and `maybeWhen`, and the values are booleans indicating whether to enable
generation of the extension method not.


Example:

```yaml
when_extensions:
when: true # enable the `when` extension method
maybeWhen: true # enable the `maybeWhen` extension method
```

Example:

```yaml
Expand Down
31 changes: 15 additions & 16 deletions codegen/gql_build/lib/src/schema_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "dart:async";

import "package:build/build.dart";
import "package:code_builder/code_builder.dart";
import "package:gql_build/src/allocators/gql_allocator.dart";
import "package:gql_code_builder/schema.dart";
import "package:path/path.dart";

Expand All @@ -14,11 +15,8 @@ class SchemaBuilder implements Builder {
final EnumFallbackConfig enumFallbackConfig;
final bool generatePossibleTypesMap;

SchemaBuilder(
this.typeOverrides,
this.enumFallbackConfig,
this.generatePossibleTypesMap,
);
SchemaBuilder(this.typeOverrides, this.enumFallbackConfig,
this.generatePossibleTypesMap);

@override
Map<String, List<String>> get buildExtensions => {
Expand All @@ -34,19 +32,20 @@ class SchemaBuilder implements Builder {
.uri
.path;

final library = buildSchemaLibrary(
doc,
basename(generatedPartUrl),
typeOverrides,
enumFallbackConfig,
generatePossibleTypesMap: generatePossibleTypesMap,
final schemaUrl =
outputAssetId(buildStep.inputId, schemaExtension).uri.toString();
final allocator = GqlAllocator(
buildStep.inputId.uri.toString(),
outputAssetId(buildStep.inputId, schemaExtension).uri.toString(),
schemaUrl,
);

final library = buildSchemaLibrary(
doc, basename(generatedPartUrl), typeOverrides, enumFallbackConfig,
generatePossibleTypesMap: generatePossibleTypesMap,
allocator: allocator);

return writeDocument(
library,
buildStep,
schemaExtension,
outputAssetId(buildStep.inputId, schemaExtension).uri.toString(),
);
library, buildStep, schemaExtension, schemaUrl, allocator);
}
}
16 changes: 9 additions & 7 deletions codegen/gql_build/lib/src/serializer_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ class SerializerBuilder implements Builder {

@override
FutureOr<void> build(BuildStep buildStep) async {
final allocator = PickAllocator(
doNotPick: ["package:built_value/serializer.dart"],
include: [
"package:built_collection/built_collection.dart",
...typeOverrides.values.map((ref) => ref.url).whereType<String>()
],
);

/// BuiltValue classes with serializers. These will be added automatically
/// using `@SerializersFor`.
final builtClasses =
Expand Down Expand Up @@ -102,13 +110,7 @@ class SerializerBuilder implements Builder {
);

final _emitter = DartEmitter(
allocator: PickAllocator(
doNotPick: ["package:built_value/serializer.dart"],
include: [
"package:built_collection/built_collection.dart",
...typeOverrides.values.map((ref) => ref.url).whereType<String>()
],
),
allocator: allocator,
orderDirectives: true,
useNullSafetySyntax: true,
);
Expand Down
13 changes: 8 additions & 5 deletions codegen/gql_build/lib/src/utils/writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ Future<void> writeDocument(
BuildStep buildStep,
String extension, [
String? schemaUrl,
Allocator? allocator,
]) {
if (library.body.isEmpty) return Future.value(null);

allocator ??= GqlAllocator(
buildStep.inputId.uri.toString(),
outputAssetId(buildStep.inputId, extension).uri.toString(),
schemaUrl,
);

final generatedAsset = outputAssetId(buildStep.inputId, extension);

final genSrc = _dartfmt.format("${library.accept(
DartEmitter(
allocator: GqlAllocator(
buildStep.inputId.uri.toString(),
generatedAsset.uri.toString(),
schemaUrl,
),
allocator: allocator,
orderDirectives: true,
useNullSafetySyntax: true,
),
Expand Down
17 changes: 11 additions & 6 deletions codegen/gql_build/lib/src/var_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "dart:async";

import "package:build/build.dart";
import "package:code_builder/code_builder.dart";
import "package:gql_build/src/allocators/gql_allocator.dart";
import "package:gql_code_builder/var.dart";
import "package:path/path.dart";

Expand Down Expand Up @@ -34,18 +35,22 @@ class VarBuilder implements Builder {
.uri
.path;

final library = buildVarLibrary(
doc,
addTypenames(schema),
basename(generatedPartUrl),
typeOverrides,
final schemaUrl = outputAssetId(schemaId, schemaExtension).uri.toString();
final allocator = GqlAllocator(
buildStep.inputId.uri.toString(),
outputAssetId(buildStep.inputId, schemaExtension).uri.toString(),
schemaUrl,
);

final library = buildVarLibrary(doc, addTypenames(schema),
basename(generatedPartUrl), typeOverrides, allocator);

return writeDocument(
library,
buildStep,
varExtension,
outputAssetId(schemaId, schemaExtension).uri.toString(),
schemaUrl,
allocator,
);
}
}
11 changes: 4 additions & 7 deletions codegen/gql_code_builder/lib/schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ import "package:gql_code_builder/src/utils/possible_types.dart";

export "package:gql_code_builder/src/config/enum_fallback_config.dart";

Library buildSchemaLibrary(
SourceNode schemaSource,
String partUrl,
Map<String, Reference> typeOverrides,
EnumFallbackConfig enumFallbackConfig, {
bool generatePossibleTypesMap = false,
}) {
Library buildSchemaLibrary(SourceNode schemaSource, String partUrl,
Map<String, Reference> typeOverrides, EnumFallbackConfig enumFallbackConfig,
{bool generatePossibleTypesMap = false, Allocator? allocator}) {
final lib = buildSchema(
schemaSource,
typeOverrides,
enumFallbackConfig,
allocator ?? Allocator(),
) as Library;

final Code? possibleTypes;
Expand Down
10 changes: 6 additions & 4 deletions codegen/gql_code_builder/lib/src/built_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Class builtClass({
Map<String, Expression>? initializers,
Map<String, SourceSelections> superclassSelections = const {},
List<Method> methods = const [],
bool hasCustomSerializer = false,
}) {
final className = builtClassName(name);
return Class(
Expand Down Expand Up @@ -76,10 +77,11 @@ Class builtClass({
).code,
),
if (getters != null) ...getters,
// Serlialization methods
buildSerializerGetter(className).rebuild(
(b) => b..body = Code("_\$${toCamelCase(className)}Serializer"),
),
// Serialization methods
if (!hasCustomSerializer)
buildSerializerGetter(className).rebuild(
(b) => b..body = Code("_\$${toCamelCase(className)}Serializer"),
),
buildToJsonGetter(
className,
isOverride: superclassSelections.isNotEmpty,
Expand Down
3 changes: 0 additions & 3 deletions codegen/gql_code_builder/lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ Reference _typeRef(TypeNode type, Map<String, Reference> typeMap) {
(b) => b
..url = ref.url
..symbol = ref.symbol

/// TODO: remove `inList` check
/// https://github.com/google/built_value.dart/issues/1011#issuecomment-804843573
..isNullable = !type.isNonNull,
);
} else if (type is ListTypeNode) {
Expand Down
85 changes: 42 additions & 43 deletions codegen/gql_code_builder/lib/src/schema.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "package:code_builder/code_builder.dart";
import "package:gql/ast.dart";
import "package:gql_code_builder/var.dart";

import "./schema/enum.dart";
import "./schema/input.dart";
Expand All @@ -12,69 +13,67 @@ Spec? buildSchema(
SourceNode schemaSource,
Map<String, Reference> typeOverrides,
EnumFallbackConfig enumFallbackConfig,
Allocator allocator,
) =>
schemaSource.document.accept(
_SchemaBuilderVisitor(
schemaSource,
typeOverrides,
enumFallbackConfig,
),
);
schemaSource.document
.accept(
_SchemaBuilderVisitor(
schemaSource,
typeOverrides,
enumFallbackConfig,
allocator,
),
)
?.first;

class _SchemaBuilderVisitor extends SimpleVisitor<Spec?> {
class _SchemaBuilderVisitor extends SimpleVisitor<List<Spec>?> {
final SourceNode schemaSource;
final Map<String, Reference> typeOverrides;
final EnumFallbackConfig enumFallbackConfig;
final Allocator allocator;

_SchemaBuilderVisitor(
this.schemaSource,
this.typeOverrides,
this.enumFallbackConfig,
);

Spec? _acceptOne(
Node? node,
) =>
node != null ? node.accept(this) : literalNull;

List<Spec?> _acceptMany(
List<Node> nodes,
) =>
nodes.map(_acceptOne).toList(
growable: false,
);
_SchemaBuilderVisitor(this.schemaSource, this.typeOverrides,
this.enumFallbackConfig, this.allocator);

@override
Spec visitDocumentNode(
List<Spec> visitDocumentNode(
DocumentNode node,
) =>
Library(
(b) => b.body.addAll(
_acceptMany(node.definitions).whereType<Spec>(),
),
);
[
Library(
(b) => b.body.addAll(
node.definitions.expand(
(node) => node.accept(this) ?? [],
),
),
)
];

@override
Spec visitInputObjectTypeDefinitionNode(
List<Spec> visitInputObjectTypeDefinitionNode(
InputObjectTypeDefinitionNode node,
) =>
buildInputClass(
node,
schemaSource,
typeOverrides,
);
) {
final inputClass = buildInputClass(
node,
schemaSource,
typeOverrides,
);
final serializer = nullAwareJsonSerializerClass(
inputClass, allocator, schemaSource, typeOverrides);
return [inputClass, serializer];
}

@override
Spec? visitScalarTypeDefinitionNode(
List<Spec> visitScalarTypeDefinitionNode(
ScalarTypeDefinitionNode node,
) =>
typeOverrides.containsKey(node.name.value)
? null
: buildScalarClass(node);
? []
: [buildScalarClass(node)];

@override
Spec visitEnumTypeDefinitionNode(
List<Spec> visitEnumTypeDefinitionNode(
EnumTypeDefinitionNode node,
) =>
buildEnumClass(node, enumFallbackConfig);
[buildEnumClass(node, enumFallbackConfig)];
}
Loading