Skip to content

Commit f7920e7

Browse files
committed
Make behavior of isUnresolved in TypeOps more consistent
wrt arrays. Make new methods that say in their name whether they treat array as unresolved or not. Both behaviors are desirable in different cases.
1 parent c7014fc commit f7920e7

5 files changed

Lines changed: 134 additions & 20 deletions

File tree

pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UseDiamondOperatorRule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public Object visit(ASTConstructorCall ctorCall, Object data) {
7171
ASTTypeArguments targs = newTypeNode.getTypeArguments();
7272
if (targs != null && targs.isDiamond()
7373
// if unresolved we can't know whether the class is generic or not
74-
|| TypeOps.isUnresolved(newType)) {
74+
|| TypeOps.hasUnresolvedSymbol(newType)) {
7575
return null;
7676
}
7777

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

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ Convertibility isConvertible(@NonNull JTypeMirror t, @NonNull JTypeMirror s, boo
634634
return isConvertible(t, lower);
635635
}
636636
// otherwise fallthrough
637-
} else if (hasUnresolvedSymbol(t) && t instanceof JClassType) {
637+
} else if (hasUnresolvedSymbol(t)) {
638638
// This also considers types with an unresolved symbol
639639
// subtypes of (nearly) anything. This allows them to
640640
// pass bound checks on type variables.
@@ -1797,7 +1797,7 @@ public static Set<JTypeMirror> mostSpecific(Collection<? extends JTypeMirror> se
17971797
vLoop:
17981798
for (JTypeMirror v : set) {
17991799
for (JTypeMirror w : set) {
1800-
if (!w.equals(v) && !hasUnresolvedSymbol(w)) {
1800+
if (!w.equals(v) && !hasUnresolvedSymbolOrArray(w)) {
18011801
Convertibility isConvertible = isConvertiblePure(w, v);
18021802
if (isConvertible.bySubtyping()
18031803
// This last case covers unchecked conversion. It is made antisymmetric by the
@@ -2079,7 +2079,8 @@ public static boolean areRelated(@NonNull JTypeMirror t, JTypeMirror s) {
20792079

20802080
/**
20812081
* Returns true if the type is {@link TypeSystem#UNKNOWN},
2082-
* {@link TypeSystem#ERROR}, or its symbol is unresolved.
2082+
* {@link TypeSystem#ERROR}, or a class type with unresolved
2083+
* symbol.
20832084
*
20842085
* @param t Non-null type
20852086
*
@@ -2089,38 +2090,70 @@ public static boolean isUnresolved(@NonNull JTypeMirror t) {
20892090
return isSpecialUnresolved(t) || hasUnresolvedSymbol(t);
20902091
}
20912092

2093+
/**
2094+
* Returns true if the type is {@link TypeSystem#UNKNOWN},
2095+
* or {@link TypeSystem#ERROR}, or a class type with unresolved
2096+
* symbol, or an array of such types.
2097+
*
2098+
* @param t Non-null type
2099+
*
2100+
* @throws NullPointerException if the parameter is null
2101+
*/
2102+
public static boolean isUnresolvedOrArray(@NonNull JTypeMirror t) {
2103+
return isSpecialUnresolvedOrArray(t) || hasUnresolvedSymbolOrArray(t);
2104+
}
2105+
2106+
/**
2107+
* Returns true if the type is {@link TypeSystem#UNKNOWN},
2108+
* or {@link TypeSystem#ERROR}.
2109+
*
2110+
* @param t Non-null type
2111+
*
2112+
* @throws NullPointerException if the parameter is null
2113+
*/
20922114
public static boolean isSpecialUnresolved(@NonNull JTypeMirror t) {
20932115
TypeSystem ts = t.getTypeSystem();
20942116
return t == ts.UNKNOWN || t == ts.ERROR;
20952117
}
20962118

2119+
/**
2120+
* Returns true if the type is {@link TypeSystem#UNKNOWN},
2121+
* or {@link TypeSystem#ERROR}, or an array of such types.
2122+
*
2123+
* @param t Non-null type
2124+
*
2125+
* @throws NullPointerException if the parameter is null
2126+
*/
2127+
public static boolean isSpecialUnresolvedOrArray(@Nullable JTypeMirror t) {
2128+
return t == null
2129+
|| isSpecialUnresolved(t)
2130+
|| t instanceof JArrayType && isSpecialUnresolved(((JArrayType) t).getElementType());
2131+
}
2132+
20972133
/**
20982134
* Return true if the argument is a {@link JClassType} with
2099-
* {@linkplain JClassSymbol#isUnresolved() an unresolved symbol} or
2100-
* a {@link JArrayType} whose element type matches the first criterion.
2135+
* {@linkplain JClassSymbol#isUnresolved() an unresolved symbol}.
21012136
*/
21022137
public static boolean hasUnresolvedSymbol(@Nullable JTypeMirror t) {
2138+
return t instanceof JClassType && t.getSymbol().isUnresolved();
2139+
}
2140+
2141+
/**
2142+
* Return true if the argument is a {@link JClassType} with
2143+
* {@linkplain JClassSymbol#isUnresolved() an unresolved symbol},
2144+
* or an array whose element type has an unresolved symbol.
2145+
*/
2146+
public static boolean hasUnresolvedSymbolOrArray(@Nullable JTypeMirror t) {
21032147
if (!(t instanceof JClassType)) {
21042148
return t instanceof JArrayType && hasUnresolvedSymbol(((JArrayType) t).getElementType());
21052149
}
2106-
return t.getSymbol() != null && t.getSymbol().isUnresolved();
2150+
return hasUnresolvedSymbol(t);
21072151
}
21082152

21092153
public static boolean isUnresolvedOrNull(@Nullable JTypeMirror t) {
21102154
return t == null || isUnresolved(t);
21112155
}
21122156

2113-
/**
2114-
* Return true if the type is null, (*unknown*), (*error*), or an array
2115-
* of unknown or error type.
2116-
*/
2117-
public static boolean isSpecialUnresolvedOrArray(@Nullable JTypeMirror t) {
2118-
return t == null
2119-
|| isSpecialUnresolved(t)
2120-
|| t instanceof JArrayType && isSpecialUnresolved(((JArrayType) t).getElementType());
2121-
}
2122-
2123-
21242157
public static @Nullable JTypeMirror getArrayComponent(@Nullable JTypeMirror t) {
21252158
return t instanceof JArrayType ? ((JArrayType) t).getComponentType() : null;
21262159
}

pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/PhaseOverloadSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ private boolean doInfer(JMethodSig m1, JMethodSig m2) {
210210

211211
private @NonNull OptionalBool unresolvedTypeFallback(JTypeMirror si, JTypeMirror ti, ExprMirror argExpr) {
212212
JTypeMirror standalone = argExpr.getStandaloneType();
213-
if (standalone != null && TypeOps.isUnresolved(standalone)) {
213+
if (TypeOps.hasUnresolvedSymbolOrArray(standalone)) {
214214
if (standalone.equals(si)) {
215215
return YES;
216216
} else if (standalone.equals(ti)) {

pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeGenerationUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ val TypeSystem.allTypesGen: Arb<JTypeMirror>
3838
fun TypeSystem.subtypesArb() =
3939
Arb.pair(refTypeGen, refTypeGen)
4040
.filter { (t, s) -> t.isConvertibleTo(s).bySubtyping() }
41-
.filter { (t, s) -> !TypeOps.hasUnresolvedSymbol(t) && !TypeOps.hasUnresolvedSymbol(s) }
41+
.filter { (t, s) -> !TypeOps.hasUnresolvedSymbolOrArray(t) && !TypeOps.hasUnresolvedSymbolOrArray(s) }
4242

4343
infix fun Boolean.implies(v: () -> Boolean): Boolean = !this || v()
4444

pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeOpsTest.kt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.types
77
import io.kotest.core.spec.style.FunSpec
88
import io.kotest.matchers.collections.shouldContainExactly
99
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
10+
import io.kotest.matchers.shouldBe
1011
import io.kotest.property.Arb
1112
import io.kotest.property.arbitrary.shuffle
1213
import io.kotest.property.checkAll
@@ -131,6 +132,86 @@ class Foo {
131132
methodId shouldHaveType barT[`?`]
132133
}
133134
}
135+
136+
test("isSpecialUnresolved") {
137+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
138+
TypeOps.isSpecialUnresolved(unresolved) shouldBe false
139+
TypeOps.isSpecialUnresolved(unresolved.toArray()) shouldBe false
140+
TypeOps.isSpecialUnresolved(unresolved.toArray(3)) shouldBe false
141+
142+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
143+
TypeOps.isSpecialUnresolved(ty) shouldBe true
144+
TypeOps.isSpecialUnresolved(ty.toArray()) shouldBe false
145+
TypeOps.isSpecialUnresolved(ty.toArray(3)) shouldBe false
146+
}
147+
}
148+
149+
test("isSpecialUnresolvedOrArray") {
150+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
151+
TypeOps.isSpecialUnresolvedOrArray(unresolved) shouldBe false
152+
TypeOps.isSpecialUnresolvedOrArray(unresolved.toArray()) shouldBe false
153+
TypeOps.isSpecialUnresolvedOrArray(unresolved.toArray(3)) shouldBe false
154+
155+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
156+
TypeOps.isSpecialUnresolvedOrArray(ty) shouldBe true
157+
TypeOps.isSpecialUnresolvedOrArray(ty.toArray()) shouldBe true
158+
TypeOps.isSpecialUnresolvedOrArray(ty.toArray(3)) shouldBe true
159+
}
160+
}
161+
162+
test("hasUnresolvedSymbol") {
163+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
164+
TypeOps.hasUnresolvedSymbol(unresolved) shouldBe true
165+
TypeOps.hasUnresolvedSymbol(unresolved.toArray()) shouldBe false
166+
TypeOps.hasUnresolvedSymbol(unresolved.toArray(3)) shouldBe false
167+
168+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
169+
TypeOps.hasUnresolvedSymbol(ty) shouldBe false
170+
TypeOps.hasUnresolvedSymbol(ty.toArray()) shouldBe false
171+
TypeOps.hasUnresolvedSymbol(ty.toArray(3)) shouldBe false
172+
}
173+
}
174+
175+
176+
test("hasUnresolvedSymbolOrArray") {
177+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
178+
TypeOps.hasUnresolvedSymbolOrArray(unresolved) shouldBe true
179+
TypeOps.hasUnresolvedSymbolOrArray(unresolved.toArray()) shouldBe true
180+
TypeOps.hasUnresolvedSymbolOrArray(unresolved.toArray(3)) shouldBe true
181+
182+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
183+
TypeOps.hasUnresolvedSymbolOrArray(ty) shouldBe false
184+
TypeOps.hasUnresolvedSymbolOrArray(ty.toArray()) shouldBe false
185+
TypeOps.hasUnresolvedSymbolOrArray(ty.toArray(3)) shouldBe false
186+
}
187+
}
188+
189+
190+
test("isUnresolved") {
191+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
192+
TypeOps.isUnresolved(unresolved) shouldBe true
193+
TypeOps.isUnresolved(unresolved.toArray()) shouldBe false
194+
TypeOps.isUnresolved(unresolved.toArray(3)) shouldBe false
195+
196+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
197+
TypeOps.isUnresolved(ty) shouldBe true
198+
TypeOps.isUnresolved(ty.toArray()) shouldBe false
199+
TypeOps.isUnresolved(ty.toArray(3)) shouldBe false
200+
}
201+
}
202+
203+
test("isUnresolvedOrArray") {
204+
val unresolved = ts.declaration(ts.createUnresolvedAsmSymbol("Unknown"))
205+
TypeOps.isUnresolvedOrArray(unresolved) shouldBe true
206+
TypeOps.isUnresolvedOrArray(unresolved.toArray()) shouldBe true
207+
TypeOps.isUnresolvedOrArray(unresolved.toArray(3)) shouldBe true
208+
209+
for (ty in listOf(ts.UNKNOWN, ts.ERROR)) {
210+
TypeOps.isUnresolvedOrArray(ty) shouldBe true
211+
TypeOps.isUnresolvedOrArray(ty.toArray()) shouldBe true
212+
TypeOps.isUnresolvedOrArray(ty.toArray(3)) shouldBe true
213+
}
214+
}
134215
}
135216
}
136217

0 commit comments

Comments
 (0)