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

Fix RootEntityType and FulfilledFragment name generation #3045

Merged
merged 8 commits into from
May 31, 2023
Merged

Conversation

AnthonyMDev
Copy link
Contributor

@AnthonyMDev AnthonyMDev commented May 25, 2023

Fully qualified names should be generated at all times for FulfilledFragments and RootEntityType. Due to the issue indicated in #2949

Fully qualified names were not being calculated properly for fragments on the root of a query. Simplified the calculation of these by adding the fully qualified root type names to the root of the FieldPathComponents. This fixes #2962.

@netlify
Copy link

netlify bot commented May 25, 2023

Deploy Preview for apollo-ios-docs canceled.

Name Link
🔨 Latest commit ed634db
🔍 Latest deploy log https://app.netlify.com/sites/apollo-ios-docs/deploys/64777b508d543100081d2b2e

@AnthonyMDev AnthonyMDev marked this pull request as draft May 25, 2023 23:02
let type: GraphQLType

/// Represents the location within a GraphQL definition (operation or fragment) of an `Entity`.
struct Location: Hashable {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to generate selection set names properly, an entity needs to be able to indicate where it is located in its definition. This includes needing to know what definition (operation or fragment) it is defined in.

Previously, we were using a hacky solution of adding an initial FieldPath component that included the name of the fragment, or the operation type. This was being used to help properly generate the selection set names, but it was hacky for 2 reasons:

  1. It was making the "field path" not really accurate. Field path included a first component for the source definition that any code that was consuming the field path just needed to understand was there. Causing tight coupling of implementation code.
  2. This partially put the responsibility of how we generate names in the templates into the IR. The IR should just represent the shape of the definitions, and the templates consume them to understand how to generate the correct code.

Representing the Location with a SourceDefinition and a FieldPath allows us to better represent the shape of the operations in the IR and allows the templates to do all the logic for formatting names of the Selection Sets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this change, especially helping separate responsibilities between the IR and Templates

@AnthonyMDev AnthonyMDev marked this pull request as ready for review May 30, 2023 23:16
@@ -44,6 +44,10 @@ public class CompilationResult: JavaScriptObject {
"\(name) on \(rootType.debugDescription)"
}

public func hash(into hasher: inout Hasher) {
hasher.combine(name)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can never be 2 operations with the same name, as graphql-js would fail validation. So this is safe

precondition(!array.isEmpty, "Cannot initialize LinkedList with an empty array. LinkedList must have at least one element.")
var segments = array
let headNode = HeadNode(value: segments.removeFirst())
public init<C: Collection<T>>(_ collection: C) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made this function take in a generic collection instead of only an array. This allows us to pass in another linked list or an ordered set.

)
}

private static func generatedSelectionSetName(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core of the changes in the template. The rest is mostly updating call sites to use these new functions.

This refactors the selection set name computation to account for the fact that the fieldPath no longer includes a component for the root definition.

@@ -6037,6 +6037,153 @@ class SelectionSetTemplateTests: XCTestCase {
expect(actual).to(equalLineByLine(expected, atLine: 1, ignoringExtraLines: true))
}

func test__render_conditionalFragmentOnQueryRoot__rendersRootEntityType() throws {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the tests for the actual bug fix. The rest of the test changes are just refactoring for other minor API changes.

Copy link
Member

@BobaFetters BobaFetters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good, nice work!

@AnthonyMDev AnthonyMDev merged commit 4771541 into main May 31, 2023
@AnthonyMDev AnthonyMDev deleted the fix-2692 branch May 31, 2023 20:45
Copy link
Member

@calvincestari calvincestari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generated code is sometimes incomplete when using @include directive
3 participants