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

Allow JsonSubTypes to be interfaces/abstract classes #149

Merged

Conversation

glentakahashi
Copy link

@glentakahashi glentakahashi commented Jun 16, 2017

By moving the check for interfaces and abstract classes into the getTypeName method as a fallback, the generator will now properly work for JsonSubTypes that are immutables. Previously, if your JsonSubTypes were immutables, those types would get improperly dropped from the taggedUnionClasses.

Also fixes a test case where Quadrilaterals should be type-restricted to only "square" and "rectangle"

@glentakahashi glentakahashi changed the title Allow JsonSubTypes to be immutables Allow JsonSubTypes to be interfaces/abstract classes Jun 16, 2017
@vojtechhabarta
Copy link
Owner

Thanks for your PR.

I was thinking that in the end some non-abstract classes are needed but if you have use case for abstracts or interfaces lets do it. It would be good if you could add some test with your scenario because otherwise somebody (including me) could refactor this out sometimes in the future.

I also thought that allowing interfaces to be part of tagged unions could cause problems because of multiple inheritance but I tried your change with diamond class hierarchy and it seems it behaves reasonably. I will commit test for it after the merge.

BTW I like that the diff of your PR is really small and there is nothing extra.

@glentakahashi
Copy link
Author

Added a test for immutables, where Square is a normal class, Rectangle is an abstract class, and Circle is an interface. Might be redundant to the current TaggedUnionsTest, so let me know if you think it's worth including.

@vojtechhabarta
Copy link
Owner

Thanks for the test. It doesn't matter that it has similar structure as other tests but it is valuable that it shows how interfaces are used in tagged unions in combination with Immutables library.

@vojtechhabarta vojtechhabarta merged commit 351a936 into vojtechhabarta:master Jun 20, 2017
@glentakahashi glentakahashi deleted the glen/allow-immutables branch June 20, 2017 14:35
@glentakahashi
Copy link
Author

@vojtechhabarta can you tag a release for the latest head? Would love to start using this in our proct

@vojtechhabarta
Copy link
Owner

Released v1.26.333.

@vojtechhabarta
Copy link
Owner

@sayresVT I was thinking this change will not break much code. Do you have some example what causes the problem? And do you think it affects more people?

I would create configuration switch and set default to original behavior. I want typescript-generator to be dependable so it should provide reasonably good backward compatibility.

On the other hand I would like to provide this functionality to people without any configuration effort.
@glentakahashi what do you think?

@glentakahashi
Copy link
Author

Yea didn't realize this would break anything, I thought it would be an entirely additive change. Let me know if it breaks and I can try and make a PR to fix it.

@sayresVT
Copy link
Contributor

I'll try to add a sscce test based upon the issue we're seeing

@sayresVT
Copy link
Contributor

I added the following unit test that I believe demonstrates the same issue we're seeing with some of the generated ts output: Q-Free-OpenRoads/typescript-generator@bd16ac5

It appears that some interfaces are being generated without the discriminant property but then extending two parent interfaces that have incompatible discriminant properties such as:

export interface Child extends ParentA, ParentB {
  // ts error, 'kind' property does not match for ParentA & ParentB
}

export interface ParentA extends RootParent {
  kind: 'Type1' | 'Type2' | 'Type3';
}

export interface ParentB extends RootParent {
  kind: 'Type1' | 'Type2';
}

export interface RootParent {
  kind: 'Type1' | 'Type2' | 'Type3' | 'Type4';
}

export interface ParentC<GenericType> extends RootParent {
  // Also saw one case where the same generated 'kind' property
  // was generated with the type of string instead of a string literal.
  // Currently unable to reproduce this case in a test
  kind: string;  
}

export interface Type1 extends Child {
  kind: 'Type1';
}
// etc.

@glentakahashi
Copy link
Author

glentakahashi commented Jun 23, 2017 via email

@glentakahashi
Copy link
Author

As for the Child error case, I couldn't understand what the underlying java was that was incorrectly parsing as that. Do you mind sharing the Java structure that output the incorrect ParentC as well as the incorrect Child. I couldn't get either of them to fail in scenarios that I tried.

@vojtechhabarta
Copy link
Owner

Yes, inherited properties with same name and type are removed from derived class (ModelCompiler.removeInheritedProperties()).

This removing was originally implemented because Jackson returns all properties (own and inherited) of beans and I didn't want to repeat one property in all descendants.

We could emit discriminant property always but this would require extra code and it would be an exception from the rule.

@sayresVT
Copy link
Contributor

sayresVT commented Jun 26, 2017

@glentakahashi adding the kind: "rectangle"; specification to INamedQuadrilateral3 was just a guess at what the correct typescript should possibly be. Without it, the generated typescript is invalid because the two inherited properties from IShape3 (kind: "circle" | "rectangle";) and IQuadrilateral3 (kind: "rectangle";) are incompatible. I'll see if I can figure out the classes that are causing the issue observed in ParentC.

@vojtechhabarta I agree that it seems preferable to avoid repeating the property in all descendants. In our case, it really only occurred in 3-4 interfaces that happened to inherit two parent interfaces with incompatible discriminant properties

@glentakahashi
Copy link
Author

Ah apologies, I didn't try to compile it, I see what you mean. I think this should be fixable, I'll try and get something out today.

@glentakahashi
Copy link
Author

@sayresVT should be fixed in #153

@vojtechhabarta
Copy link
Owner

I was experimenting with Q-Free-OpenRoads@bd16ac5 test and #153 PR and I found out that removing inherited discriminant properties is really non-intuitive. So I changed my mind and implemented special handling for these properties so that they are preserved in inherited interfaces.

This change also fixes generated TypeScript code in mentioned test so #153 should not be needed. @glentakahashi do you think we can close it?

@glentakahashi
Copy link
Author

I like this solution the best! 👍

Closed out my other PR

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.

3 participants