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 ----------
|