mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-51686 Groovy syntax parser does not recognize that indexing using array returns a slice
This commit is contained in:
+24
-20
@@ -19,18 +19,19 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path;
|
||||
import com.intellij.lang.ASTNode;
|
||||
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;
|
||||
|
||||
import static com.intellij.psi.util.PsiUtil.substituteTypeParameter;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getSmartReturnType;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
@@ -74,38 +75,41 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp
|
||||
argTypes[i] = argType;
|
||||
}
|
||||
|
||||
if (thisType instanceof GrTupleType) {
|
||||
if (thisType instanceof GrTupleType &&
|
||||
argTypes.length == 1 &&
|
||||
TypesUtil.isAssignable(PsiType.INT, argTypes[0], getManager(), getResolveScope())) {
|
||||
PsiType[] types = ((GrTupleType)thisType).getParameters();
|
||||
return types.length == 1 ? types[0] : null;
|
||||
}
|
||||
|
||||
PsiType overloadedOperatorType = null;
|
||||
final GroovyResolveResult[] candidates = TypesUtil.getOverloadedOperatorCandidates(thisType, "getAt", this, argTypes);
|
||||
GroovyResolveResult[] candidates = TypesUtil.getOverloadedOperatorCandidates(thisType, "getAt", this, argTypes);
|
||||
if (candidates.length != 1) {
|
||||
candidates = TypesUtil.getOverloadedOperatorCandidates(thisType, "getAt", this, new PsiType[]{
|
||||
new GrTupleType(argTypes, JavaPsiFacade.getInstance(getProject()), getResolveScope())});
|
||||
}
|
||||
if (candidates.length == 1) {
|
||||
final PsiElement element = candidates[0].getElement();
|
||||
if (element instanceof PsiMethod) {
|
||||
overloadedOperatorType = candidates[0].getSubstitutor().substitute(org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getSmartReturnType((PsiMethod)element));
|
||||
if (overloadedOperatorType != null && !(element instanceof GrGdkMethod)) { //gdk 'getAt' methods don't have information about type parameters
|
||||
return overloadedOperatorType;
|
||||
}
|
||||
overloadedOperatorType = candidates[0].getSubstitutor().substitute(getSmartReturnType((PsiMethod)element));
|
||||
}
|
||||
}
|
||||
|
||||
if (thisType instanceof PsiArrayType) {
|
||||
PsiType componentType = ((PsiArrayType)thisType).getComponentType();
|
||||
return TypesUtil.boxPrimitiveType(componentType, getManager(), getResolveScope());
|
||||
PsiType componentType = null;
|
||||
if (thisType instanceof PsiArrayType &&
|
||||
argTypes.length == 1 &&
|
||||
TypesUtil.isAssignable(PsiType.INT, argTypes[0], getManager(), getResolveScope())) {
|
||||
componentType = TypesUtil.boxPrimitiveType(((PsiArrayType)thisType).getComponentType(), getManager(), getResolveScope());
|
||||
}
|
||||
else if (InheritanceUtil.isInheritor(thisType, CommonClassNames.JAVA_UTIL_MAP) && argTypes.length == 1) {
|
||||
componentType = substituteTypeParameter(thisType, CommonClassNames.JAVA_UTIL_MAP, 1, true);
|
||||
}
|
||||
|
||||
if (InheritanceUtil.isInheritor(thisType, CommonClassNames.JAVA_UTIL_LIST)) {
|
||||
PsiType iterType = PsiUtil.extractIterableTypeParameter(thisType, true);
|
||||
if (iterType != null) return iterType;
|
||||
if (overloadedOperatorType != null &&
|
||||
(componentType == null || !TypesUtil.isAssignable(overloadedOperatorType, componentType, getManager(), getResolveScope()))) {
|
||||
return overloadedOperatorType;
|
||||
}
|
||||
|
||||
if (InheritanceUtil.isInheritor(thisType, CommonClassNames.JAVA_UTIL_MAP)) {
|
||||
return PsiUtil.substituteTypeParameter(thisType, CommonClassNames.JAVA_UTIL_MAP, 1, true);
|
||||
}
|
||||
|
||||
return overloadedOperatorType;
|
||||
return componentType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -58,4 +58,5 @@ class GrCompletionTestWithLibrary extends GroovyCompletionTestBase {
|
||||
public void testCategoryProperty() {doBasicTest()}
|
||||
public void testMultipleCategories() {doBasicTest()}
|
||||
|
||||
public void testArrayLikeAccessForList() throws Throwable {doBasicTest(); }
|
||||
}
|
||||
|
||||
@@ -96,10 +96,6 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase {
|
||||
doBasicTest();
|
||||
}
|
||||
|
||||
public void testArrayLikeAccessForList() throws Throwable {
|
||||
doBasicTest();
|
||||
}
|
||||
|
||||
public void testArrayLikeAccessForMap() throws Throwable {
|
||||
doBasicTest();
|
||||
}
|
||||
|
||||
@@ -117,4 +117,9 @@ public class TypeInferenceTest extends GroovyResolveTestCase {
|
||||
final GrReferenceExpression ref = (GrReferenceExpression)configureByFile("genericWildcard/A.groovy").getElement();
|
||||
assertEquals("A<Base>", ref.getType().getCanonicalText());
|
||||
}
|
||||
|
||||
public void testArrayLikeAccessWithIntSequence() {
|
||||
final GrReferenceExpression ref = (GrReferenceExpression)configureByFile("arrayLikeAccessWithIntSequence/A.groovy").getElement();
|
||||
assertEquals("java.util.List", ref.getType().getCanonicalText());
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
def foo = [1, 2, 5]
|
||||
def list = foo[1, 2]
|
||||
|
||||
print l<ref>ist
|
||||
Reference in New Issue
Block a user