Merge branch 'pr-5340'
This commit is contained in:
commit
e60f460e02
@ -27,6 +27,7 @@ This is a {{ site.pmd.release_type }} release.
|
|||||||
* [#5329](https://github.com/pmd/pmd/issues/5329): \[java] Type inference issue with unknown method ref in call chain
|
* [#5329](https://github.com/pmd/pmd/issues/5329): \[java] Type inference issue with unknown method ref in call chain
|
||||||
* java-bestpractices
|
* java-bestpractices
|
||||||
* [#5083](https://github.com/pmd/pmd/issues/5083): \[java] UnusedPrivateMethod false positive when method reference has no target type
|
* [#5083](https://github.com/pmd/pmd/issues/5083): \[java] UnusedPrivateMethod false positive when method reference has no target type
|
||||||
|
* [#5097](https://github.com/pmd/pmd/issues/5097): \[java] UnusedPrivateMethod FP with raw type missing from the classpath
|
||||||
* [#5318](https://github.com/pmd/pmd/issues/5318): \[java] PreserveStackTraceRule: false-positive on Pattern Matching with instanceof
|
* [#5318](https://github.com/pmd/pmd/issues/5318): \[java] PreserveStackTraceRule: false-positive on Pattern Matching with instanceof
|
||||||
* java-performance
|
* java-performance
|
||||||
* [#5287](https://github.com/pmd/pmd/issues/5287): \[java] TooFewBranchesForSwitch false-positive with switch using list of case constants
|
* [#5287](https://github.com/pmd/pmd/issues/5287): \[java] TooFewBranchesForSwitch false-positive with switch using list of case constants
|
||||||
|
@ -717,6 +717,12 @@ public final class TypeOps {
|
|||||||
// no unchecked warning.
|
// no unchecked warning.
|
||||||
return allArgsAreUnboundedWildcards(sargs) ? Convertibility.UNCHECKED_NO_WARNING
|
return allArgsAreUnboundedWildcards(sargs) ? Convertibility.UNCHECKED_NO_WARNING
|
||||||
: Convertibility.UNCHECKED_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()) {
|
if (targs.size() != sargs.size()) {
|
||||||
|
@ -13,14 +13,14 @@ import io.kotest.property.Exhaustive
|
|||||||
import io.kotest.property.checkAll
|
import io.kotest.property.checkAll
|
||||||
import io.kotest.property.exhaustive.ints
|
import io.kotest.property.exhaustive.ints
|
||||||
import io.kotest.property.forAll
|
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.ast.ParserTestCtx
|
||||||
import net.sourceforge.pmd.lang.java.symbols.internal.UnresolvedClassStore
|
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.symbols.internal.asm.createUnresolvedAsmSymbol
|
||||||
import net.sourceforge.pmd.lang.java.types.TypeConversion.*
|
import net.sourceforge.pmd.lang.java.types.TypeConversion.capture
|
||||||
import net.sourceforge.pmd.lang.java.types.TypeOps.Convertibility.*
|
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.ComparableList
|
||||||
import net.sourceforge.pmd.lang.java.types.testdata.SomeEnum
|
import net.sourceforge.pmd.lang.java.types.testdata.SomeEnum
|
||||||
|
import net.sourceforge.pmd.lang.test.ast.shouldBeA
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +187,9 @@ class SubtypingTest : FunSpec({
|
|||||||
Class shouldBeUncheckedSubtypeOf `Class{String}`
|
Class shouldBeUncheckedSubtypeOf `Class{String}`
|
||||||
|
|
||||||
ts.STRING shouldBeSubtypeOf `Comparable{Wildcard}`
|
ts.STRING shouldBeSubtypeOf `Comparable{Wildcard}`
|
||||||
|
|
||||||
|
val unresolvedT = ts.createUnresolvedAsmSymbol("foo")
|
||||||
|
unresolvedT[`?`] shouldBeSubtypeOf ts.rawType(unresolvedT)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("Test wildcard subtyping") {
|
test("Test wildcard subtyping") {
|
||||||
|
@ -704,4 +704,39 @@ class C {
|
|||||||
buildItem.methodType.symbol shouldBe buildItemDecl
|
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,6 +2218,38 @@ public class ObtainViaTest {
|
|||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-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-code>
|
<test-code>
|
||||||
<description>UnusedPrivateMethod #5113</description>
|
<description>UnusedPrivateMethod #5113</description>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user