-
Notifications
You must be signed in to change notification settings - Fork 437
Don't write irrelevant annotations in .ajava files #6254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
59d2b4b
5e51863
6b54b61
b9a34bc
b947f16
f1b7064
9f4523b
8197f24
62e0f64
64e3dc1
e1882db
63f507c
f0eeae5
bfa0838
cc36287
92197b3
3104592
56fcd9f
b9bb730
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,4 +34,3 @@ annotation @G: @Retention(RUNTIME) | |
| boolean[] fieldC | ||
| int fieldD | ||
| int fieldE | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -190,15 +190,26 @@ public abstract class GenericAnnotatedTypeFactory< | |
| * <p>Although a {@code Class<?>} object exists for every element, this does not contain those | ||
| * {@code Class<?>} objects because the elements will be compared to TypeMirrors for which Class | ||
| * objects may not exist (they might not be on the classpath). | ||
| * | ||
| * <p>For their names, see {@link #relevantJavaTypeNames}. | ||
| */ | ||
| public final @Nullable Set<TypeMirror> relevantJavaTypes; | ||
|
|
||
| /** | ||
| * True if users may write type annotations on arrays. Ignored unless {@link #relevantJavaTypes} | ||
| * is non-null. | ||
| */ | ||
| public final @Nullable Set<String> relevantJavaTypeNames; | ||
|
|
||
| /** Whether users may write type annotations on arrays. */ | ||
| protected final boolean arraysAreRelevant; | ||
|
|
||
| /** | ||
| * Whether users may write type annotations on non-primitives (classes, arrays, etc.). This is | ||
| * redundant with the value of {@link #relevantJavaTypes} but is included for efficiency. | ||
| */ | ||
| protected final boolean nonprimitivesAreRelevant; | ||
|
|
||
| // Flow related fields | ||
|
|
||
| /** Should flow be used by default? */ | ||
|
|
@@ -368,16 +379,21 @@ protected GenericAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFlow) | |
| checker.getClass().getAnnotation(RelevantJavaTypes.class); | ||
| if (relevantJavaTypesAnno == null) { | ||
| this.relevantJavaTypes = null; | ||
| this.relevantJavaTypeNames = null; | ||
| this.arraysAreRelevant = true; | ||
| this.nonprimitivesAreRelevant = true; | ||
| } else { | ||
| Types types = getChecker().getTypeUtils(); | ||
| Elements elements = getElementUtils(); | ||
| Class<?>[] classes = relevantJavaTypesAnno.value(); | ||
| Set<TypeMirror> relevantJavaTypesTemp = new HashSet<>(MapsP.mapCapacity(classes.length)); | ||
| Set<String> relevantJavaTypeNamesTemp = new HashSet<>(MapsP.mapCapacity(classes.length)); | ||
| boolean arraysAreRelevantTemp = false; | ||
| boolean nonprimitivesAreRelevantTemp = false; | ||
| for (Class<?> clazz : classes) { | ||
| if (clazz == Object[].class) { | ||
| arraysAreRelevantTemp = true; | ||
| nonprimitivesAreRelevantTemp = true; | ||
| } else if (clazz.isArray()) { | ||
| throw new TypeSystemError( | ||
| "Don't use arrays other than Object[] in @RelevantJavaTypes on " | ||
|
|
@@ -386,10 +402,24 @@ protected GenericAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFlow) | |
| TypeMirror relevantType = TypesUtils.typeFromClass(clazz, types, elements); | ||
| TypeMirror erased = types.erasure(relevantType); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this will also complicate the specification of
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are 71 instances of 58 have 0 classes in a So, I don't think this is a heavy cost, either in time to compute the strings nor in space to store the strings. |
||
| relevantJavaTypesTemp.add(erased); | ||
| String typeString = erased.toString(); | ||
| relevantJavaTypeNamesTemp.add(typeString); | ||
| if (clazz.isPrimitive()) { | ||
| nonprimitivesAreRelevantTemp = true; | ||
| } else { | ||
|
Comment on lines
+407
to
+409
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
At Line 406-408, the code sets 💡 Suggested fix- if (clazz.isPrimitive()) {
- nonprimitivesAreRelevantTemp = true;
- } else {
+ if (!clazz.isPrimitive()) {
+ nonprimitivesAreRelevantTemp = true;
int dotIndex = typeString.lastIndexOf('.');
if (dotIndex != -1) {
// It's a fully-qualified name. Add the simple name as well.
// TODO: This might not handle a user writing a nested class like "Map.Entry".
relevantJavaTypeNamesTemp.add(typeString.substring(dotIndex + 1));
}
}Also applies to: 421-421 🤖 Prompt for AI Agents |
||
| int dotIndex = typeString.lastIndexOf('.'); | ||
| if (dotIndex != -1) { | ||
| // It's a fully-qualified name. Add the simple name as well. | ||
| // TODO: This might not handle a user writing a nested class like "Map.Entry". | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given the TODO comments here and about handling type variables (at Probably the easiest way to test that would be to add another annotation to the |
||
| relevantJavaTypeNamesTemp.add(typeString.substring(dotIndex + 1)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| this.relevantJavaTypes = Collections.unmodifiableSet(relevantJavaTypesTemp); | ||
| this.relevantJavaTypeNames = Collections.unmodifiableSet(relevantJavaTypeNamesTemp); | ||
| this.arraysAreRelevant = arraysAreRelevantTemp; | ||
| this.nonprimitivesAreRelevant = nonprimitivesAreRelevantTemp; | ||
| } | ||
|
|
||
| contractsUtils = createContractsFromMethod(); | ||
|
|
@@ -2497,9 +2527,9 @@ public final boolean isRelevant(TypeMirror tm) { | |
| if (tm.getKind() != TypeKind.PACKAGE && tm.getKind() != TypeKind.MODULE) { | ||
| tm = types.erasure(tm); | ||
| } | ||
| Boolean cachedResult = isRelevantCache.get(tm); | ||
| if (cachedResult != null) { | ||
| return cachedResult; | ||
| Boolean resultBoxed = isRelevantCache.get(tm); | ||
| if (resultBoxed != null) { | ||
| return resultBoxed; | ||
| } | ||
| boolean result = isRelevantImpl(tm); | ||
| isRelevantCache.put(tm, result); | ||
|
|
@@ -2531,6 +2561,9 @@ public final boolean isRelevant(AnnotatedTypeMirror tm) { | |
| * <p>Clients should never call this. Call {@link #isRelevant} instead. This is a helper method | ||
| * for {@link #isRelevant}. | ||
| * | ||
| * <p>This should <b>not</b> be called if {@code relevantJavaTypes == null || | ||
| * relevantJavaTypes.contains(tm))}. | ||
| * | ||
| * @param tm a type | ||
| * @return true if users can write type annotations from this type system on the given Java type | ||
| */ | ||
|
|
@@ -2618,6 +2651,43 @@ protected boolean isRelevantImpl(TypeMirror tm) { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns true if users can write type annotations from this type system directly on the given | ||
| * Java type. | ||
| * | ||
| * <p>For a compound type, returns true only if it is permitted to write a type qualifier on the | ||
| * top level of the compound type. That is, this method may return false, when it is possible to | ||
| * write type qualifiers on elements of the type. | ||
| * | ||
| * <p>Subclasses should override {@code #isRelevantImpl} instead of this method. | ||
| * | ||
| * @param type a fully-qualified or simple type; should not be an array (use {@link | ||
| * #arraysAreRelevant} instead) | ||
| * @return true if users can write type annotations from this type system directly on the given | ||
| * Java type | ||
| */ | ||
| public final boolean isRelevant(String type) { | ||
| return relevantJavaTypeNames == null || relevantJavaTypeNames.contains(type); | ||
| } | ||
|
|
||
| /** | ||
| * Returns true if users can write type annotations from this type system on array types. | ||
| * | ||
| * @return true if users can write type annotations from this type system on array types | ||
| */ | ||
| public final boolean arraysAreRelevant() { | ||
| return arraysAreRelevant; | ||
| } | ||
|
|
||
| /** | ||
| * Returns true if users can write type annotations from this type system on non-primitive types. | ||
| * | ||
| * @return true if users can write type annotations from this type system on non-primitive types | ||
| */ | ||
| public final boolean nonprimitivesAreRelevant() { | ||
| return nonprimitivesAreRelevant; | ||
| } | ||
|
|
||
| /** The cached message about relevant types. */ | ||
| private @MonotonicNonNull String irrelevantExtraMessage = null; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid hard failures in relevance filtering during AJAVA writing.
At Line 1123 and Line 1159,
annotationIsRelevantcan throw and abort file generation (anno.getParentNode().get()andthrow new Error(...)). This method is documented as conservative; unknown contexts should default to “relevant” instead of crashing.💡 Suggested fix
🤖 Prompt for AI Agents