infer nominal type for maps

This commit is contained in:
Max Medvedev
2012-10-02 10:47:22 +03:00
parent 837da44b7d
commit e4e662f4b5
2 changed files with 31 additions and 7 deletions
@@ -572,7 +572,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
//map access
GrExpression qualifier = getQualifierExpression();
if (qualifier != null) {
PsiType qType = qualifier.getType();
PsiType qType = qualifier.getNominalType();
if (qType instanceof PsiClassType) {
PsiClassType.ClassResolveResult qResult = ((PsiClassType)qType).resolveGenerics();
PsiClass clazz = qResult.getElement();
@@ -598,11 +598,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
PsiType result = GrReassignedLocalVarsChecker.checkReassignedVar(refExpr, true);
if (result!=null) return result;
final PsiElement resolved = refExpr.resolve();
final PsiType inferred = refExpr.getQualifier() == null && !(resolved instanceof PsiClass) ?
TypeInferenceHelper.getCurrentContext().getVariableType(refExpr) :
null;
final PsiType inferred = getInferredTypes(refExpr, resolved);
final PsiType nominal = refExpr.getNominalType();
if (inferred == null || PsiType.NULL.equals(inferred)) {
if (nominal == null) {
@@ -617,7 +614,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
if (nominal == null) return inferred;
if (!TypeConversionUtil.isAssignable(nominal, inferred, false)) {
if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
if (resolved instanceof GrVariable && ((GrVariable)resolved).getTypeElementGroovy() != null) {
return nominal;
}
@@ -626,6 +623,33 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
}
@Nullable
private static PsiType getInferredTypes(GrReferenceExpressionImpl refExpr, PsiElement resolved) {
final GrExpression qualifier = refExpr.getQualifier();
if (qualifier == null && !(resolved instanceof PsiClass)) {
return TypeInferenceHelper.getCurrentContext().getVariableType(refExpr);
}
else if (qualifier != null) {
//map access
PsiType qType = qualifier.getType();
if (qType instanceof PsiClassType) {
PsiClassType.ClassResolveResult qResult = ((PsiClassType)qType).resolveGenerics();
PsiClass clazz = qResult.getElement();
if (clazz != null) {
PsiClass mapClass =
JavaPsiFacade.getInstance(refExpr.getProject()).findClass(CommonClassNames.JAVA_UTIL_MAP, refExpr.getResolveScope());
if (mapClass != null && mapClass.getTypeParameters().length == 2) {
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
if (substitutor != null) {
return TypeConversionUtil.erasure(substitutor.substitute(mapClass.getTypeParameters()[1]));
}
}
}
}
}
return null;
}
public PsiType getType() {
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPES_CALCULATOR);
}
@@ -241,7 +241,7 @@ class A {
public void testMethodDuplicates() {doTest();}
public void testPutValueToEmptyMap() {doTest(new GroovyAssignabilityCheckInspection());}
public void testPutIncorrectValueToMap() {doTest(new GroovyAssignabilityCheckInspection());}
public void _testPutIncorrectValueToMap() {doTest(new GroovyAssignabilityCheckInspection());} //incorrect test
public void testAmbiguousCodeBlock() {doTest();}
public void testAmbiguousCodeBlockInMethodCall() {doTest();}