forked from phoedos/pmd
[java] Fix #5097 - problem with unchecked conversion
This commit is contained in:
parent
f803aa36dc
commit
5931b6601c
@ -717,6 +717,12 @@ public final class TypeOps {
|
||||
// no unchecked warning.
|
||||
return allArgsAreUnboundedWildcards(sargs) ? Convertibility.UNCHECKED_NO_WARNING
|
||||
: Convertibility.UNCHECKED_WARNING;
|
||||
} else if (sargs.isEmpty()) {
|
||||
// C<T1...TN> <: |C|
|
||||
// JLS 4.10.2
|
||||
// unchecked conversion converts a raw type to a generic type
|
||||
// subtyping converts a generic type to its raw type
|
||||
return Convertibility.SUBTYPING;
|
||||
}
|
||||
|
||||
if (targs.size() != sargs.size()) {
|
||||
|
@ -13,14 +13,14 @@ import io.kotest.property.Exhaustive
|
||||
import io.kotest.property.checkAll
|
||||
import io.kotest.property.exhaustive.ints
|
||||
import io.kotest.property.forAll
|
||||
import net.sourceforge.pmd.lang.test.ast.shouldBeA
|
||||
import net.sourceforge.pmd.lang.java.ast.ParserTestCtx
|
||||
import net.sourceforge.pmd.lang.java.symbols.internal.UnresolvedClassStore
|
||||
import net.sourceforge.pmd.lang.java.symbols.internal.asm.createUnresolvedAsmSymbol
|
||||
import net.sourceforge.pmd.lang.java.types.TypeConversion.*
|
||||
import net.sourceforge.pmd.lang.java.types.TypeOps.Convertibility.*
|
||||
import net.sourceforge.pmd.lang.java.types.TypeConversion.capture
|
||||
import net.sourceforge.pmd.lang.java.types.TypeOps.Convertibility.UNCHECKED_NO_WARNING
|
||||
import net.sourceforge.pmd.lang.java.types.testdata.ComparableList
|
||||
import net.sourceforge.pmd.lang.java.types.testdata.SomeEnum
|
||||
import net.sourceforge.pmd.lang.test.ast.shouldBeA
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
@ -187,6 +187,9 @@ class SubtypingTest : FunSpec({
|
||||
Class shouldBeUncheckedSubtypeOf `Class{String}`
|
||||
|
||||
ts.STRING shouldBeSubtypeOf `Comparable{Wildcard}`
|
||||
|
||||
val unresolvedT = ts.createUnresolvedAsmSymbol("foo")
|
||||
unresolvedT[`?`] shouldBeSubtypeOf ts.rawType(unresolvedT)
|
||||
}
|
||||
|
||||
test("Test wildcard subtyping") {
|
||||
|
@ -702,4 +702,39 @@ class C {
|
||||
buildItem.methodType.symbol shouldBe buildItemDecl
|
||||
}
|
||||
}
|
||||
|
||||
parserTest("Unresolved type should also allow unchecked conversion") {
|
||||
// The problem here is that ConstraintViolation<?> is not convertible to ConstraintViolation,
|
||||
// because ConstraintViolation is not on the classpath.
|
||||
|
||||
val (acu, _) = parser.parseWithTypeInferenceSpy(
|
||||
"""
|
||||
import java.util.Set;
|
||||
class Foo {
|
||||
private void foo(ConstraintViolation constraintViolation) {
|
||||
constraintViolation.toString();
|
||||
}
|
||||
|
||||
public void foos(Set<ConstraintViolation<?>> constraintViolations) {
|
||||
constraintViolations.forEach(this::foo);
|
||||
}
|
||||
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
// val (foreach) = acu.methodCalls().toList()
|
||||
val constraintViolationT = acu.descendants(ASTClassType::class.java)
|
||||
.filter { it.simpleName == "ConstraintViolation" }
|
||||
.firstOrThrow().typeMirror.symbol as JClassSymbol
|
||||
val (fooDecl) = acu.methodDeclarations().toList { it.symbol }
|
||||
val (mref) = acu.descendants(ASTMethodReference::class.java).toList()
|
||||
|
||||
acu.withTypeDsl {
|
||||
mref.referencedMethod.symbol shouldBe fooDecl
|
||||
|
||||
mref shouldHaveType java.util.function.Consumer::class[constraintViolationT[`?`]]
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2218,4 +2218,36 @@ public class ObtainViaTest {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>#5097 UnusedPrivateMethod with unresolved target for method reference</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[package com.mytest;
|
||||
|
||||
import jakarta.validation.ConstraintViolation; //imported from jakarta.validation:jakarta.validation-api:3.0.2
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class UnusedPrivateMethodFalsePositive {
|
||||
//this does not trigger UnusedPrivateMethod
|
||||
private void doWork(List obj) {
|
||||
obj.toString();
|
||||
}
|
||||
|
||||
public void execute(Set<List<?>> listOfLists) {
|
||||
listOfLists.forEach(this::doWork);
|
||||
}
|
||||
|
||||
//BUT this does???
|
||||
//UnusedPrivateMethod - this as a false positive - but what is different?
|
||||
private void addValidationError(ConstraintViolation constraintViolation) {
|
||||
constraintViolation.toString();
|
||||
}
|
||||
|
||||
public void addValidationErrors(Set<ConstraintViolation<?>> constraintViolations) {
|
||||
constraintViolations.forEach(this::addValidationError);
|
||||
}
|
||||
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
Loading…
x
Reference in New Issue
Block a user