This is related to https://bugs.openjdk.org/browse/JDK-8338678.
After the changes forJDK-8338678 it is possible to access type arguments of most erroneous types, but the type arguments are still not available for type arguments on enclosing types of qualified types.
In the example below, consider the type `B<C, D>.E<F>` where none of the referenced types exist. The ErrorType is `B.E<F>`, where the type arguments on B are not available in the model.
I wondered if it would make sense to consider modeling B as an ErrorType that is the enclosing type of the type E, and associating type arguments with B. I don't have a motivating use-case for this, it just seemed like a possible extension to the improvements inJDK-8338678.
===
class T extends M<N> {
A a;
B<C, D> b;
B<C, D>.E<F> c;
}
===
===
import static javax.lang.model.util.ElementFilter.fieldsIn;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ErrorType;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes("*")
public class MissingParameterizedTypeProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
private boolean first = true;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!first) {
return false;
}
first = false;
for (Element root : roundEnv.getRootElements()) {
ErrorType superClass = (ErrorType) ((TypeElement) root).getSuperclass();
processingEnv
.getMessager()
.printMessage(
Diagnostic.Kind.ERROR,
String.format(
"%s supertype: %s, arguments: %s, enclosing: %s",
root, superClass, superClass.getTypeArguments(), superClass.getEnclosingType()));
for (Element field : fieldsIn(root.getEnclosedElements())) {
ErrorType type = (ErrorType) field.asType();
processingEnv
.getMessager()
.printMessage(
Diagnostic.Kind.ERROR,
String.format(
"%s supertype: %s, arguments: %s, enclosing: %s",
field, type, type.getTypeArguments(), type.getEnclosingType()));
}
}
return false;
}
}
===
JDK 23:
error: T supertype: M<N>, arguments: N, enclosing: none
error: a supertype: A, arguments: , enclosing: none
error: b supertype: <any>, arguments: , enclosing: none
error: c supertype: <any>, arguments: , enclosing: none
JDK 24:
error: T supertype: M<N>, arguments: N, enclosing: none
error: a supertype: A, arguments: , enclosing: none
error: b supertype: B<C,D>, arguments: C,D, enclosing: none
error: c supertype: B.E<F>, arguments: F, enclosing: none
After the changes for
In the example below, consider the type `B<C, D>.E<F>` where none of the referenced types exist. The ErrorType is `B.E<F>`, where the type arguments on B are not available in the model.
I wondered if it would make sense to consider modeling B as an ErrorType that is the enclosing type of the type E, and associating type arguments with B. I don't have a motivating use-case for this, it just seemed like a possible extension to the improvements in
===
class T extends M<N> {
A a;
B<C, D> b;
B<C, D>.E<F> c;
}
===
===
import static javax.lang.model.util.ElementFilter.fieldsIn;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ErrorType;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes("*")
public class MissingParameterizedTypeProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
private boolean first = true;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!first) {
return false;
}
first = false;
for (Element root : roundEnv.getRootElements()) {
ErrorType superClass = (ErrorType) ((TypeElement) root).getSuperclass();
processingEnv
.getMessager()
.printMessage(
Diagnostic.Kind.ERROR,
String.format(
"%s supertype: %s, arguments: %s, enclosing: %s",
root, superClass, superClass.getTypeArguments(), superClass.getEnclosingType()));
for (Element field : fieldsIn(root.getEnclosedElements())) {
ErrorType type = (ErrorType) field.asType();
processingEnv
.getMessager()
.printMessage(
Diagnostic.Kind.ERROR,
String.format(
"%s supertype: %s, arguments: %s, enclosing: %s",
field, type, type.getTypeArguments(), type.getEnclosingType()));
}
}
return false;
}
}
===
JDK 23:
error: T supertype: M<N>, arguments: N, enclosing: none
error: a supertype: A, arguments: , enclosing: none
error: b supertype: <any>, arguments: , enclosing: none
error: c supertype: <any>, arguments: , enclosing: none
JDK 24:
error: T supertype: M<N>, arguments: N, enclosing: none
error: a supertype: A, arguments: , enclosing: none
error: b supertype: B<C,D>, arguments: C,D, enclosing: none
error: c supertype: B.E<F>, arguments: F, enclosing: none
- relates to
-
JDK-8338678 Erroneous parameterized type represented as <any>
- Resolved