diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/EachWithIndexClosureCompleter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/EachWithIndexClosureCompleter.java index 520de663aa88..a54c033f0103 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/EachWithIndexClosureCompleter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/EachWithIndexClosureCompleter.java @@ -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; + } + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java index 1a294ec2b7d3..d710b59b60cb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java @@ -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(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index cec40763a918..0a1ae5580aeb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -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) {