diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java index 93fb11d11c60..969465c6aab1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java @@ -24,7 +24,6 @@ import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; -import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; @@ -40,6 +39,8 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpre import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; + /** * @author ilyas */ @@ -89,6 +90,7 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { } private static class MyTypesCalculator implements Function { + @Nullable public PsiType fun(GrListOrMapImpl listOrMap) { final GlobalSearchScope scope = listOrMap.getResolveScope(); if (listOrMap.isMap()) { @@ -109,7 +111,10 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { @Nullable private static PsiClassType inferMapInitializerType(GrListOrMapImpl listOrMap, JavaPsiFacade facade, GlobalSearchScope scope) { - PsiClass mapClass = facade.findClass("java.util.Map", scope); + PsiClass mapClass = facade.findClass("java.util.LinkedHashMap", scope); + if (mapClass == null) { + mapClass = facade.findClass(CommonClassNames.JAVA_UTIL_MAP, scope); + } PsiElementFactory factory = facade.getElementFactory(); if (mapClass != null) { PsiTypeParameter[] typeParameters = mapClass.getTypeParameters(); @@ -146,15 +151,20 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { if (labels.length == 0) return null; PsiType result = null; PsiManager manager = labels[0].getManager(); + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(labels[0].getProject()); for (GrArgumentLabel label : labels) { PsiElement el = label.getNameElement(); - final PsiType other; + PsiType other; if (el instanceof GrParenthesizedExpression) { other = ((GrParenthesizedExpression)el).getType(); } else { - if (el.getNode() != null) { - other = TypesUtil.getPsiType(el, el.getNode().getElementType()); + final ASTNode node = el.getNode(); + if (node != null) { + other = TypesUtil.getPsiType(el, node.getElementType()); + if (other == null) { + other = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, el.getResolveScope()); + } } else { other = null; @@ -186,6 +196,7 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { return result; } + @Nullable private static PsiType getLeastUpperBound(PsiType result, PsiType other, PsiManager manager) { if (other == null) return result; if (result == null) result = other; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index 36b6584c70ed..3010d46677e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -222,7 +222,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements if (getParent() instanceof GrReferenceExpression) { result = facade.getElementFactory().createType((PsiClass) resolved); } else { - PsiClass javaLangClass = facade.findClass("java.lang.Class", getResolveScope()); + PsiClass javaLangClass = facade.findClass(CommonClassNames.JAVA_LANG_CLASS, getResolveScope()); if (javaLangClass != null) { PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; final PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters(); @@ -239,14 +239,14 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements } else if (resolved instanceof PsiMethod && !GroovyPsiManager.isTypeBeingInferred(resolved)) { if (dotType == GroovyTokenTypes.mMEMBER_POINTER) { - return facade.getElementFactory().createTypeByFQClassName("groovy.lang.Closure", getResolveScope()); + return facade.getElementFactory().createTypeByFQClassName(GrClosableBlock.GROOVY_LANG_CLOSURE, getResolveScope()); } PsiMethod method = (PsiMethod) resolved; if (PropertyUtil.isSimplePropertySetter(method) && !method.getName().equals(getReferenceName())) { result = method.getParameterList().getParameters()[0].getType(); } else { PsiClass containingClass = method.getContainingClass(); - if (containingClass != null && "java.lang.Object".equals(containingClass.getQualifiedName()) && + if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) && "getClass".equals(method.getName())) { result = getTypeForObjectGetClass(facade, method); } else { @@ -283,7 +283,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics(); PsiClass clazz = qResult.getElement(); if (clazz != null) { - PsiClass mapClass = facade.findClass("java.util.Map", getResolveScope()); + PsiClass mapClass = facade.findClass(CommonClassNames.JAVA_UTIL_MAP, getResolveScope()); if (mapClass != null && mapClass.getTypeParameters().length == 2) { PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor()); if (substitutor != null) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java index 3e8f0cfc9272..730d93d2071f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java @@ -17,16 +17,16 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path; import com.intellij.lang.ASTNode; -import com.intellij.psi.CommonClassNames; -import com.intellij.psi.PsiArrayType; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -74,9 +74,21 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp argTypes[i] = argType; } - final PsiType overloadedOperatorType = TypesUtil.getOverloadedOperatorType(thisType, "getAt", this, argTypes); - if (overloadedOperatorType!=null) { - return overloadedOperatorType; + if (thisType instanceof GrTupleType) { + PsiType[] types = ((GrTupleType)thisType).getParameters(); + return types.length == 1 ? types[0] : null; + } + + PsiType overloadedOperatorType = null; + final GroovyResolveResult[] candidates = TypesUtil.getOverloadedOperatorCandidates(thisType, "getAt", this, argTypes); + if (candidates.length == 1) { + final PsiElement element = candidates[0].getElement(); + if (element instanceof PsiMethod) { + overloadedOperatorType = candidates[0].getSubstitutor().substitute(((PsiMethod)element).getReturnType()); + if (overloadedOperatorType != null && !(element instanceof GrGdkMethod)) { //gdk 'getAt' methods don't have information about type parameters + return overloadedOperatorType; + } + } } if (thisType instanceof PsiArrayType) { @@ -84,11 +96,6 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp return TypesUtil.boxPrimitiveType(componentType, getManager(), getResolveScope()); } - if (thisType instanceof GrTupleType) { - PsiType[] types = ((GrTupleType)thisType).getParameters(); - return types.length == 1 ? types[0] : null; - } - if (InheritanceUtil.isInheritor(thisType, CommonClassNames.JAVA_UTIL_LIST)) { PsiType iterType = PsiUtil.extractIterableTypeParameter(thisType, true); if (iterType != null) return iterType; @@ -97,6 +104,8 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp if (InheritanceUtil.isInheritor(thisType, CommonClassNames.JAVA_UTIL_MAP)) { return PsiUtil.substituteTypeParameter(thisType, CommonClassNames.JAVA_UTIL_MAP, 1, true); } + + return overloadedOperatorType; } } return null; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java index f38280c2924c..2e18835f8380 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java @@ -222,4 +222,8 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { } public void testSuperConstructorInvocation() throws Exception {doTest();} + + public void testIndexPropertyAccess() throws Exception { + doTest(); + } } \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/IndexPropertyAccess.groovy b/plugins/groovy/testdata/highlighting/IndexPropertyAccess.groovy new file mode 100644 index 000000000000..1c106193ff0b --- /dev/null +++ b/plugins/groovy/testdata/highlighting/IndexPropertyAccess.groovy @@ -0,0 +1,8 @@ +class X extends HashMap { + def getAt(def k) { + return "string" + } +} + +def x = new X(); +print x[2].concat("a") \ No newline at end of file