new inference: default constructor as poly expression argument

This commit is contained in:
Anna Kozlova
2013-09-20 20:36:37 +04:00
parent ee56497e3d
commit f415702127
3 changed files with 66 additions and 26 deletions
@@ -74,36 +74,51 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula {
if (myExpression instanceof PsiCallExpression) {
final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
final Map<PsiElement,Pair<PsiMethod,PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get();
final Pair<PsiMethod,PsiSubstitutor> pair = map != null ? map.get(argumentList) : null;
final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod();
if (method != null) {
final PsiTypeParameter[] typeParameters = method.getTypeParameters();
if (typeParameters.length == 0) {
final PsiType exprType = myExpression.getType();
if (exprType != null && !exprType.equals(PsiType.NULL)) {
constraints.add(new TypeCompatibilityConstraint(myT, exprType));
if (argumentList != null) {
final Map<PsiElement,Pair<PsiMethod,PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get();
final Pair<PsiMethod,PsiSubstitutor> pair = map != null ? map.get(argumentList) : null;
final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod();
PsiType returnType = null;
InferenceSession callSession = null;
if (method != null) {
returnType = method.getReturnType();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (returnType != null) {
callSession = new InferenceSession(method.getTypeParameters(), parameters,
argumentList.getExpressions(),
PsiSubstitutor.EMPTY, null, myExpression.getManager());
}
} else {
PsiType returnType = method.getReturnType();
if (argumentList != null && returnType != null) { //todo constructor
final InferenceSession callSession = new InferenceSession(typeParameters, method.getParameterList().getParameters(),
argumentList.getExpressions(),
PsiSubstitutor.EMPTY, null, myExpression.getManager());
for (PsiTypeParameter typeParameter : session.getTypeParams()) {
callSession.addCapturedVariable(typeParameter);
} else if (myExpression instanceof PsiNewExpression) { //default constructor
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference();
if (classReference != null) {
final PsiElement psiClass = classReference.resolve();
if (psiClass instanceof PsiClass) {
returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType((PsiClass)psiClass, PsiSubstitutor.EMPTY);
callSession = new InferenceSession(((PsiClass)psiClass).getTypeParameters(),
PsiParameter.EMPTY_ARRAY,
argumentList.getExpressions(),
PsiSubstitutor.EMPTY, null, myExpression.getManager());
}
callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType));
final PsiSubstitutor callSubstitutor = callSession.infer();
if (myExpression instanceof PsiMethodCallExpression) {
returnType =
PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor);
} else {
returnType = callSubstitutor.substitute(returnType);
}
constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types
}
}
if (callSession != null) {
for (PsiTypeParameter typeParameter : session.getTypeParams()) {
callSession.addCapturedVariable(typeParameter);
}
callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType));
final PsiSubstitutor callSubstitutor = callSession.infer();
if (myExpression instanceof PsiMethodCallExpression) {
returnType = PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor);
}
else {
returnType = callSubstitutor.substitute(returnType);
}
constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types
}
}
return true;
}
@@ -0,0 +1,21 @@
class Main2 {
<R> void bar(Fun<Integer, R> collector) { }
<T, D> Fun<T, Integer> foo(D d) { return null; }
public void test() {
bar(new Foo<>());
}
interface Fun<T, R> {
R _(T t);
}
class Foo<K> implements Fun<K, Integer> {
@Override
public Integer _(K k) {
return null;
}
}
}
@@ -79,6 +79,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
public void testDefaultConstructorAsArgument() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(false);
}