From d581d4b6abff8bf9a37779c3bd901f1c28d3e827 Mon Sep 17 00:00:00 2001 From: vasilich Date: Mon, 21 Jun 2021 19:51:45 +0300 Subject: [PATCH] performance --- CHANGELOG.md | 4 + lib/generator.dart | 20 ++-- lib/visitor/canonical_visitor.dart | 112 ++++++++++-------- pubspec.yaml | 10 +- .../ast_schema/input_types_test.dart | 52 ++++---- 5 files changed, 107 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30bb0f29..7c1353db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 7.0.0-beta.16 + +- lazy canonical visitors + ## 7.0.0-beta.15 - Update build_runner version in examples diff --git a/lib/generator.dart b/lib/generator.dart index a081d230..0e48c102 100644 --- a/lib/generator.dart +++ b/lib/generator.dart @@ -179,14 +179,14 @@ Iterable generateDefinitions( final rootTypeName = (schemaVisitor.schemaDefinitionNode?.operationTypes ?? []) - .firstWhereOrNull((e) => e.operation == operation.type) - ?.type - .name - .value ?? + .firstWhereOrNull((e) => e.operation == operation.type) + ?.type + .name + .value ?? suffix; final TypeDefinitionNode parentType = - objectVisitor.getByName(rootTypeName)!; + objectVisitor.getByName(rootTypeName)!; final name = QueryName.fromPath( path: createPathName([ @@ -222,11 +222,13 @@ Iterable generateDefinitions( operationName: operationName, document: documentDefinitions, classes: [ - ...canonicalVisitor.enums - .where((e) => context.usedEnums.contains(e.name)), + ...context.usedEnums + .map((e) => canonicalVisitor.enums[e.name]?.call()) + .whereType(), ...visitor.context.generatedClasses, - ...canonicalVisitor.inputObjects - .where((i) => context.usedInputObjects.contains(i.name)), + ...context.usedInputObjects + .map((e) => canonicalVisitor.inputObjects[e.name]?.call()) + .whereType(), ], inputs: visitor.context.inputsClasses, generateHelpers: options.generateHelpers, diff --git a/lib/visitor/canonical_visitor.dart b/lib/visitor/canonical_visitor.dart index 73646ebb..55b7d387 100644 --- a/lib/visitor/canonical_visitor.dart +++ b/lib/visitor/canonical_visitor.dart @@ -7,6 +7,12 @@ import 'package:artemis/generator/helpers.dart'; import 'package:artemis/generator/graphql_helpers.dart' as gql; import 'package:gql/ast.dart'; +/// class definition lazy generator +typedef ClassDefinitionGenerator = ClassDefinition Function(); + +/// class definition lazy generator +typedef EnumDefinitionGenerator = EnumDefinition Function(); + /// Visits canonical types Enums and InputObjects class CanonicalVisitor extends RecursiveVisitor { /// Constructor @@ -18,72 +24,76 @@ class CanonicalVisitor extends RecursiveVisitor { final Context context; /// List of visited input objects - final List inputObjects = []; + final Map inputObjects = {}; /// List of visited enums - final List enums = []; + final Map enums = {}; @override void visitEnumTypeDefinitionNode(EnumTypeDefinitionNode node) { - final enumName = EnumName(name: node.name.value); + enums[node.name.value] = () { + final enumName = EnumName(name: node.name.value); - final nextContext = context.sameTypeWithNoPath( - alias: enumName, - ofUnion: Nullable(null), - ); + final nextContext = context.sameTypeWithNoPath( + alias: enumName, + ofUnion: Nullable(null), + ); - logFn(context, nextContext.align, '-> Enum'); - logFn(context, nextContext.align, - '<- Generated enum ${enumName.namePrintable}.'); + logFn(context, nextContext.align, '-> Enum'); + logFn(context, nextContext.align, + '<- Generated enum ${enumName.namePrintable}.'); - enums.add(EnumDefinition( - name: enumName, - values: node.values - .map((ev) => EnumValueDefinition( - name: EnumValueName(name: ev.name.value), - annotations: proceedDeprecated(ev.directives), - )) - .toList() - ..add(ARTEMIS_UNKNOWN), - )); + return EnumDefinition( + name: enumName, + values: node.values + .map((ev) => EnumValueDefinition( + name: EnumValueName(name: ev.name.value), + annotations: proceedDeprecated(ev.directives), + )) + .toList() + ..add(ARTEMIS_UNKNOWN), + ); + }; } @override void visitInputObjectTypeDefinitionNode(InputObjectTypeDefinitionNode node) { - final name = ClassName(name: node.name.value); - final nextContext = context.sameTypeWithNoPath( - alias: name, - ofUnion: Nullable(null), - ); + inputObjects[node.name.value] = () { + final name = ClassName(name: node.name.value); + final nextContext = context.sameTypeWithNoPath( + alias: name, + ofUnion: Nullable(null), + ); - logFn(context, nextContext.align, '-> Input class'); - logFn(context, nextContext.align, - '┌ ${nextContext.path}[${node.name.value}]'); - final properties = []; + logFn(context, nextContext.align, '-> Input class'); + logFn(context, nextContext.align, + '┌ ${nextContext.path}[${node.name.value}]'); + final properties = []; - properties.addAll(node.fields.map((i) { - final nextType = gql.getTypeByName(nextContext.schema, i.type); - return createClassProperty( - fieldName: ClassPropertyName(name: i.name.value), - context: nextContext.nextTypeWithNoPath( - nextType: node, - nextClassName: ClassName(name: nextType.name.value), - nextFieldName: ClassName(name: i.name.value), - ofUnion: Nullable(null), - ), - markAsUsed: false, - ); - })); + properties.addAll(node.fields.map((i) { + final nextType = gql.getTypeByName(nextContext.schema, i.type); + return createClassProperty( + fieldName: ClassPropertyName(name: i.name.value), + context: nextContext.nextTypeWithNoPath( + nextType: node, + nextClassName: ClassName(name: nextType.name.value), + nextFieldName: ClassName(name: i.name.value), + ofUnion: Nullable(null), + ), + markAsUsed: false, + ); + })); - logFn(context, nextContext.align, - '└ ${nextContext.path}[${node.name.value}]'); - logFn(context, nextContext.align, - '<- Generated input class ${name.namePrintable}.'); + logFn(context, nextContext.align, + '└ ${nextContext.path}[${node.name.value}]'); + logFn(context, nextContext.align, + '<- Generated input class ${name.namePrintable}.'); - inputObjects.add(ClassDefinition( - isInput: true, - name: name, - properties: properties, - )); + return ClassDefinition( + isInput: true, + name: name, + properties: properties, + ); + }; } } diff --git a/pubspec.yaml b/pubspec.yaml index 66ce2c78..6ea4fe06 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: artemis -version: 7.0.0-beta.15 +version: 7.0.0-beta.16 description: Build dart types from GraphQL schemas and queries (using Introspection Query). homepage: https://github.com/comigor/artemis @@ -13,7 +13,7 @@ dependencies: build: ^2.0.2 collection: ^1.15.0 dart_style: ^2.0.1 - equatable: ^2.0.2 + equatable: ^2.0.3 glob: ^2.0.1 gql_code_builder: ^0.2.0 gql_dedupe_link: ^2.0.0 @@ -25,7 +25,7 @@ dependencies: json_annotation: ^4.0.1 path: ^1.8.0 recase: ^4.0.0 - source_gen: ^1.0.1 + source_gen: ^1.0.2 yaml: ^3.1.0 dev_dependencies: @@ -34,7 +34,7 @@ dev_dependencies: build_test: ^2.1.0 json_serializable: ^4.1.3 build_resolvers: ^2.0.3 - pedantic: ^1.11.0 - test: ^1.17.5 + pedantic: ^1.11.1 + test: ^1.17.8 logging: ^1.0.1 diff --git a/test/query_generator/ast_schema/input_types_test.dart b/test/query_generator/ast_schema/input_types_test.dart index 66e3f40b..c2ae60ad 100644 --- a/test/query_generator/ast_schema/input_types_test.dart +++ b/test/query_generator/ast_schema/input_types_test.dart @@ -103,17 +103,6 @@ final LibraryDefinition libraryDefinition = factoryPossibilities: {}, typeNameField: ClassPropertyName(name: r'__typename'), isInput: false), - ClassDefinition( - name: ClassName(name: r'OtherObjectInput'), - properties: [ - ClassProperty( - type: TypeName(name: r'String', isNonNull: true), - name: ClassPropertyName(name: r'id'), - isResolveType: false) - ], - factoryPossibilities: {}, - typeNameField: ClassPropertyName(name: r'__typename'), - isInput: true), ClassDefinition( name: ClassName(name: r'CreateThingInput'), properties: [ @@ -135,6 +124,17 @@ final LibraryDefinition libraryDefinition = ], factoryPossibilities: {}, typeNameField: ClassPropertyName(name: r'__typename'), + isInput: true), + ClassDefinition( + name: ClassName(name: r'OtherObjectInput'), + properties: [ + ClassProperty( + type: TypeName(name: r'String', isNonNull: true), + name: ClassPropertyName(name: r'id'), + isResolveType: false) + ], + factoryPossibilities: {}, + typeNameField: ClassPropertyName(name: r'__typename'), isInput: true) ], inputs: [ @@ -207,21 +207,6 @@ class CreateThing$MutationRoot extends JsonSerializable with EquatableMixin { Map toJson() => _$CreateThing$MutationRootToJson(this); } -@JsonSerializable(explicitToJson: true) -class OtherObjectInput extends JsonSerializable with EquatableMixin { - OtherObjectInput({required this.id}); - - factory OtherObjectInput.fromJson(Map json) => - _$OtherObjectInputFromJson(json); - - late String id; - - @override - List get props => [id]; - @override - Map toJson() => _$OtherObjectInputToJson(this); -} - @JsonSerializable(explicitToJson: true) class CreateThingInput extends JsonSerializable with EquatableMixin { CreateThingInput({required this.clientId, this.message, this.shares}); @@ -240,4 +225,19 @@ class CreateThingInput extends JsonSerializable with EquatableMixin { @override Map toJson() => _$CreateThingInputToJson(this); } + +@JsonSerializable(explicitToJson: true) +class OtherObjectInput extends JsonSerializable with EquatableMixin { + OtherObjectInput({required this.id}); + + factory OtherObjectInput.fromJson(Map json) => + _$OtherObjectInputFromJson(json); + + late String id; + + @override + List get props => [id]; + @override + Map toJson() => _$OtherObjectInputToJson(this); +} ''';