mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
new inference: support for nested same method calls
This commit is contained in:
@@ -389,21 +389,4 @@ public class InferenceIncorporationPhase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PsiSubstitutor checkIncorporated(PsiSubstitutor substitutor, Collection<InferenceVariable> variables) {
|
||||
for (InferenceVariable variable : variables) { //todo equals bounds?
|
||||
for (PsiType lowerBound : variable.getBounds(InferenceBound.LOWER)) {
|
||||
lowerBound = substitutor.substitute(lowerBound);
|
||||
if (mySession.isProperType(lowerBound)) {
|
||||
for (PsiType upperBound : variable.getBounds(InferenceBound.UPPER)) {
|
||||
upperBound = substitutor.substitute(upperBound);
|
||||
if (mySession.isProperType(upperBound) && !TypeConversionUtil.isAssignable(upperBound, lowerBound)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return substitutor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ public class InferenceSession {
|
||||
PsiMethod parentMethod) {
|
||||
if (!repeatInferencePhases(true)) {
|
||||
//inferred result would be checked as candidate won't be applicable
|
||||
return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
|
||||
return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
|
||||
}
|
||||
|
||||
if (parentMethod != null) {
|
||||
@@ -294,7 +294,7 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
|
||||
return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
|
||||
}
|
||||
|
||||
return prepareSubstitution();
|
||||
@@ -386,7 +386,7 @@ public class InferenceSession {
|
||||
public void registerConstraints(PsiType returnType, PsiType targetType) {
|
||||
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
|
||||
if (inferenceVariable != null) {
|
||||
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
|
||||
final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
|
||||
myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutor.substitute(inferenceVariable.getParameter()), myContext)));
|
||||
}
|
||||
else {
|
||||
@@ -529,12 +529,13 @@ public class InferenceSession {
|
||||
}
|
||||
final int i = ArrayUtilRt.find(args, arg);
|
||||
if (i < 0) return null;
|
||||
return getParameterType(parameters, args, i, PsiResolveHelper.ourGraphGuard.doPreventingRecursion(argumentList.getParent(), false, new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
return result.getSubstitutor();
|
||||
}
|
||||
}));
|
||||
return getParameterType(parameters, args, i, PsiResolveHelper.ourGraphGuard.doPreventingRecursion(argumentList.getParent(), false,
|
||||
new Computable<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor compute() {
|
||||
return result.getSubstitutor();
|
||||
}
|
||||
}));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -657,7 +658,7 @@ public class InferenceSession {
|
||||
while (!allVars.isEmpty()) {
|
||||
final List<InferenceVariable> vars = InferenceVariablesOrder.resolveOrder(allVars, this);
|
||||
if (!myIncorporationPhase.hasCaptureConstraints(vars)) {
|
||||
final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor, true);
|
||||
final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor);
|
||||
if (firstSubstitutor != null) {
|
||||
substitutor = firstSubstitutor;
|
||||
allVars.removeAll(vars);
|
||||
@@ -668,7 +669,7 @@ public class InferenceSession {
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
|
||||
for (InferenceVariable var : vars) {
|
||||
final PsiTypeParameter parameter = var.getParameter();
|
||||
final PsiTypeParameter copy = elementFactory.createTypeParameterFromText(parameter.getName(), null);
|
||||
final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
|
||||
final PsiType lub = getLowerBound(var, substitutor);
|
||||
final PsiType glb = getUpperBound(var, substitutor);
|
||||
final InferenceVariable zVariable = new InferenceVariable(copy);
|
||||
@@ -681,6 +682,8 @@ public class InferenceSession {
|
||||
zVariable.addBound(lub, InferenceBound.LOWER);
|
||||
}
|
||||
myInferenceVariables.put(copy, zVariable);
|
||||
allVars.add(zVariable);
|
||||
var.addBound(elementFactory.createType(copy), InferenceBound.EQ);
|
||||
}
|
||||
myIncorporationPhase.forgetCaptures(vars);
|
||||
if (!myIncorporationPhase.incorporate()) {
|
||||
@@ -699,7 +702,7 @@ public class InferenceSession {
|
||||
}, substitutor);
|
||||
}
|
||||
|
||||
private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor, boolean checkResult) {
|
||||
private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor) {
|
||||
for (InferenceVariable var : vars) {
|
||||
LOG.assertTrue(var.getInstantiation() == PsiType.NULL);
|
||||
final PsiTypeParameter typeParameter = var.getParameter();
|
||||
@@ -718,7 +721,7 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
|
||||
return checkResult ? myIncorporationPhase.checkIncorporated(substitutor, vars) : substitutor;
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
private PsiType getUpperBound(InferenceVariable var, PsiSubstitutor substitutor) {
|
||||
@@ -809,7 +812,7 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
//resolve input variables
|
||||
PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor, true);
|
||||
PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor);
|
||||
|
||||
if (substitutor == null) {
|
||||
return false;
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil
|
||||
import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -99,14 +100,28 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
|
||||
if (typeParams != null) {
|
||||
|
||||
for (PsiTypeParameter typeParam : typeParams) {
|
||||
session.addCapturedVariable(typeParam);
|
||||
}
|
||||
session.initBounds(typeParams);
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
//typeParams are already included
|
||||
final Collection<PsiTypeParameter> params = session.getTypeParams();
|
||||
InferenceSession callSession = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor()
|
||||
: PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
|
||||
final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
|
||||
session.collectDependencies(returnType, variables);
|
||||
final PsiTypeParameter[] params = new PsiTypeParameter[typeParams.length];
|
||||
for (int i = 0; i < typeParams.length; i++) {
|
||||
if (variables.contains(session.getInferenceVariable(typeParams[i]))) {
|
||||
params[i] = JavaPsiFacade.getElementFactory(myExpression.getProject()).createTypeParameterFromText("copyOf" + myExpression.hashCode() + typeParams[i].getName(), null);
|
||||
substitutor = substitutor.put(typeParams[i], JavaPsiFacade.getElementFactory(myExpression.getProject()).createType(params[i]));
|
||||
}
|
||||
else {
|
||||
params[i] = typeParams[i];
|
||||
}
|
||||
}
|
||||
final PsiSubstitutor siteSubstitutor = resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() : PsiSubstitutor.EMPTY;
|
||||
for (PsiTypeParameter typeParameter : siteSubstitutor.getSubstitutionMap().keySet()) {
|
||||
substitutor = substitutor.put(typeParameter, substitutor.substitute(siteSubstitutor.substitute(typeParameter)));
|
||||
}
|
||||
|
||||
final Collection<PsiTypeParameter> params1 = session.getTypeParams();
|
||||
final InferenceSession callSession = new InferenceSession(params1.toArray(new PsiTypeParameter[params1.size()]), substitutor, myExpression.getManager(), myExpression);
|
||||
callSession.initBounds(params);
|
||||
if (method != null) {
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
@@ -109,6 +109,11 @@ public class TypeEqualityConstraint implements ConstraintFormula {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (myT instanceof PsiCapturedWildcardType && myS instanceof PsiCapturedWildcardType) {
|
||||
return new TypeEqualityConstraint(((PsiCapturedWildcardType)myT).getWildcard(),
|
||||
((PsiCapturedWildcardType)myS).getWildcard()).reduce(session, constraints);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
import java.util.List;
|
||||
|
||||
class Main0 {
|
||||
<T> List<T> foo(T t){
|
||||
return null;
|
||||
}
|
||||
|
||||
{
|
||||
foo(foo(""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Main {
|
||||
static <T> T foo(T t) { return null; }
|
||||
|
||||
@@ -14,6 +27,6 @@ class Main1 {
|
||||
static <B> B bar(B t) { return null;}
|
||||
|
||||
static {
|
||||
long l = foo(bar(1));
|
||||
//long l = foo(bar(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void _testNestedCallsSameMethod() throws Exception {
|
||||
public void testNestedCallsSameMethod() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user