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

Incorrect annotation processor parameter names

XMLWordPrintable

    • x86_64
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_151"
      Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
      Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux 4.4.0-98-generic #121~14.04.1-Ubuntu SMP Wed Oct 11 11:54:55 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      When a file is compiled with the -parameters argument and the parameter names are later read by an annotation processor, the names are incorrect, shifted to the left starting at index 1.

      ie for a method with arguments:

      long personNo, java.util.Date birthDate, java.lang.String firstName, java.lang.String lastName

      the annotation processor sees:

      long personNo, java.util.Date firstName, java.lang.String lastName, java.lang.String arg3

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      # compile our annotation processor once
      javac ParameterPrintingProcessor.java

      # these show the correct argument names, compiled with and without -parameters argument, compiling both classes in a single invocation:
      javac -parameters -processor ParameterPrintingProcessor Person.java PersonDao.java
      rm Person.class PersonDao.class
      javac -processor ParameterPrintingProcessor Person.java PersonDao.java
      rm Person.class PersonDao.class

      # this is the bug, two step compilation as above with -parameters passed into first step, shows shifted/incorrect parameter names:
      javac -parameters Person.java
      # below is the actual invocation of javac where the bug lives, somehow reads saved parameter names from step above incorrectly
      # they are saved correctly above, because you can read them at runtime correctly
      javac -processor ParameterPrintingProcessor PersonDao.java


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expect the annotation processor to see:

      long personNo, java.util.Date birthDate, java.lang.String firstName, java.lang.String lastName
      ACTUAL -
      The annotation processor actually sees:

      long personNo, java.util.Date firstName, java.lang.String lastName, java.lang.String arg3

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      Person.java:

      public class Person {
          public Person(long personNo, java.util.Date birthDate, String firstName, String lastName) {}
      }

      PersonDao.java:

      import javax.annotation.processing.SupportedSourceVersion;
      import javax.lang.model.SourceVersion;
      @SupportedSourceVersion(SourceVersion.RELEASE_0)
      public interface PersonDao {
          Person getPerson();
      }

      ParameterPrintingProcessor.java:

      import javax.annotation.processing.AbstractProcessor;
      import javax.annotation.processing.RoundEnvironment;
      import javax.annotation.processing.SupportedAnnotationTypes;
      import javax.annotation.processing.SupportedSourceVersion;
      import javax.lang.model.SourceVersion;
      import javax.lang.model.element.*;
      import javax.lang.model.type.DeclaredType;
      import javax.lang.model.type.TypeKind;
      import javax.lang.model.type.TypeMirror;
      import javax.tools.Diagnostic;
      import java.util.List;
      import java.util.Set;

      @SupportedAnnotationTypes("javax.annotation.processing.SupportedSourceVersion")
      public class ParameterPrintingProcessor extends AbstractProcessor {
          @Override
          public SourceVersion getSupportedSourceVersion() {
              return SourceVersion.latestSupported();
          }

          @Override
          public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
              if (annotations.isEmpty() || roundEnv.processingOver())
                  return false; // done
              for (final Element element : roundEnv.getElementsAnnotatedWith(SupportedSourceVersion.class)) {
                  for(final Element method : ((TypeElement) element).getEnclosedElements()) {
                      if(method.getKind() != ElementKind.METHOD)
                          continue;
                      final TypeMirror returnType = ((ExecutableElement)method).getReturnType();
                      if(returnType.getKind() != TypeKind.DECLARED)
                          continue;
                      final List<? extends Element> methodsAndConstructors = ((TypeElement) ((DeclaredType) returnType).asElement()).getEnclosedElements();
                      processingEnv.getMessager().printMessage(Diagnostic.Kind.MANDATORY_WARNING,
                              methodsAndConstructors.stream().filter(e -> e.getKind() == ElementKind.CONSTRUCTOR && e.getModifiers().contains(Modifier.PUBLIC)).map(e -> e.toString() +
                                      ": '" + ((ExecutableElement) e).getParameters().stream().map(param -> param.asType() + " " + param.getSimpleName().toString()).collect(java.util.stream.Collectors.joining(", ")) + "'"
                              ).collect(java.util.stream.Collectors.joining(", ")));
                  }
              }
              return false;
          }
      }

      ---------- END SOURCE ----------

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: