This looks like it'll be a really great addition to the generator.
Something that wasn't clear from the examples or tests is how acronyms are handled when they are used at the start of a string. How would HTTPProxy be converted, for example?
I would wonder if GET_pet_petId is a better name than Get_pet_petId. Both (in a capitalized snake case) are not conventional for Swift, but the former looks clearer for distinguishing GET as an HTTP method.
That's a great callout, I added more unit tests for this case.
When used as a type name, HTTPProxy stays as HTTPProxy. When used as a variable name, it gets turned into hTTPProxy (not pretty, but are uppercase acronyms often used for member names, rather than type names?)
If not used at the start of the string, both variants look good. PrimaryHTTPProxy gets turned into a type name PrimaryHTTPProxy, and member name primaryHTTPProxy.
How is this handled in the middle of a word? Presumably correctly because the word boundary is the next cap, so we'd get myHTTPRequest.
Is there a heuristic that would better serve us here? I think we could detect word boundaries on changing case and then, during re-casing, we could recase words in their entirety, to ether title case or lowercase depending of it's being used as a type or property respectively?
Can you think of any places that this strategy would not be what we want?
Sure, we could do that. It'd require look-ahead, which we don't require today (every character is processed based on what's come before it, but never based on what comes ahead of it).
See the second half of my message, the handling in the middle of the word is correct already. The question really is only about member names that start with an acronym. I'm curious of we have examples of idiomatic names in OpenAPI docs that start with an uppercase property name. We could see what it'd take to make those look better, or agree that those have to live with the slightly awkward first lowercased letter.
Yeah, I'm curious about this. I imagine there might be many docs that have used uppercase for acronyms in their JSON schema, like UUID or ID, which with the current proposal, when used as properties, would become uUID and iD.
Right, but they're only used as properties if they're properties in the OpenAPI doc. We never take a type name (like a schema name in the OpenAPI type) and lowercase it. Only the opposite - we take property names and uppercase them when needed to be used as type names (eg for inline types).
So the question is - if someone names their property "UUID", what would they want to see in Swift?
But... Once it is shipped, we'll have to care about breaking changes, right? Oh, so it is not the new strategy that produces the undesired uUID and hTTPProxy, then? Sorry I did not read the thread well enough.
The code does not aim at being exemplar, just at doing what reasonable users expect (it converts a raw Swift type name, potentially qualified, into an identifier that looks like a variable or property name).
There being a single override per key leads me to think that the names are generated from the override.
If so, would it make sense to instead allow the user to configure the capitalised and non-capitalised version of the name? With that escape hatch it might be acceptable to forgo the look-ahead re-casing strategy.
In practice, we can never change anything about a naming strategy, because any change could break an existing adopter. We haven't changed the existing defensive strategy since it was introduced, and once we ship this idiomatic strategy, we won't be able to change it again within v1 of Swift OpenAPI Generator. But we also want to avoid having to add a third strategy, this proposal is really meant to settle the topic for v1.
With that in mind, yes we need to figure out the details for handling acronyms and other cases during this proposal period, as we won't have an opportunity to fix it up later.
Right now the proposed implementation actually takes the overrides exactly as they are, without even changing casing. My assumption was that the specific string shows up either as a type, or as a member, but very rarely both.
That said, I think it's reasonable to consider more granular overrides, for types vs members. Do you have an idea in mind for the exact spelling, @georgebarnett?
But I suspect we'll need to make the jump and do the word separation and then glueing them back together. I mainly need folks to comment here with test cases, of the input string and what they'd expect for a type name and a member name. I'll drop them into the unit test suite and figure out how to implement it later.
I've already added HTTPProxy -> (HTTPProxy, httpProxy). But would be good to have more, where folks have a clear idea of what they'd like to see.
I refrained from chiming in because I know nothing about OpenAPI and its conventions. But now that you ask this openly maybe I can share some things I remember from the top of my head from the time I wrote a small casing library myself where I implemented word separations from all kinds string input.
These were the hardest cases:
There are mixed letter acronyms like IoT or iOS that are hard to parse into words.
On some platforms it's idiomatic to keep abbreviations in uppercase when camelCasing and on other platforms only the first letter stays uppercased. In Swift we usually keep the abbreviations uppercase. So you could want that image_url becomes imageURL instead of imageUrl.
Plural handling: CustomerUUIDs is meant to be ["Customer", "UUIDs"] instead of ["Customer", "UUI", "Ds"].
Sometimes abbreviation follow each other, but are meant to be separate words. For example: AWSJWT.
To my knowledge all of these issues can only be addressed with dictionaries of problematic word sequences or heuristics that will have their own false positives. I would advise against trying to find build-in solutions for this.
You could argue to make exceptions for abbreviations where there is already precedence in the standard library and always uppercase them accordingly even when they are provided as mixed casing. For example URL. But then what else? JSON, JWT, XML should they also get special treatment? Where would we stop? And since this list needs to be kept stable for at least one major version, it would be super hard to come up with a definitive list. Especially because every org has their own share of abbreviations it might be weird to have mixed handling.
I firmly believe it cannot be handled by library authors. There is already an escape hatch for people who care about perfect casing and this is nameOverrides.
What I could see myself wanting is support for RegEx in the name overrides so that I can address reoccurring patterns like replacing Url with URL or similar to keep up with idiomatic Swift naming conventions.
Oh okay, I must admit I haven't taken the time to read through the code so didn't realise this was the case. In gRPC we need names in upper and lower hence the suggestion.
Given it's rare for a string to show up as a type as a member I would keep the existing approach for overrides. If this ever becomes necessary you could always extend the expected schema in the future such that the override could be a dictionary rather than a string.