-
-
Notifications
You must be signed in to change notification settings - Fork 353
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
Handling of receiver parameters #4069
Comments
I think the ideal solutions here are not backward compatible. If we value compatibility the most, we can save the former in some organized way. When we redesign the general API, there may then be ideas that have matured over time to minimize hasty design decisions. |
Sorry about the late response on this one, it slipped past during vacations.
I agree that his is wrong, and would label it a bug that should be fixed. As for a solution, I personally would like the receiver parameter to remain in the list of formal parameters. While Spoon originally was all about semantics, several projects I'm involved in (merging and automatic program repair) rely heavily on the Spoon AST remaining somewhat close to the actual syntactical structure of the source file. This is especially helpful when pretty printing, and even more so when sniper printing. I think options 1) and 2a) (perhaps both, they aren't mutually exclusive) are the most promising. I dislike option 3) because every method and constructor has a receiver, it's just implicit in the vast majority of cases. An additional option would be to implement option 1/2 with Ping @monperrus, thoughts? |
Thanks for analyzing this dark corner.
That can be fixed in a PR. I don't expect many/any test case to fail.
That can be fixed in a separate PR.
That's reasonable and easy to understand for clients. Definitely a good improvement. |
I was looking into #4145 for a bit and came across spoon/src/main/java/spoon/support/visitor/ClassTypingContext.java Lines 660 to 663 in 9a45639
I'm not sure if there are more spots like that, but this is definitely an edge case that can cause major headache I think. |
Closing this as we implemented #5674 in Spoon v11. |
This issue covers the general handling of receiver parameters in spoon.
Receiver parameters were introduced with Java 8. They are specified in JLS 8.4 with example code in JLS 8.4.1.
Spoon got support for this feature with this Pull request (related issue).
Currently, spoon handles receiver parameters in the same way other parameters are handled too. This brings us to the first issue:
When creating a
CtExecutableReference
(usingCtExecutable#getReference()
orExecutableFactory#createReference(CtExecutable<?>)
), the receiver parameter is included. For me, this is unexpected or even wrong, and a call toCtExecutableReference#getActualMethod()
will always returnnull
.Having the receiver parameter in the parameter list also makes the creation of invocations harder, as you manually need to ignore receiver parameters on your own.
A second issue becomes visible when looking at the example code in the JLS: For now, spoon only handles methods. A receiver parameter in a constructor of an inner class (referencing the enclosing class) will simply be ignored and does not appear in the model created by spoon.
Adding support for constructors in the same way as with methods should be pretty simple, but I'd like to discuss alternatives of how to represent receiver parameters in the metamodel altogether.
I thought about several solutions with different pros and cons:
1) Add a
isReceiver(): boolean
method toCtParameter
Pros:
CtParameter#getSimpleName().equals("this")
CtParameter#getSimpleName().equals("this")
internallyCons:
CtExecutableReference#getParameters()
still returns a list ofCtTypeReference
s including the receiver parametersisReceiver()
method inCtTypeReference
would increase code that does not really belong thereCtParameter
s of theCtExecutable
to see if aCtTypeReference
is a receiver2) Add a
hasReceiver(): boolean
method toCtExecutable
a) but keep the parameter in the parameter list
Pros:
Outer.Inner.this
) and position (0) and is represented in the model this wayCons:
CtExecutableReference
toob) and remove it from the parameter list
Pros:
Cons:
CtExecutable#getParameters()
orCtParameter
3) Add a
CtReceiver
Do not add it to the parameter list but add
get/setReceiver()
methods. Add the respective properties toCtExecutable
. I'm not sure if it should be part ofCtExecutableReference
with aCtReceiverReference
or similar.(super types of
CtReceiver
might be discussed)Pros:
Cons:
4) Only add support for constructors the same way as for methods
Pros:
Cons:
Some general questions:
CtExecutable#addParameterAt(int, CtParameter)
with0
asposition
? (e.g. refactoring a method and its invocations by adding a parameter at 0 would fail currently)Side note: When looking at the code, I was super confused because the JDT
Receiver
is never traversed by JDT itself - in contrast to the other arguments, annotations, type parameters, etc. I don't know if this is a bug in JDT, but calling the traverse method ourselves is fine I guess.I'm happy to implement any of this, or modified variants depending on your opinions and ideas. Feedback is very welcome.
The text was updated successfully, but these errors were encountered: