IDEA-94733 Groovy: complete 'eachWithIndex' with different types

This commit is contained in:
Max Medvedev
2012-11-12 16:19:32 +04:00
parent b29159f74d
commit b78d37e75c
3 changed files with 39 additions and 41 deletions
@@ -24,8 +24,10 @@ import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.completion.closureParameters.ClosureParameterInfo;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Arrays;
@@ -61,10 +63,10 @@ public class EachWithIndexClosureCompleter extends ClosureCompleter {
final PsiType type = parameters[0].getType();
final PsiType collection = substitutor.substitute(type);
final PsiType iterable = PsiUtil.extractIterableTypeParameter(collection, true);
final PsiType iterable = getIteratedType(parent, collection);
if (iterable != null) {
return Arrays.asList(
new ClosureParameterInfo(PsiImplUtil.normalizeWildcardTypeByPosition(iterable, (GrExpression)parent).getCanonicalText(), "entry"),
new ClosureParameterInfo(iterable.getCanonicalText(), "entry"),
new ClosureParameterInfo("int", "i")
);
}
@@ -85,4 +87,21 @@ public class EachWithIndexClosureCompleter extends ClosureCompleter {
return Arrays.asList(new ClosureParameterInfo(collection.getCanonicalText(), "entry"), new ClosureParameterInfo("int", "i"));
}
private static PsiType getIteratedType(PsiElement parent, PsiType collection) {
if (parent instanceof GrReferenceExpression) {
final GrExpression qualifier = ((GrReferenceExpression)parent).getQualifier();
if (qualifier != null) {
return ClosureParameterEnhancer.findTypeForIteration(qualifier, parent);
}
}
final PsiType iterable = PsiUtil.extractIterableTypeParameter(collection, true);
if (iterable != null && parent instanceof GrExpression) {
return PsiImplUtil.normalizeWildcardTypeByPosition(iterable, (GrExpression)parent);
}
else {
return iterable;
}
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
import com.intellij.psi.*;
@@ -12,20 +27,17 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.arithmetic.GrRangeExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Map;
import java.util.Set;
import static com.intellij.psi.CommonClassNames.JAVA_IO_FILE;
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
/**
* @author peter
@@ -240,22 +252,6 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
return ((GrRangeType)iterType).getIterationType();
}
if (InheritanceUtil.isInheritor(iterType, GroovyCommonClassNames.GROOVY_LANG_INT_RANGE)) {
return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_LANG_INTEGER, context);
}
if (InheritanceUtil.isInheritor(iterType, GroovyCommonClassNames.GROOVY_LANG_OBJECT_RANGE)) {
PsiElement element = qualifier;
element = skipParentheses(element, false);
if (element instanceof GrReferenceExpression) {
GrReferenceExpression ref = (GrReferenceExpression)element;
element = skipParentheses(ref.resolve(), false);
}
if (element instanceof GrRangeExpression) {
return getRangeElementType((GrRangeExpression)element);
}
return null;
}
PsiType res = PsiUtil.extractIterableTypeParameter(iterType, true);
if (res != null) {
return PsiImplUtil.normalizeWildcardTypeByPosition(res, qualifier);
@@ -271,20 +267,6 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
return null;
}
@Nullable
private static PsiType getRangeElementType(GrRangeExpression range) {
GrExpression left = range.getLeftOperand();
GrExpression right = range.getRightOperand();
if (right != null) {
final PsiType leftType = left.getType();
final PsiType rightType = right.getType();
if (leftType != null && rightType != null) {
return TypesUtil.getLeastUpperBound(leftType, rightType, range.getManager());
}
}
return null;
}
@Nullable
private static String findMethodName(@NotNull GrMethodCall methodCall) {
GrExpression expression = methodCall.getInvokedExpression();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,6 +81,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
@@ -1231,11 +1232,7 @@ public class PsiUtil {
public static PsiType extractIteratedType(GrForInClause forIn) {
GrExpression iterated = forIn.getIteratedExpression();
if (iterated == null) return null;
PsiType type = iterated.getType();
if (type == null) return null;
if (type instanceof PsiArrayType) return ((PsiArrayType)type).getComponentType();
return com.intellij.psi.util.PsiUtil.extractIterableTypeParameter(type, true);
return ClosureParameterEnhancer.findTypeForIteration(iterated, forIn);
}
public static boolean isThisReference(@Nullable PsiElement expression) {