pass parameter type inference policy to produce ? extends for cases when no constraints were found during inference (IDEA-156231)

This commit is contained in:
Anna.Kozlova
2016-05-23 16:29:23 +02:00
parent 36978bb4bf
commit cd63335147
7 changed files with 108 additions and 11 deletions
@@ -23,6 +23,8 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
@@ -87,6 +89,7 @@ public class InferenceSession {
public final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this);
private final PsiElement myContext;
private ParameterTypeInferencePolicy myPolicy;
private PsiSubstitutor myInferenceSubstitution = PsiSubstitutor.EMPTY;
private PsiSubstitutor myRestoreNameSubstitution = PsiSubstitutor.EMPTY;
@@ -104,6 +107,7 @@ public class InferenceSession {
}
myInferenceSessionContainer = initialState.getInferenceSessionContainer();
myErased = initialState.isErased();
myPolicy = DefaultParameterTypeInferencePolicy.INSTANCE;
}
public InferenceSession(PsiTypeParameter[] typeParams,
@@ -125,15 +129,25 @@ public class InferenceSession {
addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(leftTypes[i]), substituteWithInferenceVariables(rightType)));
}
}
myPolicy = DefaultParameterTypeInferencePolicy.INSTANCE;
}
public InferenceSession(PsiTypeParameter[] typeParams,
PsiSubstitutor siteSubstitutor,
PsiManager manager,
PsiElement context) {
this(typeParams, siteSubstitutor, manager, context, DefaultParameterTypeInferencePolicy.INSTANCE);
}
public InferenceSession(PsiTypeParameter[] typeParams,
PsiSubstitutor siteSubstitutor,
PsiManager manager,
PsiElement context,
ParameterTypeInferencePolicy policy) {
myManager = manager;
mySiteSubstitutor = siteSubstitutor;
myContext = context;
myPolicy = policy;
initBounds(typeParams);
}
@@ -1198,7 +1212,12 @@ public class InferenceSession {
type = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
}
else {
type = myErased ? null : upperBound;
if (myErased) {
type = null;
}
else {
type = var.getBounds(InferenceBound.UPPER).size() == 1 ? myPolicy.getInferredTypeWithNoConstraint(myManager, upperBound).first : upperBound;
}
}
if (type instanceof PsiIntersectionType) {
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.source.resolve.graphInference;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.ExpressionCompatibilityConstraint;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
@@ -63,7 +64,8 @@ public class InferenceSessionContainer {
@NotNull PsiParameter[] parameters,
@NotNull PsiExpression[] arguments,
@NotNull PsiSubstitutor partialSubstitutor,
@NotNull final PsiElement parent) {
@NotNull final PsiElement parent,
@NotNull final ParameterTypeInferencePolicy policy) {
if (parent instanceof PsiCall) {
final PsiExpressionList argumentList = ((PsiCall)parent).getArgumentList();
final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
@@ -82,14 +84,14 @@ public class InferenceSessionContainer {
InferenceSession session;
if (MethodCandidateInfo.isOverloadCheck() || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty() || LambdaUtil.isLambdaParameterCheck()) {
session = startTopLevelInference(topLevelCall);
session = startTopLevelInference(topLevelCall, policy);
}
else {
session = CachedValuesManager.getCachedValue(topLevelCall, new CachedValueProvider<InferenceSession>() {
@Nullable
@Override
public Result<InferenceSession> compute() {
return new Result<InferenceSession>(startTopLevelInference(topLevelCall), PsiModificationTracker.MODIFICATION_COUNT);
return new Result<InferenceSession>(startTopLevelInference(topLevelCall, policy), PsiModificationTracker.MODIFICATION_COUNT);
}
});
@@ -102,7 +104,7 @@ public class InferenceSessionContainer {
if (childSession != null) {
for (PsiTypeParameter parameter : typeParameters) {
if (!childSession.getInferenceSubstitution().getSubstitutionMap().containsKey(parameter)) {
session = startTopLevelInference(topLevelCall);
session = startTopLevelInference(topLevelCall, policy);
break;
}
}
@@ -124,13 +126,13 @@ public class InferenceSessionContainer {
}
}
else if (topLevelCall instanceof PsiMethodCallExpression) {
return new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent).prepareSubstitution();
return new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent, policy).prepareSubstitution();
}
}
}
}
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent);
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent, policy);
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
return inferenceSession.infer(parameters, arguments, parent);
}
@@ -178,7 +180,7 @@ public class InferenceSessionContainer {
}
@Nullable
private static InferenceSession startTopLevelInference(final PsiCall topLevelCall) {
private static InferenceSession startTopLevelInference(final PsiCall topLevelCall, final ParameterTypeInferencePolicy policy) {
final JavaResolveResult result = topLevelCall.resolveMethodGenerics();
if (result instanceof MethodCandidateInfo) {
final PsiMethod method = ((MethodCandidateInfo)result).getElement();
@@ -190,7 +192,7 @@ public class InferenceSessionContainer {
@Override
public InferenceSession compute() {
final InferenceSession topLevelSession =
new InferenceSession(method.getTypeParameters(), ((MethodCandidateInfo)result).getSiteSubstitutor(), topLevelCall.getManager(), topLevelCall);
new InferenceSession(method.getTypeParameters(), ((MethodCandidateInfo)result).getSiteSubstitutor(), topLevelCall.getManager(), topLevelCall, policy);
topLevelSession.initExpressionConstraints(topLevelParameters, topLevelArguments, topLevelCall, method, ((MethodCandidateInfo)result).isVarargs());
topLevelSession.infer(topLevelParameters, topLevelArguments, topLevelCall, ((MethodCandidateInfo)result).createProperties());
return topLevelSession;
@@ -68,7 +68,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
@NotNull LanguageLevel languageLevel) {
if (typeParameters.length == 0) return partialSubstitutor;
return InferenceSessionContainer.infer(typeParameters, parameters, arguments, partialSubstitutor, parent);
return InferenceSessionContainer.infer(typeParameters, parameters, arguments, partialSubstitutor, parent, policy);
}
@NotNull
@@ -0,0 +1,24 @@
class FooBar {
{
addSourceRoot(JavaResourceRootType.RESOURCE);
}
public static <P extends JpsElement> void addSourceRoot(JpsModuleSourceRootType<P> rootType) {
}
interface JpsElement {}
interface JpsModuleSourceRootType<P extends JpsElement> {}
static class JavaResourceRootProperties extends JpsElementBase<JavaResourceRootProperties>{}
static class JpsElementBase<Self extends JpsElementBase<Self>> implements JpsElement {}
static class JavaResourceRootType implements JpsModuleSourceRootType<JavaResourceRootProperties> {
public static final JavaResourceRootType RESOURCE = new JavaResourceRootType();
public static final JavaResourceRootType TEST_RESOURCE = new JavaResourceRootType();
}
}
@@ -0,0 +1,24 @@
class FooBar {
{
addSourceRoot(JavaResourceRootType.<caret>);
}
public static <P extends JpsElement> void addSourceRoot(JpsModuleSourceRootType<P> rootType) {
}
interface JpsElement {}
interface JpsModuleSourceRootType<P extends JpsElement> {}
static class JavaResourceRootProperties extends JpsElementBase<JavaResourceRootProperties>{}
static class JpsElementBase<Self extends JpsElementBase<Self>> implements JpsElement {}
static class JavaResourceRootType implements JpsModuleSourceRootType<JavaResourceRootProperties> {
public static final JavaResourceRootType RESOURCE = new JavaResourceRootType();
public static final JavaResourceRootType TEST_RESOURCE = new JavaResourceRootType();
}
}
@@ -0,0 +1,24 @@
class FooBar {
{
addSourceRoot(JavaResourceRootType.<caret>);
}
public static <P extends JpsElement> void addSourceRoot(JpsModuleSourceRootType<P> rootType) {
}
interface JpsElement {}
interface JpsModuleSourceRootType<P extends JpsElement> {}
static class JavaResourceRootProperties extends JpsElementBase<JavaResourceRootProperties>{}
static class JpsElementBase<Self extends JpsElementBase<Self>> implements JpsElement {}
static class JavaResourceRootType implements JpsModuleSourceRootType<JavaResourceRootProperties> {
public static final JavaResourceRootType RESOURCE = new JavaResourceRootType();
public static final JavaResourceRootType TEST_RESOURCE = new JavaResourceRootType();
}
}
@@ -85,6 +85,10 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase {
doTest(false);
}
public void testNoConstraintsWildcard() throws Exception {
doTest();
}
public void testInheritorConstructorRef() {
myFixture.addClass("package intf; public interface Intf<T> {}");
myFixture.addClass("package foo; public class ImplBar implements intf.Intf<String> {}");