Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8189708

class reading issue with named and annotated parameters

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 9
    • tools
    • None

      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)

            cushon Liam Miller-Cushon
            cushon Liam Miller-Cushon
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: