Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
950f391
8354556: Expand value-based class warnings to java.lang.ref API
vicente-romero-oracle Apr 17, 2025
4c4aebe
minor fixes
vicente-romero-oracle Apr 21, 2025
0979978
Merge branch 'master' into JDK-8354556
vicente-romero-oracle Apr 21, 2025
d35ef50
fixing bug
vicente-romero-oracle Apr 21, 2025
ed64f22
removing the REQUIRES_IDENTITY flag
vicente-romero-oracle Apr 22, 2025
e6c17f7
removing requiresIdentityInternalType
vicente-romero-oracle Apr 22, 2025
d40e285
removing unnecessary changes
vicente-romero-oracle Apr 22, 2025
5a0b6bf
fixing bug
vicente-romero-oracle Apr 22, 2025
434dda7
only do extra analysis if lint warning enable
vicente-romero-oracle Apr 22, 2025
9f0407a
minor chantes to CreateSymbol
vicente-romero-oracle Apr 22, 2025
9f71ab7
Merge branch 'master' into JDK-8354556
lahodaj Apr 23, 2025
2697858
additional coverage for other uses of types
vicente-romero-oracle Apr 23, 2025
b4f5329
additional coverage for other uses of types
vicente-romero-oracle Apr 23, 2025
ac28815
Merge branch 'JDK-8354556' of https://github.com/vicente-romero-oracl…
vicente-romero-oracle Apr 24, 2025
5491f39
covering more cases plus refactoring in order to simplify the code
vicente-romero-oracle Apr 25, 2025
eb98145
First support for runtime visible and invisible type annotations in C…
lahodaj Apr 25, 2025
09b8331
refactoring
vicente-romero-oracle Apr 25, 2025
9d6af78
refactoring
vicente-romero-oracle Apr 25, 2025
4a6b9bc
more refactorings and tests
vicente-romero-oracle Apr 25, 2025
1c3cd61
more refactorings
vicente-romero-oracle Apr 25, 2025
84b52a6
removing unneeded changes
vicente-romero-oracle Apr 25, 2025
70e0311
additional refactorings
vicente-romero-oracle Apr 25, 2025
5e3acc9
final adjustments
vicente-romero-oracle Apr 25, 2025
27104b4
Improving the behavior of the PrintingProcessor.
lahodaj Apr 29, 2025
1134ffe
updating test
vicente-romero-oracle May 2, 2025
151908a
Merge branch 'master' into JDK-8354556
vicente-romero-oracle May 2, 2025
60f1f53
changes to test
vicente-romero-oracle May 2, 2025
ad7f617
addressing review comment
vicente-romero-oracle May 5, 2025
5d834ce
Merge branch 'master' into JDK-8354556
vicente-romero-oracle May 8, 2025
d52ec33
documentation and adding alias to lint categories
vicente-romero-oracle May 8, 2025
1ff2f2c
additional documentation changes and bug fixes
vicente-romero-oracle May 9, 2025
ea63116
fixing bugs, removing dead code
vicente-romero-oracle May 9, 2025
a9a5378
integrating code from Archie
vicente-romero-oracle May 10, 2025
3c6dacb
removing dead code
vicente-romero-oracle May 10, 2025
973307e
additional changes from Archie
vicente-romero-oracle May 10, 2025
63fd151
Update src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
vicente-romero-oracle May 10, 2025
22acaf2
Merge branch 'master' into JDK-8354556
vicente-romero-oracle May 13, 2025
a8b1130
Merge remote-tracking branch 'vicente/JDK-8354556' into JDK-8354556
lahodaj May 14, 2025
700c150
Adjustments, annotation filtering, adding more tests
lahodaj May 14, 2025
456ff25
Fixing build
lahodaj May 14, 2025
daed20f
Cleanup.
lahodaj May 14, 2025
696cd66
Merge remote-tracking branch 'upstream/master' into JDK-8356894
lahodaj May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import java.io.StringWriter;
import java.io.Writer;
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.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
Expand Down Expand Up @@ -991,6 +993,12 @@ private void addGenericAttributes(FeatureDescription desc, Consumer<? super Attr
if (desc.runtimeAnnotations != null && !desc.runtimeAnnotations.isEmpty()) {
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) {
Expand Down Expand Up @@ -1066,6 +1074,44 @@ private AnnotationValue createAttributeValue(Object value) {
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>

Expand Down Expand Up @@ -2213,7 +2259,10 @@ private boolean readAttribute(FeatureDescription feature, Attribute<?> attr) {
chd.permittedSubclasses = a.permittedSubclasses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList());
}
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
}

Expand Down Expand Up @@ -2270,6 +2319,31 @@ private AnnotationDescription annotation2Description(java.lang.classfile.Annotat

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>

protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
Expand Down Expand Up @@ -2391,6 +2465,8 @@ static abstract class FeatureDescription {
String versions = "";
List<AnnotationDescription> classAnnotations;
List<AnnotationDescription> runtimeAnnotations;
List<TypeAnnotationDescription> classTypeAnnotations;
List<TypeAnnotationDescription> runtimeTypeAnnotations;

protected void writeAttributes(Appendable output) throws IOException {
if (flags != 0)
Expand All @@ -2413,6 +2489,18 @@ protected void writeAttributes(Appendable output) throws IOException {
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) {
Expand Down Expand Up @@ -2442,6 +2530,14 @@ protected void readAttributes(LineBasedReader reader) {
if (inRuntimeAnnotations != null) {
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;
Expand All @@ -2454,6 +2550,8 @@ public int hashCode() {
hash = 89 * hash + Objects.hashCode(this.signature);
hash = 89 * hash + listHashCode(this.classAnnotations);
hash = 89 * hash + listHashCode(this.runtimeAnnotations);
hash = 89 * hash + listHashCode(this.classTypeAnnotations);
hash = 89 * hash + listHashCode(this.runtimeTypeAnnotations);
return hash;
}

Expand Down Expand Up @@ -2481,6 +2579,12 @@ public boolean equals(Object obj) {
if (!listEquals(this.runtimeAnnotations, other.runtimeAnnotations)) {
return false;
}
if (!listEquals(this.classTypeAnnotations, other.classTypeAnnotations)) {
return false;
}
if (!listEquals(this.runtimeTypeAnnotations, other.runtimeTypeAnnotations)) {
return false;
}
return true;
}

Expand Down Expand Up @@ -3285,6 +3389,8 @@ public int hashCode() {
hash = 59 * hash + Objects.hashCode(this.descriptor);
hash = 59 * hash + Objects.hashCode(this.thrownTypes);
hash = 59 * hash + Objects.hashCode(this.annotationDefaultValue);
hash = 59 * hash + Objects.hashCode(this.classParameterAnnotations);
hash = 59 * hash + Objects.hashCode(this.runtimeParameterAnnotations);
return hash;
}

Expand All @@ -3309,6 +3415,12 @@ public boolean equals(Object obj) {
if (!Objects.equals(this.annotationDefaultValue, other.annotationDefaultValue)) {
return false;
}
if (!Objects.equals(this.classParameterAnnotations, other.classParameterAnnotations)) {
return false;
}
if (!Objects.equals(this.runtimeParameterAnnotations, other.runtimeParameterAnnotations)) {
return false;
}
return true;
}

Expand Down Expand Up @@ -3636,6 +3748,40 @@ private static String dumpAnnotationValue(Object value) {
}
}

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 {
String type;
String constant;
Expand Down Expand Up @@ -3975,23 +4121,69 @@ public static List<AnnotationDescription> parseAnnotations(String encoded, int[]

private static AnnotationDescription parseAnnotation(String value, int[] 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]) == '(') {
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];

while (value.charAt(valuePointer[0]++) != '=');

String name = value.substring(nameStart, valuePointer[0] - 1);

attribute2Value.put(name, parseAnnotationValue(value, valuePointer));
}

valuePointer[0]++;

return 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]++) != '=');
while (value.charAt(valuePointer[0]++) != ':');

String name = value.substring(nameStart, valuePointer[0] - 1);

attribute2Value.put(name, parseAnnotationValue(value, valuePointer));
typePath.add(new TypeAnnotationDescription.TypePathComponentDesc(name, Integer.parseInt(readDigits(value, valuePointer))));
}

valuePointer[0]++;
}

return new AnnotationDescription(className, attribute2Value);
return new TypeAnnotationDescription(ann, targetInfo, typePath);
}
//</editor-fold>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ public static EnumSet<Flag> asFlagSet(long flags) {
*/
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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,8 @@ public <A extends Annotation> Attribute.Compound getAttribute(Class<A> annoType)
boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
return (anno.position.type == TargetType.CLASS_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;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,15 @@ public boolean isTerminal() {
// Enter a synthetic class that is used to mark classes in ct.sym.
// This class does not have a class file.
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
// 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;
sym.completer = Completer.NULL_COMPLETER;
sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
Expand Down Expand Up @@ -613,7 +619,7 @@ public <R, P> R accept(ElementVisitor<R, P> v, P p) {
valueBasedType = enterClass("jdk.internal.ValueBased");
valueBasedInternalType = enterSyntheticAnnotation("jdk.internal.ValueBased+Annotation");
requiresIdentityType = enterClass("jdk.internal.RequiresIdentity");
requiresIdentityInternalType = enterSyntheticAnnotation("jdk.internal.RequiresIdentity+Annotation");
requiresIdentityInternalType = enterSyntheticAnnotation(names.requiresIdentityInternal);
classDescType = enterClass("java.lang.constant.ClassDesc");
enumDescType = enterClass("java.lang.Enum$EnumDesc");
// For serialization lint checking
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ private <T extends Attribute.Compound> void annotateNow(Symbol toAnnotate,
&& types.isSameType(c.type, syms.restrictedType)) {
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();
Expand Down
Loading