-
Notifications
You must be signed in to change notification settings - Fork 468
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 Swift codegen escaping for identifiers, types, and strings #1515
Fix Swift codegen escaping for identifiers, types, and strings #1515
Conversation
@lilyball: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Meteor Contributor Agreement here: https://contribute.meteor.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome, thanks so much for contributing!
Most of my comments are questions because my grip on TypeScript is a little tenuous, but overall this is going to be an enormous help.
packages/apollo-codegen-swift/src/__tests__/__snapshots__/codeGeneration.ts.snap
Show resolved
Hide resolved
.join(" "); | ||
} | ||
return new SwiftSource( | ||
`"${string.replace(/[\0\\\t\n\r"]/g, c => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind throwing in a comment for the regex-impared explaining what's being replaced here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, this is a pretty simple regex. It's just matching any of 6 characters. I suppose I could say something like // Match any character that needs escaping in Swift strings
but I thought that was inferable from context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, but I think maybe what threw me is I'm not really sure what's being escaped with \0
, or why a single quote isn't being escaped. The other bits are pretty straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically all I really need to escape is \n
, \r
, "
, and \\
, but I included \0
(the NUL character) and \t
because Swift has defined escapes for those and that makes the source easier to read. Single quote isn't escaped because it's not a special character in a Swift string literal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - maybe if there's someplace where those are defined it might be worth throwing in a comment link to it. Otherwise, this is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I can put in a link to the Swift language reference.
* Concatenates multiple `SwiftSource`s together. | ||
*/ | ||
concat(...sources: SwiftSource[]): SwiftSource { | ||
// Documentation says + is faster than String.concat, so let's use that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moderately less silly question: Would this work with Typescript reduce
, or is that only something that works in Swift?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This absolutely could be Array.reduce
and I will make that change. I'm actually not normally a JavaScript/TypeScript programmer so I don't know offhand what functional methods are in the standard library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah neither am I, clearly.
// Disable trimming if the string contains """ as this means we're probably printing an | ||
// operation definition where trimming is destructive. | ||
this.printOnNewline( | ||
SwiftSource.string(string, /* trim */ !string.includes('"""')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the inline comment here is to indicate what that parameter is, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. Would you prefer I remove it, or use a different style?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, I just hadn't seen that particular syntax before
7a8eadd
to
c147a13
Compare
Force-pushed to fix the flagged issues (including renaming Pushed again to resolve the conflict. |
c147a13
to
54c384b
Compare
When the GraphQL field name `self` is used, the synthesized type name `Self` matches a reserved keyword and isn't being properly escaped. This test currently fails.
For example, the type `Self?` needs to escape the identifier `Self`.
This allows for replacing the `string` type given to `print` and `printOnNewline` with a new type, as long as it responds to `toString()`. The idea here is that languages can define their own source types and use tagged template literals to implement automatic escaping as needed.
The source generator now operates using a string wrapper type called `SwiftSource`. Identifiers are escaped when converting into `SwiftSource` values, with an alternative method for producing escaped string literals. An escape hatch is provided for disabling escapes, but the default behavior is to escape all identifiers in the dynamic input. Most `SwiftSource` values are produced by a tagged template literal, which allows for easy mixing of string literals containing Swift keywords and dynamic input that needs escaping. As part of this, rewrite string escaping such that it actually escapes string contents properly. This required fixing a test that had a bad spec enforcing broken behavior. This commit makes the test added earlier pass. Fixes apollographql/apollo-ios#193. Fixes apollographql/apollo-ios#752.
54c384b
to
b9a72a3
Compare
Updated again, this time with a test for unescaped types (similar to what was encountered in apollographql/apollo-ios#193), as well as the changelog. This PR should now be good to go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great - I'll need to test it against our main repo this afternoon before I merge it to see if this should be a minor or patch release on the iOS SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this'll go out in a patch. Woot!
@JakeDawkins Can you confirm the failing circle tests are an issue on our end? It certainly looks like it with the error |
Failing checks are due to this coming from a fork - tooling team is on it. Merging this! |
Oh good, now that this has been released, I can state that it did not introduce any performance regressions, which I was afraid it might (due to replacing strings with objects). But running |
The source generator now operates using a string wrapper type called
SwiftSource
. Identifiers are escaped when converting intoSwiftSource
values, with an alternative method for producing escaped string literals. An escape hatch is provided for disabling escapes, but the default behavior is to escape all identifiers in the dynamic input.Most
SwiftSource
values are produced by a tagged template literal, which allows for easy mixing of string literals containing Swift keywords and dynamic input that needs escaping.As part of this, rewrite string escaping such that it actually escapes string contents properly. This required fixing a test that had a bad spec enforcing broken behavior.
Fixes apollographql/apollo-ios#193.
Fixes apollographql/apollo-ios#752.
This PR isn't quite done yet. I haven't updated the changelog, and I also haven't added tests for apollographql/apollo-ios#193 that fail without this change. I'm submitting this now because it's almost 1AM and I'm going to bed, and I'd like to get some eyes on it.
TODO:
*Make sure changelog entries note which project(s) has been affected. See older entries for examples on what this looks like.