Try to fix bug with capture
Spot a bug with nested expressions. Skipping instantiation is disabled until later
This commit is contained in:
@ -382,25 +382,20 @@ public final class TypeOps {
|
||||
|
||||
private static JTypeMirror upperBound(JTypeMirror type) {
|
||||
if (type instanceof JWildcardType) {
|
||||
return upperBound(((JWildcardType) type).asUpperBound());
|
||||
} else if (type instanceof JTypeVar && ((JTypeVar) type).isCaptured()) {
|
||||
return upperBound(((JTypeVar) type).getUpperBound());
|
||||
return ((JWildcardType) type).asUpperBound();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static JTypeMirror lowerBound(JTypeMirror type) {
|
||||
if (type instanceof JWildcardType) {
|
||||
return lowerBound(((JWildcardType) type).asLowerBound());
|
||||
} else if (type instanceof JTypeVar && ((JTypeVar) type).isCaptured()) {
|
||||
return lowerBound(((JTypeVar) type).getLowerBound());
|
||||
return ((JWildcardType) type).asLowerBound();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static boolean isTypeRange(JTypeMirror s) {
|
||||
return s instanceof JWildcardType
|
||||
|| s instanceof JTypeVar && ((JTypeVar) s).isCaptured();
|
||||
return s instanceof JWildcardType;
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,11 +97,11 @@ final class ExprCheckHelper {
|
||||
// now if the return type of the arg is polymorphic and unsolved,
|
||||
// there are some additional bounds on our own infCtx
|
||||
|
||||
// FIXME if the argument is not compatible we'll fail resolution
|
||||
// altogether, though if we're in invocation phase we should
|
||||
// preserve the CT-decl
|
||||
|
||||
checker.checkExprConstraint(infCtx, mostSpecific.getReturnType(), targetType);
|
||||
|
||||
// fixme this fails to set the inferred type of arguments
|
||||
// if we skip invocation on the outer expr
|
||||
if (phase.isInvocation()) {
|
||||
infCtx.addInstantiationListener(
|
||||
infCtx.freeVarsIn(mostSpecific.getReturnType()),
|
||||
|
@ -448,7 +448,7 @@ final class ExprOps {
|
||||
TypeSystem ts = sig.getTypeSystem();
|
||||
if ("getClass".equals(sig.getName()) && sig.getDeclaringType().equals(ts.OBJECT)) {
|
||||
if (erasedReceiverType != null) {
|
||||
return sig.internalApi().withReturnType(getClassReturn(erasedReceiverType, ts));
|
||||
return sig.internalApi().withReturnType(getClassReturn(erasedReceiverType, ts)).internalApi().markAsAdapted();
|
||||
}
|
||||
}
|
||||
return sig;
|
||||
|
@ -247,13 +247,11 @@ public final class Infer {
|
||||
if (isReturnTypeFinished(m)) {
|
||||
assert assertReturnIsGround(m);
|
||||
|
||||
// todo this appears duplicated
|
||||
m = ExprOps.adaptGetClass(m, site.getExpr().getErasedReceiverType());
|
||||
|
||||
LOG.skipInstantiation(m, site);
|
||||
expr.setInferredType(m.getReturnType());
|
||||
|
||||
if (site.areAllArgsRelevantToApplicability()) {
|
||||
// fixme the type of subexpressions might not have been set
|
||||
if (false && site.areAllArgsRelevantToApplicability()) {
|
||||
// then all have been inferred
|
||||
return ctdecl;
|
||||
}
|
||||
|
@ -6,11 +6,13 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.types
|
||||
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.property.Arb
|
||||
import io.kotest.property.Exhaustive
|
||||
import io.kotest.property.RandomSource
|
||||
import io.kotest.property.Sample
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBeA
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode
|
||||
@ -59,6 +61,14 @@ fun JTypeVar.withNewBounds(upper: JTypeMirror? = null, lower:JTypeMirror? = null
|
||||
this.cloneWithBounds(upper ?: this.upperBound, lower ?: this.lowerBound)
|
||||
}
|
||||
|
||||
fun JTypeMirror.shouldBeCaptureOf(wild: JWildcardType) =
|
||||
this.shouldBeA<JTypeVar> {
|
||||
it.isCaptured shouldBe true
|
||||
if (wild.isLowerBound)
|
||||
it.lowerBound shouldBe wild.asLowerBound()
|
||||
else
|
||||
it.upperBound shouldBe wild.asUpperBound()
|
||||
}
|
||||
|
||||
@Suppress("ObjectPropertyName", "MemberVisibilityCanBePrivate")
|
||||
class TypeGen(override val ts: TypeSystem) : Arb<JTypeMirror>(), TypeDslMixin {
|
||||
@ -125,6 +135,7 @@ class TypeGen(override val ts: TypeSystem) : Arb<JTypeMirror>(), TypeDslMixin {
|
||||
|
||||
/** raw Comparable */
|
||||
val t_Comparable: JClassType get() = java.lang.Comparable::class.raw
|
||||
val t_Comparator: JClassType get() = java.util.Comparator::class.raw
|
||||
|
||||
val t_EnumSet: JClassType get() = java.util.EnumSet::class.raw
|
||||
|
||||
|
@ -4,12 +4,16 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.types.internal.infer
|
||||
|
||||
import io.kotest.inspectors.forExactly
|
||||
import io.kotest.matchers.collections.shouldBeSingleton
|
||||
import io.kotest.matchers.shouldBe
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBe
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldBeA
|
||||
import net.sourceforge.pmd.lang.ast.test.shouldMatchN
|
||||
import net.sourceforge.pmd.lang.java.ast.*
|
||||
import net.sourceforge.pmd.lang.java.types.*
|
||||
import net.sourceforge.pmd.lang.java.types.testdata.TypeInferenceTestCases
|
||||
import net.sourceforge.pmd.lang.java.types.typeDsl
|
||||
import java.util.function.ToIntFunction
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
@ -83,6 +87,75 @@ class CaptureInferenceTest : ProcessorTestSpec({
|
||||
}
|
||||
}
|
||||
|
||||
parserTest("Test method ref on captured thing") {
|
||||
|
||||
logTypeInference(verbose = true)
|
||||
|
||||
val acu = parser.parse("""
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
class Scratch {
|
||||
private List<? extends String> sortIt(final List<? extends String> stats) {
|
||||
final List<? extends String> statList = new ArrayList<>(stats);
|
||||
statList.sort(Comparator.comparingInt(Object::hashCode));
|
||||
return statList;
|
||||
}
|
||||
}
|
||||
|
||||
""".trimIndent())
|
||||
|
||||
val call = acu.descendants(ASTMethodCall::class.java).first()!!
|
||||
|
||||
call.shouldMatchN {
|
||||
methodCall("sort") {
|
||||
it::getTypeMirror shouldBe with(it.typeDsl) { ts.NO_TYPE }
|
||||
|
||||
variableAccess("statList") {}
|
||||
argList {
|
||||
var capture: JTypeVar? = null
|
||||
methodCall("comparingInt") {
|
||||
with (it.typeDsl) {
|
||||
// eg. java.util.Comparator<capture#45 of ? extends java.lang.String>
|
||||
val ret = it.typeMirror.shouldBeA<JClassType> {
|
||||
it.symbol shouldBe gen.t_Comparator.symbol
|
||||
it.typeArgs.shouldBeSingleton {
|
||||
capture = it.shouldBeCaptureOf(`?` extends gen.t_String)
|
||||
}
|
||||
}
|
||||
|
||||
it.methodType.shouldMatchMethod(
|
||||
named = "comparingInt",
|
||||
declaredIn = gen.t_Comparator,
|
||||
withFormals = listOf(ToIntFunction::class[`?` `super` capture!!]),
|
||||
returning = ret
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
typeExpr {
|
||||
classType("Comparator")
|
||||
}
|
||||
|
||||
argList {
|
||||
methodRef("hashCode") {
|
||||
typeExpr {
|
||||
classType("Object")
|
||||
}
|
||||
|
||||
with(it.typeDsl) {
|
||||
it.referencedMethod shouldBe ts.OBJECT.getMethodsByName("hashCode").single()
|
||||
it.typeMirror shouldBe ToIntFunction::class[capture!!]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -4,16 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.ast.test
|
||||
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.matchers.shouldBe as ktShouldBe
|
||||
import io.kotest.matchers.should
|
||||
import io.kotest.matchers.Matcher
|
||||
import io.kotest.matchers.equalityMatcher
|
||||
import io.kotest.matchers.collections.haveSize
|
||||
import java.util.stream.Stream
|
||||
import kotlin.streams.toList
|
||||
import io.kotest.matchers.should
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
|
||||
/**
|
||||
* Extension to add the name of a property to error messages.
|
||||
|
Reference in New Issue
Block a user