Skip to content

Commit 3249158

Browse files
committed
Fix type test util for anons
1 parent 5aa9a69 commit 3249158

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol;
1818
import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
1919
import net.sourceforge.pmd.lang.java.symbols.internal.UnresolvedClassStore;
20+
import net.sourceforge.pmd.util.OptionalBool;
2021

2122
/**
2223
* Public utilities to test the type of nodes.
@@ -106,8 +107,10 @@ public static boolean isA(final @NonNull String canonicalName, final @Nullable T
106107
AssertionUtil.requireParamNotNull("canonicalName", (Object) canonicalName);
107108
if (node == null) {
108109
return false;
109-
} else if (isExactlyA(canonicalName, node)) {
110-
return true;
110+
}
111+
OptionalBool exactMatch = isExactlyAOrAnon(canonicalName, node);
112+
if (exactMatch != OptionalBool.NO) {
113+
return exactMatch == OptionalBool.YES; // otherwise anon, and we return false
111114
}
112115

113116
JTypeMirror thisType = node.getTypeMirror();
@@ -125,13 +128,19 @@ public static boolean isA(final @NonNull String canonicalName, final @Nullable T
125128
TypeSystem ts = thisType.getTypeSystem();
126129
UnresolvedClassStore unresolvedStore = InternalApiBridge.getProcessor(node).getUnresolvedStore();
127130
@Nullable JTypeMirror otherType = TypesFromReflection.loadType(ts, canonicalName, unresolvedStore);
128-
if (otherType == null) {
131+
if (otherType == null
132+
|| otherType.isClassOrInterface() && ((JClassType) otherType).getSymbol().isAnonymousClass()) {
129133
return false; // we know isExactlyA(canonicalName, node); returned false
130134
}
131135

132136
return thisType.isSubtypeOf(otherType);
133137
}
134138

139+
private static boolean isAnonymous(JTypeMirror type) {
140+
JTypeDeclSymbol symbol = type.getSymbol();
141+
return symbol instanceof JClassSymbol && ((JClassSymbol) symbol).isAnonymousClass();
142+
}
143+
135144
private static boolean isAnnotationSuperType(String clazzName) {
136145
// then, the supertype may only be Object, j.l.Annotation
137146
// this is used e.g. by the typeIs function in XPath
@@ -210,25 +219,31 @@ private static boolean isExactlyA(@NonNull Class<?> klass, @Nullable JTypeDeclSy
210219
* @throws NullPointerException if the class name parameter is null
211220
*/
212221
public static boolean isExactlyA(@NonNull String canonicalName, final @Nullable TypeNode node) {
222+
return isExactlyAOrAnon(canonicalName, node) == OptionalBool.YES;
223+
}
224+
225+
private static OptionalBool isExactlyAOrAnon(@NonNull String canonicalName, final @Nullable TypeNode node) {
213226
AssertionUtil.requireParamNotNull("canonicalName", canonicalName);
214227
if (node == null) {
215-
return false;
228+
return OptionalBool.NO;
216229
}
217230

218231
JTypeDeclSymbol sym = node.getTypeMirror().getSymbol();
219232
if (sym == null || sym instanceof JTypeParameterSymbol) {
220-
return false;
233+
return OptionalBool.NO;
221234
}
222235

223236
canonicalName = StringUtils.deleteWhitespace(canonicalName);
224237

225238
JClassSymbol klass = (JClassSymbol) sym;
226239
String canonical = klass.getCanonicalName();
227-
return canonical != null && canonical.equals(canonicalName);
240+
if (canonical == null) {
241+
return OptionalBool.UNKNOWN; // anonymous
242+
}
243+
return OptionalBool.definitely(canonical.equals(canonicalName));
228244
}
229245

230246

231-
232247
private static boolean hasNoSubtypes(Class<?> clazz) {
233248
// Neither final nor an annotation. Enums & records have ACC_FINAL
234249
// Note: arrays have ACC_FINAL, but have subtypes by covariance

0 commit comments

Comments
 (0)