-
Notifications
You must be signed in to change notification settings - Fork 329
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
enhancing Java parsers to recover method invocation type attribution when arg types are missing #4596
base: main
Are you sure you want to change the base?
Conversation
…d type attribution when arg types are missing if there's only one valid signature matching the method name and arg count
Hi Nick, I doubt processors will be introduced any time soon since annotation processing is triggered in Saving the |
Thanks @nmck257 ! Not sure if you've spoken to Sam about this effort already, but you've at least inspired |
yeah, we've had a few pings across mismatched working hours. the |
The work there has hardly been tested at all yet. There is basically only a simple test for I have checked that I can run |
Or Sam will classload the annotation processor and call the relevant methods, instead, haha. I won't have time this week, but I can throw most of the parsing together over the weekend. |
Getting this exception:
swapping |
Thanks for taking a look! @sambsnyd might have some idea or insights. |
edit: I've pushed a change to support if it's useful with minimal context, here's an error I got when parsing a file which uses The field it was parsing is the first occurrence of
|
TLDR: I quickly looked, and some Lombok annotations get pretty ugly. There are ways to work around the complexity by preserving the original tree, but I don't want to touch it. Jon, Knut, or Sam will find a clean solution. Info: Annotations that generate statements such as Before: import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
} After: import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public CleanupExample() {
super();
}
public static void main(String[] args) throws IOException {
@Cleanup
InputStream in = new FileInputStream(args[0]);
try {
@Cleanup
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (java.util.Collections.singletonList(out).get(0) != null) {
out.close();
}
}
} finally {
if (java.util.Collections.singletonList(in).get(0) != null) {
in.close();
}
}
}
} Lombok doesn't account for unnecessary annotations, which adds additional complexity: Before: import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public CleanupExample() {
super();
}
public static void main(String[] args) throws IOException {
@Cleanup
InputStream in = new FileInputStream(args[0]);
try {
@Cleanup
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (java.util.Collections.singletonList(out).get(0) != null) {
out.close();
}
}
} finally {
if (java.util.Collections.singletonList(in).get(0) != null) {
in.close();
}
}
}
} After: import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public CleanupExample() {
super();
}
public static void main(String[] args) throws IOException {
@Cleanup
InputStream in = new FileInputStream(args[0]);
try {
try {
@Cleanup
OutputStream out = new FileOutputStream(args[1]);
try {
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (java.util.Collections.singletonList(out).get(0) != null) {
out.close();
}
}
} finally {
if (java.util.Collections.singletonList(out).get(0) != null) {
out.close();
}
}
} finally {
if (java.util.Collections.singletonList(in).get(0) != null) {
in.close();
}
}
} finally {
if (java.util.Collections.singletonList(in).get(0) != null) {
in.close();
}
}
}
} |
yeah, that Cleanup example is pretty grizzly -- I wonder if an interim option could be configuring the lombok annotation processor to simply ignore some of its more-troublesome annotations? |
an "elegant" (if not performant) option might be compiling the files twice -- once without annotation processors and once with -- and visiting the non-annotation-processed outputs to produce the trees, but, using the processed version as a parallel reference point to re-populate missing types |
IIRC, the majority of parsing time is spent in the If anyone has time before I get around to it:
On second thought, this could become problematic with a large source set. |
I investigated the Lombok code a bit and it looks like Lombok supports registering custom handlers for annotations, so the idea would be try to supply handlers for the problematic annotations when using Lombok programmatically. I will try this out next week if I find some time. |
(if there's only one valid signature matching the method name and arg count)
What's changed?
see subject
What's your motivation?
Lombok support (#1297) is presumably still far away. In the interim, this PR attempts to "patch over" one hole in type attribution which Lombok repos can introduce.
For example, I frequently work with ( / refactor) code like this:
Sometimes developers will supply those props from a separate Properties class with getters from Lombok, eg,
.propA(lombokPropertyClass.getPropA())
. OpenRewrite won't know the type of the getter, because Lombok. That cascades to OpenRewrite not knowing the type of thepropA(...)
method invocation. That cascades to OpenRewrite not knowing the type of theselect
for the next method, and so on. If I want to refactorfancyConfig(...)
, then even if those arg types are known, theselect
is unknown, and method matchers miss.Anything in particular you'd like reviewers to focus on?
Anyone you would like to review specifically?
maybe @sambsnyd , @knutwannheden
Have you considered any alternatives or workarounds?
Any additional context
It's a draft because I haven't ported to the other JDK versions yet (or tested much beyond the unit tests), and figured I'd solicit feedback first in case there were directional concerns.
Checklist