When javac reads MethodParameters attributes it saves the parameter names in a field in MethodSymbol that is used the first time MethodSymbol#params() is called. When it reads Runtime{Visible,Invisible}ParameterAnnotations attributes, it calls MethodSymbol#params() to get the parameters' VarSymbols to attach the annotations to. So, if a method has both parameter annotations and a MethodParameters attribute, the parameter names are not processed correctly.
One possible fix is to buffer the method parameter annotations as they are read, and attach them to the corresponding VarSymbols only after the method's attributes are processed (including the MethodParameters attribute, if present).
Repro:
=== ./plugin/module-info.java
module parameterplugin {
requires transitive jdk.compiler;
provides com.sun.source.util.Plugin with parameterplugin.ParameterPlugin;
}
=== ./plugin/parameterplugin/ParameterPlugin.java
package parameterplugin;
import static java.util.stream.Collectors.joining;
import com.sun.source.tree.*;
import com.sun.source.util.*;
import javax.lang.model.element.*;
public class ParameterPlugin implements Plugin {
@Override
public String getName() {
return "ParameterPlugin";
}
@Override
public void init(JavacTask javacTask, String... strings) {
javacTask.addTaskListener(
new TaskListener() {
@Override
public void finished(TaskEvent e) {
if (e.getKind() != TaskEvent.Kind.ENTER) {
return;
}
new TreePathScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void aVoid) {
ExecutableElement e =
(ExecutableElement) Trees.instance(javacTask).getElement(getCurrentPath());
System.err.println(
e.getSimpleName()
+ e.getParameters()
.stream()
.map(p -> p.asType() + " " + p.getSimpleName())
.collect(joining(", ", "(", ")")));
return null;
}
}.scan(new TreePath(e.getCompilationUnit()), null);
}
});
}
}
=== ./A.java
class A {
@interface Anno {}
static void f(@Anno int a, int b) {}
static void g(int a, int b) {}
}
=== ./B.java
class B {
{
A.f(1, 2);
A.g(1, 2);
}
}
===
$ javac -fullversion
javac full version "9.0.1+11"
$ javac -parameters $(find . -name "*.java")
$ javac -parameters --processor-module-path plugin -Xplugin:ParameterPlugin B.java -sourcepath : -parameters
...
f(int arg0, int arg1)
g(int a, int b)
One possible fix is to buffer the method parameter annotations as they are read, and attach them to the corresponding VarSymbols only after the method's attributes are processed (including the MethodParameters attribute, if present).
Repro:
=== ./plugin/module-info.java
module parameterplugin {
requires transitive jdk.compiler;
provides com.sun.source.util.Plugin with parameterplugin.ParameterPlugin;
}
=== ./plugin/parameterplugin/ParameterPlugin.java
package parameterplugin;
import static java.util.stream.Collectors.joining;
import com.sun.source.tree.*;
import com.sun.source.util.*;
import javax.lang.model.element.*;
public class ParameterPlugin implements Plugin {
@Override
public String getName() {
return "ParameterPlugin";
}
@Override
public void init(JavacTask javacTask, String... strings) {
javacTask.addTaskListener(
new TaskListener() {
@Override
public void finished(TaskEvent e) {
if (e.getKind() != TaskEvent.Kind.ENTER) {
return;
}
new TreePathScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void aVoid) {
ExecutableElement e =
(ExecutableElement) Trees.instance(javacTask).getElement(getCurrentPath());
System.err.println(
e.getSimpleName()
+ e.getParameters()
.stream()
.map(p -> p.asType() + " " + p.getSimpleName())
.collect(joining(", ", "(", ")")));
return null;
}
}.scan(new TreePath(e.getCompilationUnit()), null);
}
});
}
}
=== ./A.java
class A {
@interface Anno {}
static void f(@Anno int a, int b) {}
static void g(int a, int b) {}
}
=== ./B.java
class B {
{
A.f(1, 2);
A.g(1, 2);
}
}
===
$ javac -fullversion
javac full version "9.0.1+11"
$ javac -parameters $(find . -name "*.java")
$ javac -parameters --processor-module-path plugin -Xplugin:ParameterPlugin B.java -sourcepath : -parameters
...
f(int arg0, int arg1)
g(int a, int b)
- duplicates
-
JDK-8007720 Names are not load correctly for method parameters if the parameters have annotations
-
- Resolved
-