diff --git a/codegen/gql_build/lib/gql_build.dart b/codegen/gql_build/lib/gql_build.dart index 718bee0f..9e8efd8c 100644 --- a/codegen/gql_build/lib/gql_build.dart +++ b/codegen/gql_build/lib/gql_build.dart @@ -19,12 +19,14 @@ Builder dataBuilder( BuilderOptions options, ) => DataBuilder( - AssetId.parse( - options.config["schema"] as String, - ), - (options.config["add_typenames"] ?? true) as bool, - typeOverrideMap(options.config["type_overrides"]), - whenExtensionConfig: whenExtensionConfig(options.config)); + AssetId.parse( + options.config["schema"] as String, + ), + (options.config["add_typenames"] ?? true) as bool, + typeOverrideMap(options.config["type_overrides"]), + whenExtensionConfig: whenExtensionConfig(options.config), + dataClassConfig: dataClassConfig(options.config), + ); /// Builds GraphQL type-safe request builder Builder reqBuilder( diff --git a/codegen/gql_build/lib/src/data_builder.dart b/codegen/gql_build/lib/src/data_builder.dart index 641c17a3..f81b0fff 100644 --- a/codegen/gql_build/lib/src/data_builder.dart +++ b/codegen/gql_build/lib/src/data_builder.dart @@ -14,6 +14,7 @@ class DataBuilder implements Builder { final bool addTypenames; final Map typeOverrides; final InlineFragmentSpreadWhenExtensionConfig whenExtensionConfig; + final DataClassConfig dataClassConfig; DataBuilder( this.schemaId, @@ -23,6 +24,9 @@ class DataBuilder implements Builder { generateWhenExtensionMethod: false, generateMaybeWhenExtensionMethod: false, ), + this.dataClassConfig = const DataClassConfig( + reuseFragments: false, + ), }); @override @@ -41,11 +45,13 @@ class DataBuilder implements Builder { .path; final library = buildDataLibrary( - addTypenames ? introspection.addTypenames(doc) : doc, - introspection.addTypenames(schema), - basename(generatedPartUrl), - typeOverrides, - whenExtensionConfig); + addTypenames ? introspection.addTypenames(doc) : doc, + introspection.addTypenames(schema), + basename(generatedPartUrl), + typeOverrides, + whenExtensionConfig, + dataClassConfig, + ); return writeDocument( library, diff --git a/codegen/gql_build/lib/src/utils/config.dart b/codegen/gql_build/lib/src/utils/config.dart index 4eddc5ec..6afbfe2b 100644 --- a/codegen/gql_build/lib/src/utils/config.dart +++ b/codegen/gql_build/lib/src/utils/config.dart @@ -42,6 +42,10 @@ EnumFallbackConfig enumFallbackConfig(Map config) => fallbackValueMap: enumFallbackMap(config["enum_fallbacks"]), ); +DataClassConfig dataClassConfig(Map config) => DataClassConfig( + reuseFragments: config["reuse_fragments"] == true, + ); + InlineFragmentSpreadWhenExtensionConfig whenExtensionConfig( Map config) { final whenYamlConfig = config["when_extensions"] as YamlMap?; diff --git a/codegen/gql_code_builder/lib/data.dart b/codegen/gql_code_builder/lib/data.dart index b64d6607..e14186a7 100644 --- a/codegen/gql_code_builder/lib/data.dart +++ b/codegen/gql_code_builder/lib/data.dart @@ -1,11 +1,14 @@ import "package:built_collection/built_collection.dart"; import "package:code_builder/code_builder.dart"; import "package:gql/ast.dart"; +import "package:gql_code_builder/src/common.dart"; +import "package:gql_code_builder/src/config/data_class_config.dart"; import "package:gql_code_builder/src/config/when_extension_config.dart"; import "./source.dart"; import "./src/operation/data.dart"; +export "package:gql_code_builder/src/config/data_class_config.dart"; export "package:gql_code_builder/src/config/when_extension_config.dart"; Library buildDataLibrary( @@ -18,7 +21,15 @@ Library buildDataLibrary( generateWhenExtensionMethod: false, generateMaybeWhenExtensionMethod: false, ), + DataClassConfig dataClassConfig = const DataClassConfig( + reuseFragments: false, + ), ]) { + final fragmentMap = _fragmentMap(docSource); + final dataClassAliasMap = dataClassConfig.reuseFragments + ? _dataClassAliasMap(docSource, fragmentMap) + : {}; + final operationDataClasses = docSource.document.definitions .whereType() .expand( @@ -28,6 +39,8 @@ Library buildDataLibrary( schemaSource, typeOverrides, whenExtensionConfig, + fragmentMap, + dataClassAliasMap, ), ) .toList(); @@ -41,6 +54,8 @@ Library buildDataLibrary( schemaSource, typeOverrides, whenExtensionConfig, + fragmentMap, + dataClassAliasMap, ), ) .toList(); @@ -54,3 +69,140 @@ Library buildDataLibrary( ]), ); } + +Map _fragmentMap(SourceNode source) => { + for (var def + in source.document.definitions.whereType()) + def.name.value: SourceSelections( + url: source.url, + selections: def.selectionSet.selections, + ), + for (var import in source.imports) ..._fragmentMap(import) + }; + +Map _dataClassAliasMap( + SourceNode source, Map fragmentMap, + [Map? aliasMap, Set? visitedSource]) { + aliasMap ??= {}; + visitedSource ??= {}; + + source.imports.forEach((s) { + if (!visitedSource!.contains(source.url)) { + visitedSource.add(source.url); + _dataClassAliasMap(s, fragmentMap, aliasMap); + } + }); + + for (final def + in source.document.definitions.whereType()) { + _dataClassAliasMapDFS( + typeRefPrefix: builtClassName("${def.name!.value}Data"), + getAliasTypeName: (fragmentName) => "${builtClassName(fragmentName)}Data", + selections: def.selectionSet.selections, + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + } + + for (final def + in source.document.definitions.whereType()) { + _dataClassAliasMapDFS( + typeRefPrefix: builtClassName(def.name.value), + getAliasTypeName: builtClassName, + selections: def.selectionSet.selections, + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + _dataClassAliasMapDFS( + typeRefPrefix: builtClassName("${def.name.value}Data"), + getAliasTypeName: (fragmentName) => "${builtClassName(fragmentName)}Data", + selections: def.selectionSet.selections, + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + } + + return aliasMap; +} + +void _dataClassAliasMapDFS({ + required String typeRefPrefix, + required String Function(String fragmentName) getAliasTypeName, + required List selections, + required Map fragmentMap, + required Map aliasMap, +}) { + if (selections.isEmpty) return; + + // flatten selections to extract untouched fragments while visiting children. + final shrunkenSelections = + shrinkSelections(mergeSelections(selections, fragmentMap), fragmentMap); + + // alias single fragment and finish + final selectionsWithoutTypename = shrunkenSelections + .where((s) => !(s is FieldNode && s.name.value == "__typename")); + if (selectionsWithoutTypename.length == 1 && + selectionsWithoutTypename.first is FragmentSpreadNode) { + final node = selectionsWithoutTypename.first as FragmentSpreadNode; + final fragment = fragmentMap[node.name.value]; + final fragmentTypeName = getAliasTypeName(node.name.value); + aliasMap[typeRefPrefix] = + refer(fragmentTypeName, "${fragment!.url ?? ""}#data"); + // print("alias $typeRefPrefix => $fragmentTypeName"); + return; + } + + for (final node in selectionsWithoutTypename) { + if (node is FragmentSpreadNode) { + // exclude redefined selections from each fragment selections + final fragmentSelections = fragmentMap[node.name.value]!.selections; + final exclusiveFragmentSelections = + mergeSelections(fragmentSelections, fragmentMap).where((s1) { + if (s1 is FieldNode) { + final name = (s1.alias ?? s1.name).value; + return selectionsWithoutTypename + .whereType() + .every((s2) => name != (s2.alias ?? s2.name).value); + } else if (s1 is InlineFragmentNode && s1.typeCondition != null) { + /// TODO: Handle inline fragments without a type condition + final name = s1.typeCondition!.on.name.value; + return selectionsWithoutTypename + .whereType() + .every((s2) => name != s2.typeCondition?.on.name.value); + } + return false; + }).toList(); + + _dataClassAliasMapDFS( + typeRefPrefix: typeRefPrefix, + getAliasTypeName: getAliasTypeName, + selections: exclusiveFragmentSelections, + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + } else if (node is InlineFragmentNode) { + if (node.typeCondition != null) { + /// TODO: Handle inline fragments without a type condition + _dataClassAliasMapDFS( + typeRefPrefix: + "${typeRefPrefix}__as${node.typeCondition!.on.name.value}", + getAliasTypeName: getAliasTypeName, + selections: [ + ...selections.where((s) => s != node), + ...node.selectionSet.selections, + ], + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + } + } else if (node is FieldNode && node.selectionSet != null) { + _dataClassAliasMapDFS( + typeRefPrefix: "${typeRefPrefix}_${(node.alias ?? node.name).value}", + getAliasTypeName: getAliasTypeName, + selections: node.selectionSet!.selections, + fragmentMap: fragmentMap, + aliasMap: aliasMap, + ); + } + } +} diff --git a/codegen/gql_code_builder/lib/src/built_class.dart b/codegen/gql_code_builder/lib/src/built_class.dart index 631ba97b..135507ae 100644 --- a/codegen/gql_code_builder/lib/src/built_class.dart +++ b/codegen/gql_code_builder/lib/src/built_class.dart @@ -11,6 +11,7 @@ Class builtClass({ Map? initializers, Map superclassSelections = const {}, List methods = const [], + Map? dataClassAliasMap, }) { final className = builtClassName(name); return Class( @@ -30,12 +31,16 @@ Class builtClass({ ], ), ), - ...superclassSelections.keys.map( - (superName) => refer( - builtClassName(superName), - (superclassSelections[superName]?.url ?? "") + "#data", - ), - ) + ...superclassSelections.keys + .where((superName) => + dataClassAliasMap?.containsKey(builtClassName(superName)) != + true) + .map( + (superName) => refer( + builtClassName(superName), + (superclassSelections[superName]?.url ?? "") + "#data", + ), + ) ], ) ..constructors.addAll( diff --git a/codegen/gql_code_builder/lib/src/common.dart b/codegen/gql_code_builder/lib/src/common.dart index 7cbcd01a..590a575e 100644 --- a/codegen/gql_code_builder/lib/src/common.dart +++ b/codegen/gql_code_builder/lib/src/common.dart @@ -138,6 +138,7 @@ Method buildGetter({ required TypeNode typeNode, required SourceNode schemaSource, Map typeOverrides = const {}, + Reference? typeRefAlias, String? typeRefPrefix, bool built = true, bool isOverride = false, @@ -151,7 +152,9 @@ Method buildGetter({ final typeMap = { ...defaultTypeMap, - if (typeRefPrefix != null) + if (typeRefAlias != null) + typeName: typeRefAlias + else if (typeRefPrefix != null) typeName: refer("${typeRefPrefix}_${nameNode.value}") else if (typeDef != null) typeName: refer( diff --git a/codegen/gql_code_builder/lib/src/config/data_class_config.dart b/codegen/gql_code_builder/lib/src/config/data_class_config.dart new file mode 100644 index 00000000..65a399e5 --- /dev/null +++ b/codegen/gql_code_builder/lib/src/config/data_class_config.dart @@ -0,0 +1,8 @@ +/// config for the optimization of data class generation. +class DataClassConfig { + final bool reuseFragments; + + const DataClassConfig({ + required this.reuseFragments, + }); +} diff --git a/codegen/gql_code_builder/lib/src/inline_fragment_classes.dart b/codegen/gql_code_builder/lib/src/inline_fragment_classes.dart index 1eff2d74..7ccddb9c 100644 --- a/codegen/gql_code_builder/lib/src/inline_fragment_classes.dart +++ b/codegen/gql_code_builder/lib/src/inline_fragment_classes.dart @@ -22,6 +22,7 @@ List buildInlineFragmentClasses({ required String type, required Map typeOverrides, required Map fragmentMap, + required Map dataClassAliasMap, required Map superclassSelections, required List inlineFragments, required bool built, @@ -31,6 +32,7 @@ List buildInlineFragmentClasses({ baseTypeName: name, inlineFragments: inlineFragments, config: whenExtensionConfig, + dataClassAliasMap: dataClassAliasMap, ); return [ Class( @@ -38,12 +40,15 @@ List buildInlineFragmentClasses({ ..abstract = true ..name = builtClassName(name) ..implements.addAll( - superclassSelections.keys.map( - (superName) => refer( - builtClassName(superName), - (superclassSelections[superName]?.url ?? "") + "#data", - ), - ), + superclassSelections.keys + .where((superName) => + !dataClassAliasMap.containsKey(builtClassName(superName))) + .map( + (superName) => refer( + builtClassName(superName), + (superclassSelections[superName]?.url ?? "") + "#data", + ), + ), ) ..methods.addAll([ ...fieldGetters, @@ -51,6 +56,7 @@ List buildInlineFragmentClasses({ ..._inlineFragmentRootSerializationMethods( name: builtClassName(name), inlineFragments: inlineFragments, + dataClassAliasMap: dataClassAliasMap, ), ]), ), @@ -65,6 +71,7 @@ List buildInlineFragmentClasses({ fragmentMap, ), fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, schemaSource: schemaSource, type: type, typeOverrides: typeOverrides, @@ -77,33 +84,46 @@ List buildInlineFragmentClasses({ /// TODO: Handle inline fragments without a type condition /// https://spec.graphql.org/June2018/#sec-Inline-Fragments - ...inlineFragments.where((frag) => frag.typeCondition != null).expand( - (inlineFragment) => buildSelectionSetDataClasses( - name: "${name}__as${inlineFragment.typeCondition!.on.name.value}", - selections: mergeSelections( - [ - ...selections.whereType(), - ...selections.whereType(), - ...inlineFragment.selectionSet.selections, - ], - fragmentMap, - ), - fragmentMap: fragmentMap, - schemaSource: schemaSource, - type: inlineFragment.typeCondition!.on.name.value, - typeOverrides: typeOverrides, - superclassSelections: { - name: SourceSelections(url: null, selections: selections) - }, - built: built, - whenExtensionConfig: whenExtensionConfig), - ), + ...inlineFragments.where((frag) { + if (frag.typeCondition == null) { + return false; + } + final typeName = + builtClassName("${name}__as${frag.typeCondition!.on.name.value}"); + if (dataClassAliasMap.containsKey(typeName)) { + // print("alias $typeName => ${dataClassAliasMap[typeName]!.symbol}"); + return false; + } + return true; + }).expand( + (inlineFragment) => buildSelectionSetDataClasses( + name: "${name}__as${inlineFragment.typeCondition!.on.name.value}", + selections: mergeSelections( + [ + ...selections.whereType(), + ...selections.whereType(), + ...inlineFragment.selectionSet.selections, + ], + fragmentMap, + ), + fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, + schemaSource: schemaSource, + type: inlineFragment.typeCondition!.on.name.value, + typeOverrides: typeOverrides, + superclassSelections: { + name: SourceSelections(url: null, selections: selections) + }, + built: built, + whenExtensionConfig: whenExtensionConfig), + ), ]; } List _inlineFragmentRootSerializationMethods({ required String name, required List inlineFragments, + required Map dataClassAliasMap, }) => [ buildSerializerGetter(name).rebuild( @@ -121,9 +141,11 @@ List _inlineFragmentRootSerializationMethods({ { for (var v in inlineFragments .where((frag) => frag.typeCondition != null)) - "${v.typeCondition!.on.name.value}": refer( - "${name}__as${v.typeCondition!.on.name.value}", - ) + "${v.typeCondition!.on.name.value}": dataClassAliasMap[ + "${name}__as${v.typeCondition!.on.name.value}"] ?? + refer( + "${name}__as${v.typeCondition!.on.name.value}", + ) }, ), ]).code, diff --git a/codegen/gql_code_builder/lib/src/operation/data.dart b/codegen/gql_code_builder/lib/src/operation/data.dart index 7a43b669..e8fea5ab 100644 --- a/codegen/gql_code_builder/lib/src/operation/data.dart +++ b/codegen/gql_code_builder/lib/src/operation/data.dart @@ -1,4 +1,5 @@ import "package:code_builder/code_builder.dart"; +import "package:collection/collection.dart"; import "package:gql/ast.dart"; import "package:gql_code_builder/src/config/when_extension_config.dart"; @@ -13,12 +14,13 @@ List buildOperationDataClasses( SourceNode schemaSource, Map typeOverrides, InlineFragmentSpreadWhenExtensionConfig whenExtensionConfig, + Map fragmentMap, + Map dataClassAliasMap, ) { if (op.name == null) { throw Exception("Operations must be named"); } - final fragmentMap = _fragmentMap(docSource); return buildSelectionSetDataClasses( name: "${op.name!.value}Data", selections: mergeSelections( @@ -32,6 +34,7 @@ List buildOperationDataClasses( ), typeOverrides: typeOverrides, fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, superclassSelections: {}, whenExtensionConfig: whenExtensionConfig, ); @@ -43,8 +46,9 @@ List buildFragmentDataClasses( SourceNode schemaSource, Map typeOverrides, InlineFragmentSpreadWhenExtensionConfig whenExtensionConfig, + Map fragmentMap, + Map dataClassAliasMap, ) { - final fragmentMap = _fragmentMap(docSource); final selections = mergeSelections( frag.selectionSet.selections, fragmentMap, @@ -58,6 +62,7 @@ List buildFragmentDataClasses( type: frag.typeCondition.on.name.value, typeOverrides: typeOverrides, fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, superclassSelections: {}, built: false, whenExtensionConfig: whenExtensionConfig, @@ -70,6 +75,7 @@ List buildFragmentDataClasses( type: frag.typeCondition.on.name.value, typeOverrides: typeOverrides, fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, superclassSelections: { frag.name.value: SourceSelections( url: docSource.url, @@ -98,16 +104,6 @@ String _operationType( .value; } -Map _fragmentMap(SourceNode source) => { - for (var def - in source.document.definitions.whereType()) - def.name.value: SourceSelections( - url: source.url, - selections: def.selectionSet.selections, - ), - for (var import in source.imports) ..._fragmentMap(import) - }; - /// Builds one or more data classes, with properties based on [selections]. /// /// For each selection that is a field with nested selections, a descendent @@ -124,6 +120,7 @@ List buildSelectionSetDataClasses({ required String type, required Map typeOverrides, required Map fragmentMap, + required Map dataClassAliasMap, required Map superclassSelections, bool built = true, required InlineFragmentSpreadWhenExtensionConfig whenExtensionConfig, @@ -162,6 +159,8 @@ List buildSelectionSetDataClasses({ typeNode: typeNode, schemaSource: schemaSource, typeOverrides: typeOverrides, + typeRefAlias: + dataClassAliasMap[builtClassName("${name}_${nameNode.value}")], typeRefPrefix: node.selectionSet != null ? builtClassName(name) : null, built: built, isOverride: superclassSelectionNodes.contains(node), @@ -181,23 +180,27 @@ List buildSelectionSetDataClasses({ type: type, typeOverrides: typeOverrides, fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, superclassSelections: superclassSelections, inlineFragments: inlineFragments, built: built, whenExtensionConfig: whenExtensionConfig, ) - else if (!built) + else if (!built && dataClassAliasMap[name] == null) Class( (b) => b ..abstract = true ..name = builtClassName(name) ..implements.addAll( - superclassSelections.keys.map( - (superName) => refer( - builtClassName(superName), - (superclassSelections[superName]?.url ?? "") + "#data", - ), - ), + superclassSelections.keys + .where((superName) => + !dataClassAliasMap.containsKey(builtClassName(superName))) + .map( + (superName) => refer( + builtClassName(superName), + (superclassSelections[superName]?.url ?? "") + "#data", + ), + ), ) ..methods.addAll([ ...fieldGetters, @@ -217,18 +220,23 @@ List buildSelectionSetDataClasses({ "G__typename": literalString(type), }, superclassSelections: superclassSelections, + dataClassAliasMap: dataClassAliasMap, ), // Build classes for each field that includes selections ...selections .whereType() .where( - (field) => field.selectionSet != null, + (field) => + field.selectionSet != null && + !dataClassAliasMap.containsKey(builtClassName( + "${name}_${field.alias?.value ?? field.name.value}")), ) .expand( (field) => buildSelectionSetDataClasses( name: "${name}_${field.alias?.value ?? field.name.value}", selections: field.selectionSet!.selections, fragmentMap: fragmentMap, + dataClassAliasMap: dataClassAliasMap, schemaSource: schemaSource, type: unwrapTypeNode( _getFieldTypeNode( @@ -251,6 +259,55 @@ List buildSelectionSetDataClasses({ ]; } +/// Shrink merged fields nodes based on FragmentMap +List shrinkSelections( + List selections, + Map fragmentMap, +) { + final unmerged = [...selections]; + + for (final selection in selections) { + if (selection is FieldNode && selection.selectionSet != null) { + final index = unmerged.indexOf(selection); + unmerged[index] = FieldNode( + name: selection.name, + alias: selection.alias, + selectionSet: SelectionSetNode( + selections: + shrinkSelections(selection.selectionSet!.selections, fragmentMap), + ), + ); + } else if (selection is InlineFragmentNode && + selection.typeCondition != null) { + /// TODO: Handle inline fragments without a type condition + final index = unmerged.indexOf(selection); + unmerged[index] = InlineFragmentNode( + typeCondition: selection.typeCondition, + directives: selection.directives, + selectionSet: SelectionSetNode( + selections: + shrinkSelections(selection.selectionSet.selections, fragmentMap), + ), + ); + } + } + + for (final node in unmerged.whereType().toList()) { + final fragment = fragmentMap[node.name.value]!; + final spreadIndex = unmerged.indexOf(node); + final duplicateIndexList = []; + unmerged.forEachIndexed((selectionIndex, selection) { + if (selectionIndex > spreadIndex && + fragment.selections.any((s) => s.hashCode == selection.hashCode)) { + duplicateIndexList.add(selectionIndex); + } + }); + duplicateIndexList.reversed.forEach(unmerged.removeAt); + } + + return unmerged; +} + /// Deeply merges field nodes List mergeSelections( List selections, @@ -282,6 +339,29 @@ List mergeSelections( fragmentMap, ))); } + } else if (selection is InlineFragmentNode && + selection.typeCondition != null) { + /// TODO: Handle inline fragments without a type condition + final key = selection.typeCondition!.on.name.value; + if (selectionMap.containsKey(key)) { + selectionMap[key] = InlineFragmentNode( + typeCondition: selection.typeCondition, + directives: selection.directives, + selectionSet: SelectionSetNode( + selections: mergeSelections( + [ + ...(selectionMap[key] as InlineFragmentNode) + .selectionSet + .selections, + ...selection.selectionSet.selections, + ], + fragmentMap, + ), + ), + ); + } else { + selectionMap[key] = selection; + } } else { selectionMap[selection.hashCode.toString()] = selection; } diff --git a/codegen/gql_code_builder/lib/src/when_extension.dart b/codegen/gql_code_builder/lib/src/when_extension.dart index 52987e54..197bcab4 100644 --- a/codegen/gql_code_builder/lib/src/when_extension.dart +++ b/codegen/gql_code_builder/lib/src/when_extension.dart @@ -39,7 +39,8 @@ Code _caseStatement(InlineFragmentNode inlineFragment) => Extension? inlineFragmentWhenExtension( {required String baseTypeName, required List inlineFragments, - required InlineFragmentSpreadWhenExtensionConfig config}) { + required InlineFragmentSpreadWhenExtensionConfig config, + required Map dataClassAliasMap}) { final inlineFragmentsWithTypConditions = inlineFragments .where((inlineFragment) => inlineFragment.typeCondition != null) .toList(); @@ -54,8 +55,11 @@ Extension? inlineFragmentWhenExtension( /// returns the name of the concrete built class for the inlineFragment /// so we can refer to it in the generated code - String getGeneratedTypeName(InlineFragmentNode node) => - builtClassName("${baseTypeName}__as${node.typeCondition!.on.name.value}"); + String getGeneratedTypeName(InlineFragmentNode node) { + final typeName = builtClassName( + "${baseTypeName}__as${node.typeCondition!.on.name.value}"); + return dataClassAliasMap[typeName]?.symbol ?? typeName; + } /// a pool of parameter names which have already been used /// so we can avoid name clashes