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

Fix isenum for referenced enums #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

LukeMarlin
Copy link
Owner

Fixes OpenAPITools#5676
Referenced enums are now properly marked as isEnum = true

Had to fix kotlin spring generator. Tests go through as before, and I doubled checked that current code gives me the exact same models output for the sample that was related to this topic.

PR checklist

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project beforehand.
  • Run the shell script ./bin/generate-samples.shto update all Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master. These must match the expectations made by your contribution. You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/config/java*. For Windows users, please run the script in Git BASH.
  • File the PR against the correct branch: master
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

While this is not targeting a specific generator, it did affect a kotlin spring test, so I'm summoning its technical comitee as my code in these files might not be OK: @jimschubert, @dr4ke616, @karismann, @Zomzog, @andrewemery, @4brunu, @yutaka0m

It also failed samples generation for haskell, so I patched it with a quick if, that should definitely be checked by the team: @jonschoning

Fixes OpenAPITools#5676
Referenced enums are now properly marked as isEnum = true
Copy link

@jimschubert jimschubert left a comment

Choose a reason for hiding this comment

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

I'm running some tests locally, but left a couple comments.

There are a lot of changes to how enums are processed by other languages, which I'd need to understand better as it's considered a breaking change for these.

for (CodegenProperty prop : model.allVars) {
//If a property is an enum and a primitive type, it is an embedded enum
if (prop.isEnum && prop.isPrimitiveType) {
model.imports.add("JsonValue");

Choose a reason for hiding this comment

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

This will have already occurred on line 519.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Not what I witnessed: if the model itself is not an enum, but has variables that are enums, then kotlin generator need to have that import.

... Now that I reread, I see it's hasEnums so you should be right. Two possibilities: my code here changed nothing so I'll remove it, or hasEnumwas false and I need to check out why. I'll try to do that on monday and report back

Copy link
Owner Author

Choose a reason for hiding this comment

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

@jimschubert Just took a look at it again, line 519 adds JsonProperty if a model is not an enum, because it will have properties.
My code replaces the previous line 521 that was adding JsonValue whenever a model has enums by a code that adds it only if one of the enum is embedded, as what was done previously by that generator. I did it to have the same result as master, although the JsonValue import doesn't seem to be used at all...

@@ -20,7 +20,7 @@
{{>interfaceOptVar}}
{{/optionalVars}}
{{/discriminator}}
{{#hasEnums}}{{#vars}}{{#isEnum}}
{{#hasEnums}}{{#vars}}{{#isEnum}}{{#isPrimitiveType}}

Choose a reason for hiding this comment

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

Interesting. I started looking at this a bit after our Slack conversation, but hadn't thought about how isPrimitiveType might fit into things.

One issue with considering enums as primitive is that $ref doesn't mean "This is a class/model", it means "I want to reuse this bit of schema in more than one place". So, if an enum which is inline is a primitive type, an enum that is $ref should also be a primitive type.

I'll have to think about this a little more and maybe discuss with the core team.

Copy link
Owner Author

@LukeMarlin LukeMarlin Jul 4, 2020

Choose a reason for hiding this comment

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

Yes, the kotlin test allowed me to notice that an inline enum is basically this in core:

  • isEnum = True
  • isPrimitive = True
  • isString = True

But when you have a referenced enum (with my change), you get:

  • isEnum = True

and that's it.

So relying on isPrimitive would be the only way for generators to distinguish between the two cases (as far as I've noticed).
It does seem a bit brittle though. I guess isString might be ok, but I'm unsure it would cover all cases.

@@ -5257,6 +5258,9 @@ public void setParameterBooleanFlagWithCodegenProperty(CodegenParameter paramete
* @param var list of CodegenProperty
*/
public void updateCodegenPropertyEnum(CodegenProperty var) {
if (!var.isPrimitiveType) {
return;

Choose a reason for hiding this comment

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

What is the rationale for returning early here?

This prevents the allowableValues/EnumVars from being constructed at all, which I think you'd want to do if it's an Enum in any way.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ah sorry, I should have removed the summoning from description. I gave a bit more context to Jim about that base PR.
first is the actual intended change, the second is a lame attempt at fixing all the changes that result from it. So there is no rationale behind this change, I was just trying stuff out.

So yes, you are absolutely right here. My bad!

| E'EnumString'Lower -- ^ @"lower"@
| E'EnumString'Empty -- ^ @""@
deriving (P.Show, P.Eq, P.Typeable, P.Ord, P.Bounded, P.Enum)
=

Choose a reason for hiding this comment

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

the generated enum properties are missing here now

@LukeMarlin
Copy link
Owner Author

Reverted the commit that was a lame attempt at keeping backward compatibility, it was just noise to the matter at hand.

@jimschubert
Copy link

I wonder if in the 14 places where we add + "Enum" to enum names, whether we should do this only if the text doesn't end in Enum already. Maybe @wing328 will have a thought on it.

There are a ton of changes in this PR that change previous OuterEnum to OuterEnumEnum, which isn't ideal.

There are times when an enum may be a $ref just for reusability and the user may not want it to be generated as a model. I think in those cases people may need to change from components/schema to another yaml/json node which doesn't have a specific meaning in the OAI spec.

@LukeMarlin
Copy link
Owner Author

I wonder if in the 14 places where we add + "Enum" to enum names, whether we should do this only if the text doesn't end in Enum already. Maybe @wing328 will have a thought on it.

I could add it if it's needed, I think it makes sense.

There are times when an enum may be a $ref just for reusability and the user may not want it to be generated as a model. I think in those cases people may need to change from components/schema to another yaml/json node which doesn't have a specific meaning in the OAI spec.

Unsure whether I understand, TBH :)

We'd "preserve" the old behaviour by telling people to move their enum to a non openapi section if they want to avoid having a model generated (due to now's true value of isEnum)? That's still quite a breaking change right?

@jimschubert
Copy link

I think it's correct to always generate a top-level type for $ref enum when supported by the generator.

It would be better if swagger-parser supported yaml fully and allowed anchors and node references, then we wouldn't need to worry about the edge case of people using $ref for reuse rather than model definition.

@jimschubert
Copy link

@LukeMarlin I couldn't tell if you were continuing to work on this or not.

Whenever you're ready to contribute this upstream, please open the PR against openapi-generator repo (rather than your fork).

@LukeMarlin
Copy link
Owner Author

Hi @jimschubert ! I didn't do anything new on that PR because I have no idea in which direction I should go.
This is a breaking change, and based on last comments I couldn't tell if it was a desirable one or not.

Considering only the first commit, do you think I should open the PR with it, or do you see changes to be made first?

@wing328
Copy link

wing328 commented Dec 28, 2022

closed via OpenAPITools#13880

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.

[CORE] Referenced Enums incorrectly tagged isEnum = false
4 participants