Skip to content

Conversation

akkp-windsurf
Copy link
Contributor

📝 Description

🔗 Related Issues

akkp-windsurf#7

devin-ai-integration bot and others added 5 commits September 24, 2025 08:36
- Add responseClassToTypeSpecs map to GraphQLClientGeneratorContext
- Implement post-processing logic to identify structurally identical response types
- Generate shared response types using structural comparison based on property signatures
- Remove duplicated response types from per-operation generation
- Maintain backward compatibility with existing type generation
- Follow existing patterns used for input types and enums sharing

This change reduces code duplication by sharing identical response types across
different GraphQL operations, similar to how input types and enums are currently shared.

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
…ed-types-response-types

feat: extend shared types mechanism to include response types
…end-shared-types-response-types"

This reverts commit a2045e6, reversing
changes made to e3b74bf.
- Add useSharedResponseTypes flag to GraphQLClientGeneratorConfig (defaults to false)
- Add responseClassToTypeSpecs cache to GraphQLClientGeneratorContext for shared response types
- Add responseTypeToSelectionSetMap cache to track merged selection sets
- Modify generateCustomClassName to use shared packages for ObjectTypeDefinition when enabled
- Implement shouldCreateSharedResponseType and mergeSelectionSets helper functions
- Update GraphQLClientGenerator to output shared response types in .responses package
- Add comprehensive test coverage with SharedResponseTypesTest
- Response types now use .responses package similar to .inputs and .enums when feature is enabled
- Maintains backward compatibility with existing behavior when feature is disabled

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
- Replace hardcoded type detection with two-pass generation approach
- First pass: analyze all queries to track ObjectTypeDefinition usage across operations
- Second pass: generate shared types for types used in multiple operations
- Add typeUsageCount map to GraphQLClientGeneratorContext for usage tracking
- Modify shouldCreateSharedResponseType to use usage count instead of hardcoded names
- Enhance selection set merging to work with usage-based detection
- Maintain backward compatibility when useSharedResponseTypes=false

This eliminates the need to hardcode specific type names like 'ComplexObject',
'DetailsObject', and 'ScalarWrapper', making the feature more flexible and
automatically applicable to any GraphQL schema.

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
@samuelAndalon
Copy link
Contributor

replying here as well:

The reuse types logic is partially implemented in graphql-kotlin-client-generator, it just needs to be extended to apply for all operations that are find during generation goal, currently it reuses types for single operations

see: https://github.com/ExpediaGroup/graphql-kotlin/tree/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types

for this operation: https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/ReusedTypesQuery.graphql

we should expect three ComplexObject types
https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject.kt
https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject2.kt
https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject3.kt

the test included in this PR does not test an actual scenario where reusing types is possible,
the folder is that the PR attempts to test is:

https://github.com/ExpediaGroup/graphql-kotlin/tree/master/plugins/client/graphql-kotlin-client-generator/src/test/data/kotlinx/multiple_queries

which contains 2 queries:

https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/kotlinx/multiple_queries/FirstQuery.graphql

https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/kotlinx/multiple_queries/SecondQuery.graphql

that are not actually selecting the same fields from ComplexObject, so type wouldn't be able to reused

I wrote a use case you could use to test your logic:

query Operation1 {
  first: complexObjectQuery {
    id
    name
  }
  second: complexObjectQuery {
    id
    name
    details {
      id
      value
    }
  }
  third: complexObjectQuery {
    id
    name
    details {
      id
    }
  }
  fourth: complexObjectQuery {
    id
    name
  }
  fifth: complexObjectQuery {
    id
    name
    details {
      id
      value
    }
  }
}
query Operation2 {
  first: complexObjectQuery {
    id
    name
  }
  second: complexObjectQuery {
    id
    name
    details {
      id
      value
    }
  }
  third: complexObjectQuery {
    id
    name
    details {
      id
    }
  }
  fourth: complexObjectQuery {
    id
    name
  }
  fifth: complexObjectQuery {
    id
    name
    details {
      id
      value
    }
  }
}

You should you be able to generate only 3 types and reuse them for both queries:

https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject.kt
https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject2.kt
https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/client/graphql-kotlin-client-generator/src/test/data/generator/reuse_types/reusedtypesquery/ComplexObject3.kt

