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

Avoid generating invalid Scala identifiers when printing schemas and protocols #178

Merged
merged 3 commits into from Dec 5, 2019

Conversation

cb372
Copy link
Member

@cb372 cb372 commented Dec 5, 2019

Fixes #114

Added a new identifier combinator to Printer, which turns arbitrary strings into valid Scala identifiers by wrapping them with backticks if necessary. Unfortunately it wasn't possible to actually use the combinator in that many places; I ended up directly calling the underlying Printer.toValidIdentifier instead.

I didn't want to write my own buggy implementation of the Scala lexical spec, so I used scalameta to take care of the logic to decide when something needs to be backticked.

The printing of Mu schemas/protocols was pretty trivial to fix. The OpenAPI printing, on the other hand, is much more complex. There is a lot more code being generated, and there was already a lot of string manipulation/normalization going on. Because of this, I'm not that confident I've covered every single case correctly, but the test coverage is at least high enough to convince me I haven't made the situation worse.

These changes have caused the OpenAPI codegen behaviour to change in a few cases. Now instead of names being "normalized" (which did not take account of the need to escape Scala reserved words), they are left as-is but wrapped in backticks as necessary when they are used as Scala identifiers. See e.g. this updated test for an example of the changes. There were also a couple of small unintended changes that were really hard to avoid without extensive refactoring, e.g. this change from Status to status.

There is already a `normalize` function which makes an attempt to
normalize strings into valid Scala identifiers, but it does not handle
all cases correctly, e.g. it does not handle reserved words.

Added an `ident` function which does a better job at converting an
arbitrary string into a valid identifier, by delegating the logic to
scalameta. Rather than fiddling with the contents of the string to make
it valid, we just wrap it in backticks if required.

Unfortunately, `normalize` is used for a lot of different things, not
only generation of valid identifiers, so I then had to go through the
code and switch from `normalize` to `ident` in *just* the right places
to make the tests pass.

The codegen behaviour has changed slightly (for the better I think) in a
few cases. See the updated unit tests for the details.
Similar to the previous commit, just wrapping strings in
`toValidIdentifier` in all the right places.

Extended the existing protobuf printing test to cover this new
behaviour.
Copy link
Member

@juanpedromoreno juanpedromoreno left a comment

Choose a reason for hiding this comment

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

Thanks @cb372 , LGTM!

build.sbt Outdated Show resolved Hide resolved
*/
def toValidIdentifier(string: String): String =
if (string.isEmpty) string
else scala.meta.Term.Name(string).syntax
Copy link
Member

Choose a reason for hiding this comment

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

👌

Co-Authored-By: Juan Pedro Moreno <4879373+juanpedromoreno@users.noreply.github.com>
@juanpedromoreno juanpedromoreno merged commit 15e408b into higherkindness:master Dec 5, 2019
@pepegar
Copy link
Member

pepegar commented Dec 5, 2019

Hey @cb372 I'm fairly late to this party... but this looks awesome, thank you very much!

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.

Add a new combinator to escape Scala reserved words
3 participants