-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
8
-
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 ----------
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 ----------