new inference: assert that no resolve is performed on the "inference-in-progress" reference

This commit is contained in:
Anna Kozlova
2015-04-29 21:39:25 +02:00
parent f629e68a55
commit e86c7dcb25
5 changed files with 67 additions and 30 deletions

View File

@@ -418,7 +418,7 @@ public class InferenceSession {
final Computable<JavaResolveResult> computableResolve = new Computable<JavaResolveResult>() {
@Override
public JavaResolveResult compute() {
return callExpression.resolveMethodGenerics();
return getResolveResult(callExpression, argumentList);
}
};
MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
@@ -428,6 +428,24 @@ public class InferenceSession {
: PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, false, computableResolve);
}
public static JavaResolveResult getResolveResult(PsiCallExpression callExpression, PsiExpressionList argumentList) {
if (callExpression instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)callExpression).getClassOrAnonymousClassReference();
final JavaResolveResult resolveResult = classReference != null ? classReference.advancedResolve(false) : null;
final PsiElement psiClass = resolveResult != null ? resolveResult.getElement() : null;
if (psiClass instanceof PsiClass) {
final JavaPsiFacade facade = JavaPsiFacade.getInstance(callExpression.getProject());
final JavaResolveResult constructor = facade.getResolveHelper()
.resolveConstructor(facade.getElementFactory().createType((PsiClass)psiClass).rawType(), argumentList, callExpression);
return constructor.getElement() == null ? resolveResult : constructor;
}
else {
return JavaResolveResult.EMPTY;
}
}
return callExpression.resolveMethodGenerics();
}
public PsiSubstitutor retrieveNonPrimitiveEqualsBounds(Collection<InferenceVariable> variables) {
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
for (InferenceVariable variable : variables) {

View File

@@ -84,33 +84,19 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
if (argumentList != null) {
final MethodCandidateInfo.CurrentCandidateProperties candidateProperties = MethodCandidateInfo.getCurrentMethod(((PsiCallExpression)myExpression).getArgumentList());
final JavaResolveResult resolveResult;
PsiType returnType = null;
PsiTypeParameter[] typeParams = null;
final JavaResolveResult resolveResult = candidateProperties != null ? null : InferenceSession.getResolveResult((PsiCallExpression)myExpression, argumentList);
PsiMethod method = null;
if (candidateProperties != null) {
resolveResult = null;
method = candidateProperties.getMethod();
}
else {
if (myExpression instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference();
final PsiElement psiClass = classReference != null ? classReference.resolve() : null;
if (psiClass instanceof PsiClass) {
final JavaPsiFacade facade = JavaPsiFacade.getInstance(myExpression.getProject());
resolveResult = facade.getResolveHelper().resolveConstructor(facade.getElementFactory().createType((PsiClass)psiClass).rawType(), argumentList, myExpression);
returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType((PsiClass)psiClass, PsiSubstitutor.EMPTY);
typeParams = ((PsiClass)psiClass).getTypeParameters();
}
else {
resolveResult = JavaResolveResult.EMPTY;
}
}
else {
resolveResult = ((PsiCallExpression)myExpression).resolveMethodGenerics();
final PsiElement element = resolveResult.getElement();
if (element instanceof PsiMethod) {
method = (PsiMethod)element;
}
}
final PsiMethod method = candidateProperties != null ? candidateProperties.getMethod() : (PsiMethod)resolveResult.getElement();
if (method != null && !method.isConstructor()) {
returnType = method.getReturnType();
@@ -118,6 +104,13 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
typeParams = method.getTypeParameters();
}
}
else if (resolveResult != null) {
final PsiClass psiClass = method != null ? method.getContainingClass() : (PsiClass)resolveResult.getElement();
if (psiClass != null) {
returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType(psiClass, PsiSubstitutor.EMPTY);
typeParams = psiClass.getTypeParameters();
}
}
if (typeParams != null) {
PsiSubstitutor siteSubstitutor =

View File

@@ -73,12 +73,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
public final CandidateInfo resolveConflict(@NotNull final List<CandidateInfo> conflicts){
final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(myArgumentsList);
if (properties != null) {
final PsiMethod method = properties.getMethod();
for (CandidateInfo conflict : conflicts) {
if (conflict.getElement() == method) {
return conflict;
}
}
LOG.error("Recursive conflict resolution for:" + properties.getMethod());
}
return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, true, new Computable<CandidateInfo>() {
@Override

View File

@@ -0,0 +1,20 @@
import java.util.*;
class Test {
public static void main(String[] args) {
new A<>(new B<>(of("")));
}
static <E> List<E> of(E element) {
return null;
}
static class A<K> {
A(String s) {}
A(B<K> b) {}
}
static class B<T> extends ArrayList<List<T>> {
public B(List<T> l) {}
}
}

View File

@@ -17,7 +17,7 @@ package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
@@ -35,13 +35,24 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
doTestAllMethodCallExpressions();
}
public void testAvoidClassRefCachingDuringInference() throws Exception {
doTestAllMethodCallExpressions();
}
private void doTestAllMethodCallExpressions() {
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
final Collection<PsiMethodCallExpression> methodCallExpressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiMethodCallExpression.class);
for (PsiMethodCallExpression expression : methodCallExpressions) {
final Collection<PsiCallExpression> methodCallExpressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiCallExpression.class);
for (PsiCallExpression expression : methodCallExpressions) {
getPsiManager().dropResolveCaches();
assertNotNull("Failed inference for: " + expression.getText(), expression.getType());
}
final Collection<PsiReferenceParameterList> parameterLists = PsiTreeUtil.findChildrenOfType(getFile(), PsiReferenceParameterList.class);
for (PsiReferenceParameterList list : parameterLists) {
getPsiManager().dropResolveCaches();
final PsiType[] arguments = list.getTypeArguments();
assertNotNull("Failed inference for: " + list.getParent().getText(), arguments);
}
}
@Override