@samuelAndalon samuelAndalon self-requested a review September 25, 2025 23:22
- Modify generateCustomClassName to use cross-operation reuse logic for shared types
- Add isCachedTypeApplicableForSharedType function for selection set verification
- Update selection set tracking to work with type variants across operations
- Create cross_operation_reuse test case with Operation1 and Operation2
- Generate exactly 3 shared types (ComplexObject, ComplexObject2, ComplexObject3)
- Maintain backward compatibility with existing reuse_types functionality
- Fix missing ScalarTypeDefinition import that caused compilation errors
- Verify functionality with gradle-client and maven-client examples

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
@akkp-windsurf
Copy link
Contributor Author

@samuelAndalon, provided Devin with the feedback and made some changes, would you mind taking a look?

devin-ai-integration bot and others added 3 commits September 26, 2025 17:32
…tGenerator

- Add proper imports for graphql.language.Field and graphql.language.SelectionSet
- Replace fully qualified names with imported types
- Remove redundant null check for selection.selectionSet in recursive call
- Address PR feedback on code quality improvements

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
…ypeUsageTracker

- Remove analyzeTypeUsage first pass and processSelectionSet methods from GraphQLClientGenerator
- Simplify shouldCreateSharedResponseType to only check if useSharedResponseTypes feature is enabled
- Remove typeUsageCount from GraphQLClientGeneratorContext (no longer needed)
- Delete SharedResponseTypesTest.kt and integrate testing into existing GenerateGraphQLClientIT structure
- Remove cross_operation_reuse test directory that was causing test failures
- Treat all ObjectTypeDefinition types as reuse candidates when feature is enabled
- Maintain cross-operation type reuse functionality without CPU overhead
- Fix unused import issues (Field, SelectionSet) and remove needless blank line

This optimization eliminates the expensive CPU operation that was only used to detect
multi-use types, improving build performance while maintaining the same functionality.

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
- Inline context.config.useSharedResponseTypes directly instead of shouldCreateSharedResponseType function
- Remove unused mergeSelectionSets function that had unused parameters
- Improve code quality by eliminating unnecessary function overhead
- All tests, ktlintCheck, and detekt pass successfully

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
@Samjin
Copy link
Contributor

Samjin commented Oct 2, 2025

Would a additional flag to turn on shared resp type provides smooth adoption?

@samuelAndalon
Copy link
Contributor

@samuelAndalon, provided Devin with the feedback and made some changes, would you mind taking a look?

sorry, I thought there was some ongoing work still, the tests disappeared.

…ared response types

- Create GenerateSharedResponseTypesIT with useSharedResponseTypes = true
- Move cross_operation_reuse test case to shared_response_types directory
- Exclude shared_response_types from GenerateGraphQLClientIT to avoid config mismatch
- Ensure test configuration matches expected output structure (responses package)
- Generate exactly 7 files: Operation1.kt, Operation2.kt, and 5 shared response types

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
@akkp-windsurf
Copy link
Contributor Author

@samuelAndalon the cross operation use tests should be added back now

devin-ai-integration bot and others added 3 commits October 6, 2025 18:15
…ResponseTypes parameter

- Remove GenerateSharedResponseTypesIT test class
- Add conditional logic in GenerateGraphQLClientIT for cross_operation_reuse directory
- Add useSharedResponseTypes parameter to generateClient function
- Update Gradle and Maven plugins to pass the parameter (with TODO for configuration)
- Maintain backwards compatibility with default value false

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
…tion logic

- Rename cross_operation_reuse directory to cross_operation_reuse_types for clarity
- Update GenerateGraphQLClientIT condition to check for cross_operation_reuse_types
- Remove old shared_response_types directory structure
- Remove GenerateSharedResponseTypesIT test class as requested
- All tests, lint checks, and sample applications pass successfully

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
- Remove filter that excludes shared_response_types from default generator tests
- This filter is no longer needed after simplifying the test structure
- All tests, ktlintCheck, and detekt pass successfully

Co-Authored-By: Arthur Poon <arthur.poon@windsurf.com>
@samuelAndalon samuelAndalon merged commit 2959ce9 into ExpediaGroup:master Oct 8, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants