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

Introduce SignatureBuilder API #147

Merged
merged 5 commits into from
Jan 11, 2023
Merged

Conversation

mkouba
Copy link
Contributor

@mkouba mkouba commented Jan 6, 2023

This pull request supersedes #116.

Usage example:

import io.quarkus.gizmo.SignatureBuilder;
import io.quarkus.gizmo.Type;

// List<String> test();
method.setSignature(SignatureBuilder.forMethod()
   .setReturnType(Type.parameterizedType(Type.classType(List.class), Type.classType(String.class)))
   .build()
)

See also io.quarkus.gizmo.SignaturesTest.

@mkouba mkouba requested review from Ladicek, gsmet and Sgitario January 6, 2023 09:33
@Ladicek
Copy link
Contributor

Ladicek commented Jan 6, 2023

Looks great! I added some minor comments, and I have 2 more general here:

  1. I'd generally try to keep most of this private. For example, I don't think we need public Type.toSignature() or Type.isClass() / asClass() etc.
  2. I didn't think of this before, but it occured to me when reviewing this. Maybe we could split TypeVariable to TypeParameter and TypeVariableArgument for this particular case? A TypeParameter may have bounds, while TypeArgumentVariable has just the identifier. (TypeArgumentVariable is a terrible name...) This would allow a bit more type safety, e.g. a ParameterizedType wouldn't accept a TypeParameter as a type argument. Not sure it's worth it.

@mkouba mkouba force-pushed the signature-from branch 2 times, most recently from d110414 to 3f66373 Compare January 6, 2023 10:05
@mkouba
Copy link
Contributor Author

mkouba commented Jan 6, 2023

  1. I'd generally try to keep most of this private. For example, I don't think we need public Type.toSignature() or Type.isClass() / asClass() etc.

Well, we would have to use some abstract superclass because interfaces cannot declare private members and we use these methods in impls. I don't think that it's a problem.

  1. I didn't think of this before, but it occured to me when reviewing this. Maybe we could split TypeVariable to TypeParameter and TypeVariableArgument for this particular case? A TypeParameter may have bounds, while TypeArgumentVariable has just the identifier. (TypeArgumentVariable is a terrible name...) This would allow a bit more type safety, e.g. a ParameterizedType wouldn't accept a TypeParameter as a type argument. Not sure it's worth it.

Hmm. I'm not sure. From user's POV I think that the name "type variable" is more understandable. In any case, I believe that the current version is "good enough".

@Ladicek
Copy link
Contributor

Ladicek commented Jan 6, 2023

Added one commit that refactors the SignatureBuilder for better encapsulation (per my ideas above). Feel free to drop :-)

The tests could use some improvements -- I'll get to it next week.

@gsmet
Copy link
Member

gsmet commented Jan 6, 2023

I will have a look on Monday and try to use it in Quarkus GitHub App.

@Sgitario
Copy link

Sgitario commented Jan 9, 2023

Back from my PTO. I will use these changes in some Quarkus extensions to give some feedback asap. Thanks!

@mkouba
Copy link
Contributor Author

mkouba commented Jan 9, 2023

Added one commit that refactors the SignatureBuilder for better encapsulation (per my ideas above). Feel free to drop :-)

@Ladicek I can't say I like all those (TypeImpl) casts and similar but other than the Signature interface it looks very good.

The tests could use some improvements -- I'll get to it next week.

Feel free to improve the coverage ;-).

@Ladicek
Copy link
Contributor

Ladicek commented Jan 9, 2023

I don't like the TypeImpl class either, but it was Friday afternoon and I was stupid. I can make Type an abstract class instead of an interface and then I can encapsulate properly without those silly casts. Will fix.

@Ladicek
Copy link
Contributor

Ladicek commented Jan 9, 2023

Done.

@mkouba
Copy link
Contributor Author

mkouba commented Jan 9, 2023

Done.

Ok, I think that we're ready to go. We could either merge this PR and improve the coverage in a follow-up or wait a little... WDYT?

@gsmet
Copy link
Member

gsmet commented Jan 9, 2023

Maybe wait for this afternoon? I want to test it on Quarkus GitHub App and report back.

@gsmet
Copy link
Member

gsmet commented Jan 9, 2023

(Working on Sergey's PR this morning so can't work on that now)

@mkouba
Copy link
Contributor Author

mkouba commented Jan 9, 2023

Maybe wait for this afternoon? I want to test it on Quarkus GitHub App and report back.

👍

@Ladicek
Copy link
Contributor

Ladicek commented Jan 9, 2023

I did add the most interesting test case I wanted (the horror of inner classes). There's more that could be done for methods, but I feel the code by now is correct by construction. I have a very similar piece of code in Jandex with a lot more tests, so I feel pretty good about what we have.

@gsmet
Copy link
Member

gsmet commented Jan 9, 2023

@Ladicek yeah I was thinking of either that, or have several flavors of superClass() and interfaces() (which would probably need to be singular or it would be annoying) for the ClassCreator builder which would allow to push parameterized types.

We would then push them to the SignatureBuilder to generate the default signature (that you would still be able to override if you want to do more advanced stuff).

Just pushing ideas, I will let you decide what's best.

@mkouba
Copy link
Contributor Author

mkouba commented Jan 9, 2023

Passing a ClassSignatureBuilder to the io.quarkus.gizmo.ClassCreator.Builder seems to be the "best" option but I don't like it very much.

@Ladicek
Copy link
Contributor

Ladicek commented Jan 9, 2023

I think we could just add an overload of signature() that would accept ClassSignatureBuilder and when that is used, superClass() and interfaces() become optional. Maybe we could even verify that when both are set, they match.

@gsmet
Copy link
Member

gsmet commented Jan 10, 2023

Another option would be to create a ClassSignature from the builder and have signature(ClassSignature) as an overload of signature(String).

That would probably be a bit better than passing a builder.

@mkouba
Copy link
Contributor Author

mkouba commented Jan 10, 2023

That would probably be a bit better than passing a builder.

Except that it would require one more useless allocation...

@Ladicek
Copy link
Contributor

Ladicek commented Jan 10, 2023

Also one more [otherwise] useless class. I didn't get to trying it yet (generic signatures and descriptors are so much fun... :-) ), but I suspect using a builder will be just fine.

@gsmet
Copy link
Member

gsmet commented Jan 10, 2023

Except that it would require one more useless allocation...

I fail to see how it would ever be in the hot path. But I won't fight for it. I can live with what's already there if you all think it's the way to go.
It gets the dark magic away and makes things far more readable for people not familiar with the Java bytecode.

@gsmet
Copy link
Member

gsmet commented Jan 10, 2023

Didn't want my review to be blocking, I will let you all have fun with it and merge :).

@mkouba
Copy link
Contributor Author

mkouba commented Jan 10, 2023

Didn't want my review to be blocking, I will let you all have fun with it and merge :).

No problem. It's a great feedback. Thanks!

@mkouba
Copy link
Contributor Author

mkouba commented Jan 10, 2023

Also one more [otherwise] useless class. I didn't get to trying it yet (generic signatures and descriptors are so much fun... :-) ), but I suspect using a builder will be just fine.

I have something... will add a commit - feel free to refactor/throw it away.

@Ladicek
Copy link
Contributor

Ladicek commented Jan 10, 2023

No throwing away, this is pretty much what I thought I'd do. I think it's fine.

@mkouba mkouba requested a review from Ladicek January 11, 2023 08:32
@mkouba
Copy link
Contributor Author

mkouba commented Jan 11, 2023

Didn't want my review to be blocking, I will let you all have fun with it and merge :).

@gsmet How about something like this? https://github.com/quarkusio/gizmo/pull/147/files#diff-f3ceec916aa72c0ab7318fa5821d400412118071f45e55d13310c5f4a3796df9R260-R274

@gsmet
Copy link
Member

gsmet commented Jan 11, 2023

Much better, me likey!

@mkouba mkouba merged commit 3260d3f into quarkusio:main Jan 11, 2023
@Ladicek
Copy link
Contributor

Ladicek commented Jan 11, 2023

Yay! 😆

Sgitario added a commit to Sgitario/quarkus that referenced this pull request Jan 23, 2023
From quarkusio/gizmo#147, we can use the latest SignatureBuilder API. 
To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary.
Sgitario added a commit to Sgitario/quarkus that referenced this pull request Jan 24, 2023
From quarkusio/gizmo#147, we can use the latest SignatureBuilder API.
To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary.
michelle-purcell pushed a commit to michelle-purcell/quarkus that referenced this pull request Jan 24, 2023
From quarkusio/gizmo#147, we can use the latest SignatureBuilder API.
To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary.
michelle-purcell pushed a commit to michelle-purcell/quarkus that referenced this pull request Jan 24, 2023
From quarkusio/gizmo#147, we can use the latest SignatureBuilder API.
To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary.
ebullient pushed a commit to maxandersen/quarkus that referenced this pull request Jan 24, 2023
From quarkusio/gizmo#147, we can use the latest SignatureBuilder API.
To use the new SignatureBuilder API, I had to deal with the gizmo type class, so more changes than expected were necessary.
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.

4 participants