apollo-ios icon indicating copy to clipboard operation
apollo-ios copied to clipboard

Reserved keyword "self" is not escaped in 1.0 Beta 1 codegen

Open scottasoutherland opened this issue 3 years ago • 4 comments

Bug report

We have an existing project which has query called "self" i.e. the query looks like

query self{
    self {
    ....
    }
}

and likewise the query in the schema is named self. When running codegen in 0.51.2 the usages of Self or self are escaped properly using back-ticks. However in 1.0 Beta 1 the code generation does not escape self and we get compiler errors such as

Keyword 'Self' cannot be used as an identifier here

or Getter/setter can only be defined for a single variable when it interprets self as the keyword.

Versions

Please fill in the versions you're currently using:

  • apollo-ios SDK version: 1.0 Beta 1
  • Xcode version: 13.4
  • Swift version: 5.6
  • Package manager: cocoapods

Steps to reproduce

  • Create a graphQL schema with a query named "self"
  • Create a query on the client also named self
  • Run code-generation against that query.
  • Attempt to compile

Further details

scottasoutherland avatar Aug 04 '22 16:08 scottasoutherland

Ooooh, we did not think about this! We're going to need to create a list of all reserved keywords and backtick on all of them! Thanks for the report, we will get this in a beta release coming up soon!

AnthonyMDev avatar Aug 04 '22 16:08 AnthonyMDev

I've been working on this issue, and there are a lot of extra edge cases here that are going to take me longer to work through.

I've got a branch I'm working on right now where fields with names of reserved keywords should work now when the field is a scalar field. I need to handle the escaping properly for the names of the generated SelectionSets for fields with those names still.

My goal is to have a Beta out by the end of the week, which will include backtick escaping names of fields as described in this issue originally. But there is a ton of other work that will probably have to come in the next Beta.

I also have to get this working when keywords are used as the names of:

  • Name of Generated SelectionSet (as stated above)
  • Field Aliases
  • Object Types
  • Interface Types
  • Union Types
  • Enum Types
  • Input Object Types
  • Fragment Names
  • Field Arguments
  • Fields on Input Objects
  • Enum Case Names
  • Name of your Schema Module/Namespace (may just disallow this one, since it's fully in your control, and naming your Schema Module Type is pretty ridiculous IMO.)

It's going to take longer to get this working... lots of complications. One being that when you have a type in your schema with a reserved keyword name like Protocol or Type. Swift does NOT like that, even with backticks, so I have to come up with a different solution.

Thanks for making me aware of this issue. Hope this update helps with your planning!

AnthonyMDev avatar Aug 10 '22 23:08 AnthonyMDev

Okay, the PR (#2432) is merged into release/1.0 for the first part of this work. This should solve the exact case you've described above and a number of other ones. The rest of the cases I've mentioned in my previous comment will be resolved next week.

This part will make it into the beta which I aim to release tomorrow (8/11/2022). @scottasoutherland Please try depending on the release branch and verify that this works for you as needed now!

AnthonyMDev avatar Aug 12 '22 02:08 AnthonyMDev

I'm going to leave this issue open to track the rest of the needed changes as well.

AnthonyMDev avatar Aug 12 '22 02:08 AnthonyMDev

Most of this work is done and now available in beta 2. We'll create new tracking issues for the remaining items.

hwillson avatar Aug 18 '22 18:08 hwillson

👋🏻 @AnthonyMDev / @hwillson are there known new/remaining issues here?
A situation I just ran across with some local generated code in 1.0.6:

type Input {
    operator: String
}

Generated:

struct Input: InputObject {
    public private(set) var __data: InputDict

    public init(_ data: InputDict) {
      __data = data
    }

    public init(
      `operator`: GraphQLNullable<String> = nil,
    ) {
      __data = InputDict([
        "operator": `operator`,
      ])
    }

    public var `operator`: GraphQLNullable<String> {
      get { __data["`operator`"] }
      set { __data["`operator`"] = newValue }
    }
}

As you can see, the operator keyword is properly escaped on the var and the init, but the generated input dict has a mismatch between the string it is using between the init and the getter.

Happy to put this in a separate issue if this is new, but just ran into it!

👏🏻 Thanks for all you do!

pluddy avatar Jan 31 '23 14:01 pluddy

Hi @pluddy, this was fixed with #2773 which hasn't been published in a release yet. It will go out with 1.0.7 but for now you can get the fix by using the main branch.

calvincestari avatar Jan 31 '23 18:01 calvincestari

Awesome @calvincestari, looking forward to it! Thanks for the quick response 👊🏻

pluddy avatar Feb 03 '23 13:02 pluddy