8356894: Adjust CreateSymbols to properly handle the newly added @jdk.internal.RequiresIdentity
Reviewed-by: vromero, liach
This commit is contained in:
parent
99e01301cd
commit
9d9e41f5b4
@ -46,6 +46,8 @@ import java.io.OutputStream;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
|
import java.lang.classfile.TypeAnnotation.TargetInfo;
|
||||||
|
import java.lang.classfile.TypeAnnotation.TypePathComponent;
|
||||||
import java.lang.classfile.attribute.*;
|
import java.lang.classfile.attribute.*;
|
||||||
import java.lang.classfile.constantpool.ClassEntry;
|
import java.lang.classfile.constantpool.ClassEntry;
|
||||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||||
@ -991,6 +993,12 @@ public class CreateSymbols {
|
|||||||
if (desc.runtimeAnnotations != null && !desc.runtimeAnnotations.isEmpty()) {
|
if (desc.runtimeAnnotations != null && !desc.runtimeAnnotations.isEmpty()) {
|
||||||
builder.accept(RuntimeVisibleAnnotationsAttribute.of(createAnnotations(desc.runtimeAnnotations)));
|
builder.accept(RuntimeVisibleAnnotationsAttribute.of(createAnnotations(desc.runtimeAnnotations)));
|
||||||
}
|
}
|
||||||
|
if (desc.classTypeAnnotations != null && !desc.classTypeAnnotations.isEmpty()) {
|
||||||
|
builder.accept(RuntimeInvisibleTypeAnnotationsAttribute.of(createTypeAnnotations(desc.classTypeAnnotations)));
|
||||||
|
}
|
||||||
|
if (desc.runtimeTypeAnnotations != null && !desc.runtimeTypeAnnotations.isEmpty()) {
|
||||||
|
builder.accept(RuntimeVisibleTypeAnnotationsAttribute.of(createTypeAnnotations(desc.runtimeTypeAnnotations)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Annotation> createAnnotations(List<AnnotationDescription> desc) {
|
private List<Annotation> createAnnotations(List<AnnotationDescription> desc) {
|
||||||
@ -1066,6 +1074,44 @@ public class CreateSymbols {
|
|||||||
default -> throw new IllegalArgumentException(value.getClass().getName());
|
default -> throw new IllegalArgumentException(value.getClass().getName());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TypeAnnotation> createTypeAnnotations(List<TypeAnnotationDescription> desc) {
|
||||||
|
return desc.stream().map(this::createTypeAnnotation).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeAnnotation createTypeAnnotation(TypeAnnotationDescription desc) {
|
||||||
|
Annotation baseAnn = createAnnotation(desc.annotation);
|
||||||
|
TargetInfo targetInfo = switch ((String) desc.targetInfo.get("targetType")) {
|
||||||
|
case "CLASS_TYPE_PARAMETER" -> //TODO: test!
|
||||||
|
TargetInfo.ofClassTypeParameter((int) desc.targetInfo.get("typeParameterIndex"));
|
||||||
|
case "METHOD_TYPE_PARAMETER" ->
|
||||||
|
TargetInfo.ofMethodTypeParameter((int) desc.targetInfo.get("typeParameterIndex"));
|
||||||
|
case "CLASS_EXTENDS" ->
|
||||||
|
TargetInfo.ofClassExtends((int) desc.targetInfo.get("supertypeIndex"));
|
||||||
|
case "CLASS_TYPE_PARAMETER_BOUND" ->
|
||||||
|
TargetInfo.ofClassTypeParameterBound((int) desc.targetInfo.get("typeParameterIndex"),
|
||||||
|
(int) desc.targetInfo.get("boundIndex"));
|
||||||
|
case "METHOD_TYPE_PARAMETER_BOUND" ->
|
||||||
|
TargetInfo.ofMethodTypeParameterBound((int) desc.targetInfo.get("typeParameterIndex"),
|
||||||
|
(int) desc.targetInfo.get("boundIndex"));
|
||||||
|
case "METHOD_RETURN" ->
|
||||||
|
TargetInfo.ofMethodReturn();
|
||||||
|
case "METHOD_RECEIVER" ->
|
||||||
|
TargetInfo.ofMethodReceiver();
|
||||||
|
case "METHOD_FORMAL_PARAMETER" ->
|
||||||
|
TargetInfo.ofMethodFormalParameter((int) desc.targetInfo.get("formalParameterIndex"));
|
||||||
|
case "THROWS" ->
|
||||||
|
TargetInfo.ofThrows((int) desc.targetInfo.get("throwsTargetIndex"));
|
||||||
|
case "FIELD" ->
|
||||||
|
TargetInfo.ofField();
|
||||||
|
case String targetType ->
|
||||||
|
throw new IllegalStateException("Unsupported targetType: " + targetType);
|
||||||
|
};
|
||||||
|
|
||||||
|
List<TypePathComponent> typePath = desc.typePath.stream().map(d -> TypePathComponent.of(TypePathComponent.Kind.valueOf(d.tag()), d.index())).toList();
|
||||||
|
|
||||||
|
return TypeAnnotation.of(targetInfo, typePath, baseAnn);
|
||||||
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
@ -2213,7 +2259,10 @@ public class CreateSymbols {
|
|||||||
chd.permittedSubclasses = a.permittedSubclasses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList());
|
chd.permittedSubclasses = a.permittedSubclasses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
case ModuleMainClassAttribute a -> ((ModuleHeaderDescription) feature).moduleMainClass = a.mainClass().asInternalName();
|
case ModuleMainClassAttribute a -> ((ModuleHeaderDescription) feature).moduleMainClass = a.mainClass().asInternalName();
|
||||||
case RuntimeVisibleTypeAnnotationsAttribute a -> {/* do nothing for now */}
|
case RuntimeInvisibleTypeAnnotationsAttribute a ->
|
||||||
|
feature.classTypeAnnotations = typeAnnotations2Descriptions(a.annotations());
|
||||||
|
case RuntimeVisibleTypeAnnotationsAttribute a ->
|
||||||
|
feature.runtimeTypeAnnotations = typeAnnotations2Descriptions(a.annotations());
|
||||||
default -> throw new IllegalArgumentException("Unhandled attribute: " + attr.attributeName()); // Do nothing
|
default -> throw new IllegalArgumentException("Unhandled attribute: " + attr.attributeName()); // Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2270,6 +2319,31 @@ public class CreateSymbols {
|
|||||||
|
|
||||||
return new AnnotationDescription(annotationType, values);
|
return new AnnotationDescription(annotationType, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TypeAnnotationDescription> typeAnnotations2Descriptions(List<TypeAnnotation> annos) {
|
||||||
|
return annos.stream().map(ta -> {
|
||||||
|
TypeAnnotationDescription desc = new TypeAnnotationDescription();
|
||||||
|
desc.annotation = annotation2Description(ta.annotation());
|
||||||
|
desc.targetInfo = new HashMap<>();
|
||||||
|
desc.targetInfo.put("targetType", ta.targetInfo().targetType().name());
|
||||||
|
switch (ta.targetInfo()) {
|
||||||
|
case TypeAnnotation.TypeParameterTarget tpt -> desc.targetInfo.put("typeParameterIndex", tpt.typeParameterIndex());
|
||||||
|
case TypeAnnotation.SupertypeTarget st -> desc.targetInfo.put("supertypeIndex", st.supertypeIndex());
|
||||||
|
case TypeAnnotation.TypeParameterBoundTarget tpbt -> {
|
||||||
|
desc.targetInfo.put("typeParameterIndex", tpbt.typeParameterIndex());
|
||||||
|
desc.targetInfo.put("boundIndex", tpbt.boundIndex());
|
||||||
|
}
|
||||||
|
case TypeAnnotation.EmptyTarget _ -> {
|
||||||
|
// nothing to write
|
||||||
|
}
|
||||||
|
case TypeAnnotation.FormalParameterTarget fpt -> desc.targetInfo.put("formalParameterIndex", fpt.formalParameterIndex());
|
||||||
|
case TypeAnnotation.ThrowsTarget tt -> desc.targetInfo.put("throwsTargetIndex", tt.throwsTargetIndex());
|
||||||
|
default -> throw new IllegalStateException(ta.targetInfo().targetType().name());
|
||||||
|
}
|
||||||
|
desc.typePath = ta.targetPath().stream().map(tpc -> new TypeAnnotationDescription.TypePathComponentDesc(tpc.typePathKind().name(), tpc.typeArgumentIndex())).toList();
|
||||||
|
return desc;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
|
protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
|
||||||
@ -2391,6 +2465,8 @@ public class CreateSymbols {
|
|||||||
String versions = "";
|
String versions = "";
|
||||||
List<AnnotationDescription> classAnnotations;
|
List<AnnotationDescription> classAnnotations;
|
||||||
List<AnnotationDescription> runtimeAnnotations;
|
List<AnnotationDescription> runtimeAnnotations;
|
||||||
|
List<TypeAnnotationDescription> classTypeAnnotations;
|
||||||
|
List<TypeAnnotationDescription> runtimeTypeAnnotations;
|
||||||
|
|
||||||
protected void writeAttributes(Appendable output) throws IOException {
|
protected void writeAttributes(Appendable output) throws IOException {
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
@ -2413,6 +2489,18 @@ public class CreateSymbols {
|
|||||||
output.append(quote(a.toString(), false));
|
output.append(quote(a.toString(), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (classTypeAnnotations != null && !classTypeAnnotations.isEmpty()) {
|
||||||
|
output.append(" classTypeAnnotations ");
|
||||||
|
for (TypeAnnotationDescription a : classTypeAnnotations) {
|
||||||
|
output.append(quote(a.toString(), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (runtimeTypeAnnotations != null && !runtimeTypeAnnotations.isEmpty()) {
|
||||||
|
output.append(" runtimeTypeAnnotations ");
|
||||||
|
for (TypeAnnotationDescription a : runtimeTypeAnnotations) {
|
||||||
|
output.append(quote(a.toString(), false));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldIgnore(String baselineVersion, String version) {
|
protected boolean shouldIgnore(String baselineVersion, String version) {
|
||||||
@ -2442,6 +2530,14 @@ public class CreateSymbols {
|
|||||||
if (inRuntimeAnnotations != null) {
|
if (inRuntimeAnnotations != null) {
|
||||||
runtimeAnnotations = parseAnnotations(inRuntimeAnnotations, new int[1]);
|
runtimeAnnotations = parseAnnotations(inRuntimeAnnotations, new int[1]);
|
||||||
}
|
}
|
||||||
|
String inClassTypeAnnotations = reader.attributes.get("classTypeAnnotations");
|
||||||
|
if (inClassTypeAnnotations != null) {
|
||||||
|
classTypeAnnotations = parseTypeAnnotations(inClassTypeAnnotations, new int[1]);
|
||||||
|
}
|
||||||
|
String inRuntimeTypeAnnotations = reader.attributes.get("runtimeTypeAnnotations");
|
||||||
|
if (inRuntimeTypeAnnotations != null) {
|
||||||
|
runtimeTypeAnnotations = parseTypeAnnotations(inRuntimeTypeAnnotations, new int[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean read(LineBasedReader reader) throws IOException;
|
public abstract boolean read(LineBasedReader reader) throws IOException;
|
||||||
@ -2454,6 +2550,8 @@ public class CreateSymbols {
|
|||||||
hash = 89 * hash + Objects.hashCode(this.signature);
|
hash = 89 * hash + Objects.hashCode(this.signature);
|
||||||
hash = 89 * hash + listHashCode(this.classAnnotations);
|
hash = 89 * hash + listHashCode(this.classAnnotations);
|
||||||
hash = 89 * hash + listHashCode(this.runtimeAnnotations);
|
hash = 89 * hash + listHashCode(this.runtimeAnnotations);
|
||||||
|
hash = 89 * hash + listHashCode(this.classTypeAnnotations);
|
||||||
|
hash = 89 * hash + listHashCode(this.runtimeTypeAnnotations);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2481,6 +2579,12 @@ public class CreateSymbols {
|
|||||||
if (!listEquals(this.runtimeAnnotations, other.runtimeAnnotations)) {
|
if (!listEquals(this.runtimeAnnotations, other.runtimeAnnotations)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!listEquals(this.classTypeAnnotations, other.classTypeAnnotations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!listEquals(this.runtimeTypeAnnotations, other.runtimeTypeAnnotations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3285,6 +3389,8 @@ public class CreateSymbols {
|
|||||||
hash = 59 * hash + Objects.hashCode(this.descriptor);
|
hash = 59 * hash + Objects.hashCode(this.descriptor);
|
||||||
hash = 59 * hash + Objects.hashCode(this.thrownTypes);
|
hash = 59 * hash + Objects.hashCode(this.thrownTypes);
|
||||||
hash = 59 * hash + Objects.hashCode(this.annotationDefaultValue);
|
hash = 59 * hash + Objects.hashCode(this.annotationDefaultValue);
|
||||||
|
hash = 59 * hash + Objects.hashCode(this.classParameterAnnotations);
|
||||||
|
hash = 59 * hash + Objects.hashCode(this.runtimeParameterAnnotations);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3309,6 +3415,12 @@ public class CreateSymbols {
|
|||||||
if (!Objects.equals(this.annotationDefaultValue, other.annotationDefaultValue)) {
|
if (!Objects.equals(this.annotationDefaultValue, other.annotationDefaultValue)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!Objects.equals(this.classParameterAnnotations, other.classParameterAnnotations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.runtimeParameterAnnotations, other.runtimeParameterAnnotations)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3636,6 +3748,40 @@ public class CreateSymbols {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class TypeAnnotationDescription {
|
||||||
|
AnnotationDescription annotation;
|
||||||
|
Map<String, Object> targetInfo;
|
||||||
|
List<TypePathComponentDesc> typePath;
|
||||||
|
|
||||||
|
public TypeAnnotationDescription() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeAnnotationDescription(AnnotationDescription annotation, Map<String, Object> targetInfo, List<TypePathComponentDesc> typePath) {
|
||||||
|
this.annotation = annotation;
|
||||||
|
this.targetInfo = targetInfo;
|
||||||
|
this.typePath = typePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return annotation.toString() + "{" + targetInfo.entrySet().stream().map(e -> e.getKey() + "=" + quote(printValue(e.getValue()), false)).collect(Collectors.joining(",")) + "}" +
|
||||||
|
(!typePath.isEmpty() ? "[" + typePath.stream().map(desc -> desc.tag + ":" + desc.index).collect(Collectors.joining(",")) + "]" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String printValue(Object obj) {
|
||||||
|
if (obj instanceof String s) {
|
||||||
|
return "\"" + s + "\"";
|
||||||
|
} else if (obj instanceof Integer i) {
|
||||||
|
return "I" + String.valueOf(i);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unsupported value: " + obj.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: path
|
||||||
|
record TypePathComponentDesc(String tag, int index) {}
|
||||||
|
}
|
||||||
|
|
||||||
static final class EnumConstant {
|
static final class EnumConstant {
|
||||||
String type;
|
String type;
|
||||||
String constant;
|
String constant;
|
||||||
@ -3975,10 +4121,19 @@ public class CreateSymbols {
|
|||||||
|
|
||||||
private static AnnotationDescription parseAnnotation(String value, int[] valuePointer) {
|
private static AnnotationDescription parseAnnotation(String value, int[] valuePointer) {
|
||||||
String className = className(value, valuePointer);
|
String className = className(value, valuePointer);
|
||||||
Map<String, Object> attribute2Value = new HashMap<>();
|
Map<String, Object> attribute2Value = Map.of();
|
||||||
|
|
||||||
if (valuePointer[0] < value.length() && value.charAt(valuePointer[0]) == '(') {
|
if (valuePointer[0] < value.length() && value.charAt(valuePointer[0]) == '(') {
|
||||||
while (value.charAt(valuePointer[0]) != ')') {
|
attribute2Value = parseMap(value, valuePointer, ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AnnotationDescription(className, attribute2Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> parseMap(String value, int[] valuePointer, char endBracket) {
|
||||||
|
Map<String, Object> attribute2Value = new HashMap<>();
|
||||||
|
|
||||||
|
while (value.charAt(valuePointer[0]) != endBracket) {
|
||||||
int nameStart = ++valuePointer[0];
|
int nameStart = ++valuePointer[0];
|
||||||
|
|
||||||
while (value.charAt(valuePointer[0]++) != '=');
|
while (value.charAt(valuePointer[0]++) != '=');
|
||||||
@ -3989,9 +4144,46 @@ public class CreateSymbols {
|
|||||||
}
|
}
|
||||||
|
|
||||||
valuePointer[0]++;
|
valuePointer[0]++;
|
||||||
|
|
||||||
|
return attribute2Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AnnotationDescription(className, attribute2Value);
|
public static List<TypeAnnotationDescription> parseTypeAnnotations(String encoded, int[] pointer) {
|
||||||
|
List<TypeAnnotationDescription> result = new ArrayList<>();
|
||||||
|
|
||||||
|
while (pointer[0] < encoded.length() && encoded.charAt(pointer[0]) == '@') {
|
||||||
|
pointer[0]++;
|
||||||
|
result.add(parseTypeAnnotation(encoded, pointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TypeAnnotationDescription parseTypeAnnotation(String value, int[] valuePointer) {
|
||||||
|
AnnotationDescription ann = parseAnnotation(value, valuePointer);
|
||||||
|
Map<String, Object> targetInfo = Map.of();
|
||||||
|
|
||||||
|
if (valuePointer[0] < value.length() && value.charAt(valuePointer[0]) == '{') {
|
||||||
|
targetInfo = parseMap(value, valuePointer, '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TypeAnnotationDescription.TypePathComponentDesc> typePath = new ArrayList<>();
|
||||||
|
|
||||||
|
if (valuePointer[0] < value.length() && value.charAt(valuePointer[0]) == '[') {
|
||||||
|
while (value.charAt(valuePointer[0]) != ']') {
|
||||||
|
int nameStart = ++valuePointer[0];
|
||||||
|
|
||||||
|
while (value.charAt(valuePointer[0]++) != ':');
|
||||||
|
|
||||||
|
String name = value.substring(nameStart, valuePointer[0] - 1);
|
||||||
|
|
||||||
|
typePath.add(new TypeAnnotationDescription.TypePathComponentDesc(name, Integer.parseInt(readDigits(value, valuePointer))));
|
||||||
|
}
|
||||||
|
|
||||||
|
valuePointer[0]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TypeAnnotationDescription(ann, targetInfo, typePath);
|
||||||
}
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
|
@ -399,6 +399,11 @@ public class Flags {
|
|||||||
*/
|
*/
|
||||||
public static final long RESTRICTED = 1L<<62; // MethodSymbols
|
public static final long RESTRICTED = 1L<<62; // MethodSymbols
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate parameters that require identity.
|
||||||
|
*/
|
||||||
|
public static final long REQUIRES_IDENTITY = 1L<<62; // VarSymbols (parameters)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to indicate type annotations have been queued for field initializers.
|
* Flag to indicate type annotations have been queued for field initializers.
|
||||||
*/
|
*/
|
||||||
|
@ -969,7 +969,8 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
|
|||||||
boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
|
boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
|
||||||
return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
|
return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
|
||||||
anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
|
anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
|
||||||
anno.position.parameter_index == index;
|
anno.position.parameter_index == index &&
|
||||||
|
anno.type.tsym.flatName() != name.table.names.requiresIdentityInternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,9 +384,15 @@ public class Symtab {
|
|||||||
// Enter a synthetic class that is used to mark classes in ct.sym.
|
// Enter a synthetic class that is used to mark classes in ct.sym.
|
||||||
// This class does not have a class file.
|
// This class does not have a class file.
|
||||||
private Type enterSyntheticAnnotation(String name) {
|
private Type enterSyntheticAnnotation(String name) {
|
||||||
|
return enterSyntheticAnnotation(names.fromString(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter a synthetic class that is used to mark classes in ct.sym.
|
||||||
|
// This class does not have a class file.
|
||||||
|
private Type enterSyntheticAnnotation(Name name) {
|
||||||
// for now, leave the module null, to prevent problems from synthesizing the
|
// for now, leave the module null, to prevent problems from synthesizing the
|
||||||
// existence of a class in any specific module, including noModule
|
// existence of a class in any specific module, including noModule
|
||||||
ClassType type = (ClassType)enterClass(java_base, names.fromString(name)).type;
|
ClassType type = (ClassType)enterClass(java_base, name).type;
|
||||||
ClassSymbol sym = (ClassSymbol)type.tsym;
|
ClassSymbol sym = (ClassSymbol)type.tsym;
|
||||||
sym.completer = Completer.NULL_COMPLETER;
|
sym.completer = Completer.NULL_COMPLETER;
|
||||||
sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
|
sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
|
||||||
@ -613,7 +619,7 @@ public class Symtab {
|
|||||||
valueBasedType = enterClass("jdk.internal.ValueBased");
|
valueBasedType = enterClass("jdk.internal.ValueBased");
|
||||||
valueBasedInternalType = enterSyntheticAnnotation("jdk.internal.ValueBased+Annotation");
|
valueBasedInternalType = enterSyntheticAnnotation("jdk.internal.ValueBased+Annotation");
|
||||||
requiresIdentityType = enterClass("jdk.internal.RequiresIdentity");
|
requiresIdentityType = enterClass("jdk.internal.RequiresIdentity");
|
||||||
requiresIdentityInternalType = enterSyntheticAnnotation("jdk.internal.RequiresIdentity+Annotation");
|
requiresIdentityInternalType = enterSyntheticAnnotation(names.requiresIdentityInternal);
|
||||||
classDescType = enterClass("java.lang.constant.ClassDesc");
|
classDescType = enterClass("java.lang.constant.ClassDesc");
|
||||||
enumDescType = enterClass("java.lang.Enum$EnumDesc");
|
enumDescType = enterClass("java.lang.Enum$EnumDesc");
|
||||||
// For serialization lint checking
|
// For serialization lint checking
|
||||||
|
@ -384,6 +384,12 @@ public class Annotate {
|
|||||||
&& types.isSameType(c.type, syms.restrictedType)) {
|
&& types.isSameType(c.type, syms.restrictedType)) {
|
||||||
toAnnotate.flags_field |= Flags.RESTRICTED;
|
toAnnotate.flags_field |= Flags.RESTRICTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!c.type.isErroneous()
|
||||||
|
&& toAnnotate.kind == VAR
|
||||||
|
&& types.isSameType(c.type, syms.requiresIdentityType)) {
|
||||||
|
toAnnotate.flags_field |= Flags.REQUIRES_IDENTITY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<T> buf = List.nil();
|
List<T> buf = List.nil();
|
||||||
|
@ -5729,14 +5729,14 @@ public class Check {
|
|||||||
if (!argExps.isEmpty() && msym instanceof MethodSymbol ms && ms.params != null) {
|
if (!argExps.isEmpty() && msym instanceof MethodSymbol ms && ms.params != null) {
|
||||||
VarSymbol lastParam = ms.params.head;
|
VarSymbol lastParam = ms.params.head;
|
||||||
for (VarSymbol param: ms.params) {
|
for (VarSymbol param: ms.params) {
|
||||||
if (param.attribute(syms.requiresIdentityType.tsym) != null && argExps.head.type.isValueBased()) {
|
if ((param.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
|
||||||
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
|
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
|
||||||
}
|
}
|
||||||
lastParam = param;
|
lastParam = param;
|
||||||
argExps = argExps.tail;
|
argExps = argExps.tail;
|
||||||
}
|
}
|
||||||
while (argExps != null && !argExps.isEmpty() && lastParam != null) {
|
while (argExps != null && !argExps.isEmpty() && lastParam != null) {
|
||||||
if (lastParam.attribute(syms.requiresIdentityType.tsym) != null && argExps.head.type.isValueBased()) {
|
if ((lastParam.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
|
||||||
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
|
lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
|
||||||
}
|
}
|
||||||
argExps = argExps.tail;
|
argExps = argExps.tail;
|
||||||
@ -5813,7 +5813,7 @@ public class Check {
|
|||||||
SymbolMetadata sm = t.tsym.getMetadata();
|
SymbolMetadata sm = t.tsym.getMetadata();
|
||||||
if (sm != null && !t.getTypeArguments().isEmpty()) {
|
if (sm != null && !t.getTypeArguments().isEmpty()) {
|
||||||
if (sm.getTypeAttributes().stream()
|
if (sm.getTypeAttributes().stream()
|
||||||
.filter(ta -> ta.type.tsym == syms.requiresIdentityType.tsym &&
|
.filter(ta -> isRequiresIdentityAnnotation(ta.type.tsym) &&
|
||||||
t.getTypeArguments().get(ta.position.parameter_index) != null &&
|
t.getTypeArguments().get(ta.position.parameter_index) != null &&
|
||||||
t.getTypeArguments().get(ta.position.parameter_index).isValueBased()).findAny().isPresent()) {
|
t.getTypeArguments().get(ta.position.parameter_index).isValueBased()).findAny().isPresent()) {
|
||||||
requiresWarning = true;
|
requiresWarning = true;
|
||||||
@ -5838,11 +5838,16 @@ public class Check {
|
|||||||
}
|
}
|
||||||
if (sm != null)
|
if (sm != null)
|
||||||
sm.getTypeAttributes().stream()
|
sm.getTypeAttributes().stream()
|
||||||
.filter(ta -> (ta.type.tsym == syms.requiresIdentityType.tsym) &&
|
.filter(ta -> isRequiresIdentityAnnotation(ta.type.tsym) &&
|
||||||
typeParamTrees.get(ta.position.parameter_index).type != null &&
|
typeParamTrees.get(ta.position.parameter_index).type != null &&
|
||||||
typeParamTrees.get(ta.position.parameter_index).type.isValueBased())
|
typeParamTrees.get(ta.position.parameter_index).type.isValueBased())
|
||||||
.forEach(ta -> lint.logIfEnabled(typeParamTrees.get(ta.position.parameter_index).pos(),
|
.forEach(ta -> lint.logIfEnabled(typeParamTrees.get(ta.position.parameter_index).pos(),
|
||||||
CompilerProperties.LintWarnings.AttemptToUseValueBasedWhereIdentityExpected));
|
CompilerProperties.LintWarnings.AttemptToUseValueBasedWhereIdentityExpected));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRequiresIdentityAnnotation(TypeSymbol annoType) {
|
||||||
|
return annoType == syms.requiresIdentityType.tsym ||
|
||||||
|
annoType.flatName() == syms.requiresIdentityInternalType.tsym.flatName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1556,6 +1556,9 @@ public class ClassReader {
|
|||||||
} else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
|
} else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
|
||||||
Assert.check(sym.kind == MTH);
|
Assert.check(sym.kind == MTH);
|
||||||
sym.flags_field |= RESTRICTED;
|
sym.flags_field |= RESTRICTED;
|
||||||
|
} else if (proxy.type.tsym.flatName() == syms.requiresIdentityInternalType.tsym.flatName()) {
|
||||||
|
Assert.check(sym.kind == VAR);
|
||||||
|
sym.flags_field |= REQUIRES_IDENTITY;
|
||||||
} else {
|
} else {
|
||||||
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
|
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
|
||||||
target = proxy;
|
target = proxy;
|
||||||
@ -1572,6 +1575,9 @@ public class ClassReader {
|
|||||||
} else if (proxy.type.tsym == syms.restrictedType.tsym) {
|
} else if (proxy.type.tsym == syms.restrictedType.tsym) {
|
||||||
Assert.check(sym.kind == MTH);
|
Assert.check(sym.kind == MTH);
|
||||||
sym.flags_field |= RESTRICTED;
|
sym.flags_field |= RESTRICTED;
|
||||||
|
} else if (proxy.type.tsym == syms.requiresIdentityType.tsym) {
|
||||||
|
Assert.check(sym.kind == VAR);
|
||||||
|
sym.flags_field |= REQUIRES_IDENTITY;
|
||||||
}
|
}
|
||||||
proxies.append(proxy);
|
proxies.append(proxy);
|
||||||
}
|
}
|
||||||
@ -2809,9 +2815,8 @@ public class ClassReader {
|
|||||||
params.append(param);
|
params.append(param);
|
||||||
if (parameterAnnotations != null) {
|
if (parameterAnnotations != null) {
|
||||||
ParameterAnnotations annotations = parameterAnnotations[annotationIndex];
|
ParameterAnnotations annotations = parameterAnnotations[annotationIndex];
|
||||||
if (annotations != null && annotations.proxies != null
|
if (annotations != null && annotations.proxies != null) {
|
||||||
&& !annotations.proxies.isEmpty()) {
|
attachAnnotations(param, annotations.proxies);
|
||||||
annotate.normal(new AnnotationCompleter(param, annotations.proxies));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nameIndexLvt += Code.width(t);
|
nameIndexLvt += Code.width(t);
|
||||||
|
@ -228,6 +228,9 @@ public class Names {
|
|||||||
public final Name enumSwitch;
|
public final Name enumSwitch;
|
||||||
public final Name enumConstant;
|
public final Name enumConstant;
|
||||||
|
|
||||||
|
// special annotation names
|
||||||
|
public final Name requiresIdentityInternal;
|
||||||
|
|
||||||
public final Name.Table table;
|
public final Name.Table table;
|
||||||
|
|
||||||
@SuppressWarnings("this-escape")
|
@SuppressWarnings("this-escape")
|
||||||
@ -412,6 +415,9 @@ public class Names {
|
|||||||
typeSwitch = fromString("typeSwitch");
|
typeSwitch = fromString("typeSwitch");
|
||||||
enumSwitch = fromString("enumSwitch");
|
enumSwitch = fromString("enumSwitch");
|
||||||
enumConstant = fromString("enumConstant");
|
enumConstant = fromString("enumConstant");
|
||||||
|
|
||||||
|
// special annotations:
|
||||||
|
requiresIdentityInternal = fromString("jdk.internal.RequiresIdentity+Annotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Name.Table createTable(Options options) {
|
protected Name.Table createTable(Options options) {
|
||||||
|
166
test/langtools/tools/javac/platform/RequiresIdentityTest.java
Normal file
166
test/langtools/tools/javac/platform/RequiresIdentityTest.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8356894
|
||||||
|
* @summary Verify source level checks are performed properly
|
||||||
|
* @library /tools/lib
|
||||||
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
|
* jdk.compiler/com.sun.tools.javac.util
|
||||||
|
* @build toolbox.ToolBox toolbox.JavacTask
|
||||||
|
* @run main RequiresIdentityTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import toolbox.TestRunner;
|
||||||
|
import toolbox.JavacTask;
|
||||||
|
import toolbox.Task;
|
||||||
|
import toolbox.ToolBox;
|
||||||
|
|
||||||
|
public class RequiresIdentityTest extends TestRunner {
|
||||||
|
|
||||||
|
ToolBox tb;
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
new RequiresIdentityTest().runTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
RequiresIdentityTest() {
|
||||||
|
super(System.err);
|
||||||
|
tb = new ToolBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTests() throws Exception {
|
||||||
|
runTests(m -> new Object[] { Paths.get(m.getName()) });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReleaseWorksAsCurrentVersion(Path base) throws Exception {
|
||||||
|
Path src = base.resolve("src");
|
||||||
|
Path classes = base.resolve("classes");
|
||||||
|
tb.writeJavaFiles(src,
|
||||||
|
"""
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
void test() {
|
||||||
|
WeakHashMap<Optional<Integer>, Object> m = null;
|
||||||
|
m.put(Optional.empty(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
Files.createDirectories(classes);
|
||||||
|
|
||||||
|
var expectedErrors = List.of(
|
||||||
|
"Test.java:6:20: compiler.warn.attempt.to.use.value.based.where.identity.expected",
|
||||||
|
"Test.java:7:29: compiler.warn.attempt.to.use.value.based.where.identity.expected",
|
||||||
|
"2 warnings"
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
var actualErrors =
|
||||||
|
new JavacTask(tb)
|
||||||
|
.options("-XDrawDiagnostics")
|
||||||
|
.outdir(classes)
|
||||||
|
.files(tb.findJavaFiles(src))
|
||||||
|
.run()
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
if (!expectedErrors.equals(actualErrors)) {
|
||||||
|
throw new AssertionError("Incorrect errors, expected: " + List.of(expectedErrors) +
|
||||||
|
", actual: " + actualErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var actualErrors =
|
||||||
|
new JavacTask(tb)
|
||||||
|
.options("--release", System.getProperty("java.specification.version"),
|
||||||
|
"-XDrawDiagnostics")
|
||||||
|
.outdir(classes)
|
||||||
|
.files(tb.findJavaFiles(src))
|
||||||
|
.run()
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
if (!expectedErrors.equals(actualErrors)) {
|
||||||
|
throw new AssertionError("Incorrect errors, expected: " + List.of(expectedErrors) +
|
||||||
|
", actual: " + actualErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModel(Path base) throws Exception {
|
||||||
|
{
|
||||||
|
List<String> printed =
|
||||||
|
new JavacTask(tb)
|
||||||
|
.options("-Xprint")
|
||||||
|
.classes("java.util.WeakHashMap")
|
||||||
|
.run()
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
|
||||||
|
printed.removeIf(l -> !l.contains("put(") && !l.contains("class WeakHashMap<"));
|
||||||
|
|
||||||
|
List<String> expected = List.of(
|
||||||
|
"public class WeakHashMap<@jdk.internal.RequiresIdentity K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {",
|
||||||
|
" public V put(@jdk.internal.RequiresIdentity sealed K key,"
|
||||||
|
);
|
||||||
|
if (!expected.equals(printed)) {
|
||||||
|
throw new AssertionError("Expected: " + expected +
|
||||||
|
", but got: " + printed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
List<String> printed =
|
||||||
|
new JavacTask(tb)
|
||||||
|
.options("--release", System.getProperty("java.specification.version"),
|
||||||
|
"-Xprint")
|
||||||
|
.classes("java.util.WeakHashMap")
|
||||||
|
.run()
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.STDOUT);
|
||||||
|
|
||||||
|
printed.removeIf(l -> !l.contains("put(") && !l.contains("class WeakHashMap<"));
|
||||||
|
|
||||||
|
List<String> expected = List.of(
|
||||||
|
"public class WeakHashMap<K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {",
|
||||||
|
" public V put(sealed K arg0,"
|
||||||
|
);
|
||||||
|
if (!expected.equals(printed)) {
|
||||||
|
throw new AssertionError("Expected: " + expected +
|
||||||
|
", but got: " + printed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
RequiresIdentityTest.java:16:18: compiler.warn.attempt.to.use.value.based.where.identity.expected
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
1 error
|
||||||
|
1 warning
|
@ -21,19 +21,6 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @bug 8072480 8277106 8331027
|
|
||||||
* @summary Unit test for CreateSymbols
|
|
||||||
* @modules java.compiler
|
|
||||||
* jdk.compiler/com.sun.tools.javac.api
|
|
||||||
* jdk.compiler/com.sun.tools.javac.jvm
|
|
||||||
* jdk.compiler/com.sun.tools.javac.main
|
|
||||||
* jdk.compiler/com.sun.tools.javac.util
|
|
||||||
* @clean *
|
|
||||||
* @run main/othervm CreateSymbolsTest
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -21,6 +21,19 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8072480 8277106 8331027
|
||||||
|
* @summary Unit test for CreateSymbols
|
||||||
|
* @modules java.compiler
|
||||||
|
* jdk.compiler/com.sun.tools.javac.api
|
||||||
|
* jdk.compiler/com.sun.tools.javac.jvm
|
||||||
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
|
* jdk.compiler/com.sun.tools.javac.util
|
||||||
|
* @clean *
|
||||||
|
* @run main/othervm CreateSymbolsTest
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
@ -908,6 +921,109 @@ public class CreateSymbolsTestImpl {
|
|||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTypeAnnotations() throws Exception {
|
||||||
|
doPrintElementTest("""
|
||||||
|
package t;
|
||||||
|
public class T {
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.*;
|
||||||
|
public class T<@AnnInvisible @AnnVisible E extends @AnnInvisible @AnnVisible ArrayList<@AnnInvisible @AnnVisible ArrayList>> extends @AnnInvisible @AnnVisible ArrayList {
|
||||||
|
public @AnnInvisible @AnnVisible List<@AnnInvisible @AnnVisible E> field;
|
||||||
|
public <@AnnInvisible @AnnVisible M extends @AnnInvisible @AnnVisible ArrayList<@AnnInvisible @AnnVisible ArrayList>> @AnnInvisible @AnnVisible List<@AnnInvisible @AnnVisible M> convert(@AnnInvisible @AnnVisible T<E> this, @AnnInvisible @AnnVisible M e1, @AnnInvisible @AnnVisible List<@AnnInvisible @AnnVisible E> e2) throws @AnnInvisible @AnnVisible IllegalStateException, @AnnInvisible @AnnVisible IllegalArgumentException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@interface AnnVisible {
|
||||||
|
}
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@interface AnnInvisible {
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.T",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
|
||||||
|
public class T {
|
||||||
|
|
||||||
|
public T();
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.T",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
|
||||||
|
public class T<@t.AnnInvisible @t.AnnVisible E extends java.util.@t.AnnInvisible @t.AnnVisible ArrayList<java.util.@t.AnnInvisible @t.AnnVisible ArrayList>> extends java.util.@t.AnnInvisible @t.AnnVisible ArrayList {
|
||||||
|
public java.util.@t.AnnInvisible @t.AnnVisible List<@t.AnnInvisible @t.AnnVisible E> field;
|
||||||
|
|
||||||
|
public T();
|
||||||
|
|
||||||
|
public <@t.AnnInvisible @t.AnnVisible M extends java.util.@t.AnnInvisible @t.AnnVisible ArrayList<java.util.@t.AnnInvisible @t.AnnVisible ArrayList>> java.util.@t.AnnInvisible @t.AnnVisible List<@t.AnnInvisible @t.AnnVisible M> convert(@t.AnnInvisible @t.AnnVisible M arg0,
|
||||||
|
java.util.@t.AnnInvisible @t.AnnVisible List<@t.AnnInvisible @t.AnnVisible E> arg1) throws java.lang.@t.AnnInvisible @t.AnnVisible IllegalStateException,\s
|
||||||
|
java.lang.@t.AnnInvisible @t.AnnVisible IllegalArgumentException;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParameterAnnotations() throws Exception {
|
||||||
|
doPrintElementTest("""
|
||||||
|
package t;
|
||||||
|
public class T {
|
||||||
|
public void test(int p1, int p2) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.*;
|
||||||
|
public class T {
|
||||||
|
public void test(@AnnVisible int p1, @AnnInvisible int p2) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@interface AnnVisible {
|
||||||
|
}
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@interface AnnInvisible {
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.T",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
|
||||||
|
public class T {
|
||||||
|
|
||||||
|
public T();
|
||||||
|
|
||||||
|
public void test(int arg0,
|
||||||
|
int arg1);
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"t.T",
|
||||||
|
"""
|
||||||
|
package t;
|
||||||
|
|
||||||
|
public class T {
|
||||||
|
|
||||||
|
public T();
|
||||||
|
|
||||||
|
public void test(@t.AnnVisible int arg0,
|
||||||
|
@t.AnnInvisible int arg1);
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
void doTestData(String data,
|
void doTestData(String data,
|
||||||
String... code) throws Exception {
|
String... code) throws Exception {
|
||||||
String testClasses = System.getProperty("test.classes");
|
String testClasses = System.getProperty("test.classes");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user