Swiftgen: Escaping 'Type' doesn't work as expected

Created on 7 Feb 2019  Â·  7Comments  Â·  Source: SwiftGen/SwiftGen

Hello,

I have multiple localized string keys that contains the word 'type' which is escaped by SwiftGen. But when I try to access any translation under the enum Type, the compiler says that there is no such member.

I'm using Xcode 10.1 and SwiftGen 6.0.2.

Here is a willingly simplified sample of the issue:

``` public enum Translation { public enum Food { public enumclass` {
public static let test = "test"
}

    public enum `Type` {
        public static let apple = "apple"
    }
}

}

print(Translation.Food.class.test) // This works fine
print(Translation.Food.Type.apple) // This does not compile "Type 'Translation.Food.Type' has no member 'apple'.
````

By the way it is not possible to access the 'apple' constant using the auto-completion under these circumstances.

My understanding is that the compiler do not authorize this so I guess SwiftGen can't do much about it. Would it be possible to use a "renaming policy" instead of an "escaping policy" for the keyword 'Type'... ?

Apple bug

All 7 comments

What you have here is not a reserved keyword per se, but a collision with an existing type Type, that is the "metatype" for a given type (type-ception 😆).

I'm not sure there's anything we can do to solve this. We could check if the resulting name is Type, and add an underscore so it becomes _Type. But then when you try autocompletion, you'll still get Type (the swift metatype accessor) and _Type (the child enum).

I think on call site you could also just use it as Swift intends, that is, this should work? (didn't try it though)

print(Translation.Food.`Type`.apple)

As @djbe said, that's because any type (class, struct, enum) can be suffixed with .Type in Swift to refer to the type itself, like in this example (unrelated to SwiftGen):

class CustomTableViewCell: UITableViewCell {}
func dequeue(type: UITableViewCell.Type) { print("…") }
dequeue(type: CustomTableViewCell.self)

A change in the template like the one @djbe suggested might do it, the only question then is what to use instead when you encounter Type, do we want to replace it with _Type or Type_ or anything else? At least Jeremy can amend the template according his preferences on his end, but indeed for the general case we might want to do something in the bundled template ourselves too, I just don't know what would be the best option (and indeed there's no way for us to avoid Type to pop-up in autocomplete anyway, as it would still be valid swift to refer to the metatype)

Yes I see, thank you for the quick answers.

@AliSoftware : no unfortunately, I did tried that and it didn't work either.

I guess the _Type proposal wouldn't be that bad, it does fix the issue, never-mind the auto-completion...

What's strange is that I'd expect that we'd have a similar issue with self, but it doesn't seem to bother the compiler like with .Type…

public enum Translation {
  public enum Food {
    public enum `self` {
      public static let apple = "apple"
    }
  }
}

print(Translation.Food.self.apple) // Type 'Translation.Food' has no member 'apple' (not very surprising)
print(Translation.Food.`self`.apple) // This works fine

Swift bug then?

yeah, I was actually editing my comment above to add:

So not sure why adding backticks around Type inside the print wouldn't similarly solve the issue… might actually be a Swift bug, as the point of using backticks there should explicitly be to avoid considering This as a keyword and more as a property… like it does with self…

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marcelofabri picture marcelofabri  Â·  6Comments

taykay08 picture taykay08  Â·  3Comments

gorbat-o picture gorbat-o  Â·  5Comments

romk1n picture romk1n  Â·  7Comments

gereons picture gereons  Â·  5Comments