diff --git a/plugins/groovy/resources/standardDsls/closuresInMethod.gdsl b/plugins/groovy/resources/standardDsls/closuresInMethod.gdsl index ff8b660db0fe..009d65ea5306 100644 --- a/plugins/groovy/resources/standardDsls/closuresInMethod.gdsl +++ b/plugins/groovy/resources/standardDsls/closuresInMethod.gdsl @@ -1,20 +1,20 @@ contributor(ctype: 'org.codehaus.groovy.runtime.DefaultGroovyMethods') { - closureInMethod(method: [name: 'eachWithIndex', params: ['T', 'groovy.lang.Closure']], params: [entry: null, i: 'int']) - closureInMethod(method: [name: 'inject', params: ['java.lang.Object', 'groovy.lang.Closure']], params: [acc: null, val: null]) + //closureInMethod(method: [name: 'eachWithIndex', params: ['T', 'groovy.lang.Closure']], params: [entry: null, i: 'int']) + closureInMethod(method: [name: 'inject', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [acc: null, val: 'T']) - closureInMethod(method: [name: 'min', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: null, b: null]) - closureInMethod(method: [name: 'min', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: null, b: null]) - closureInMethod(method: [name: 'min', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: null, b: null]) + closureInMethod(method: [name: 'min', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: 'T', b: "T"]) + closureInMethod(method: [name: 'min', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: 'T', b: 'T']) + closureInMethod(method: [name: 'min', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: 'java.util.Map.Entry', b: 'java.util.Map.Entry']) - closureInMethod(method: [name: 'min', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: null]) - closureInMethod(method: [name: 'min', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: null]) - closureInMethod(method: [name: 'min', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: null]) + closureInMethod(method: [name: 'min', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: 'T']) + closureInMethod(method: [name: 'min', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: 'T']) + closureInMethod(method: [name: 'min', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: 'java.util.Map.Entry']) - closureInMethod(method: [name: 'max', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: null, b: null]) - closureInMethod(method: [name: 'max', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: null, b: null]) - closureInMethod(method: [name: 'max', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: null, b: null]) + closureInMethod(method: [name: 'max', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: 'T', b: 'T']) + closureInMethod(method: [name: 'max', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: 'T', b: 'T']) + closureInMethod(method: [name: 'max', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: 'java.util.Map.Entry', b: 'java.util.Map.Entry']) - closureInMethod(method: [name: 'max', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: null]) - closureInMethod(method: [name: 'max', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: null]) - closureInMethod(method: [name: 'max', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: null]) + closureInMethod(method: [name: 'max', params: ['java.util.Collection', 'groovy.lang.Closure']], params: [a: 'T']) + closureInMethod(method: [name: 'max', params: ['java.util.Iterator', 'groovy.lang.Closure']], params: [a: 'T']) + closureInMethod(method: [name: 'max', params: ['java.util.Map', 'groovy.lang.Closure']], params: [a: 'java.util.Map.Entry']) } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureTemplateBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureTemplateBuilder.java index d9edac5a40e2..2985e0f653e5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureTemplateBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureTemplateBuilder.java @@ -25,8 +25,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.impl.compiled.ClsMethodImpl; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -52,12 +54,16 @@ public class ClosureTemplateBuilder { StringBuilder buffer = new StringBuilder(); buffer.append("{"); + + List paramTypes = ContainerUtil.newArrayList(); for (ClosureParameterInfo parameter : parameters) { final String type = parameter.getType(); final String name = parameter.getName(); if (type != null) { + if (method instanceof ClsMethodImpl) method = ((ClsMethodImpl)method).getSourceMirrorMethod(); final PsiType fromText = JavaPsiFacade.getElementFactory(project).createTypeFromText(type, method); final PsiType substituted = TypeConversionUtil.erasure(substitutor.substitute(fromText)); + paramTypes.add(substituted); buffer.append(substituted.getCanonicalText()).append(" "); } else { @@ -78,12 +84,13 @@ public class ClosureTemplateBuilder { final TemplateBuilderImpl builder = new TemplateBuilderImpl(templateClosure); + int i = 0; for (GrParameter p : templateClosure.getParameters()) { final GrTypeElement typeElement = p.getTypeElementGroovy(); final PsiElement nameIdentifier = p.getNameIdentifierGroovy(); if (typeElement != null) { - final TypeConstraint[] typeConstraints = {SupertypeConstraint.create(typeElement.getType())}; + final TypeConstraint[] typeConstraints = {SupertypeConstraint.create(paramTypes.get(i++))}; final ChooseTypeExpression expression = new ChooseTypeExpression(typeConstraints, PsiManager.getInstance(project), nameIdentifier.getResolveScope()); builder.replaceElement(typeElement, expression); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java index cee0e1250167..ea6526538488 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java @@ -58,6 +58,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor; +import org.jetbrains.plugins.groovy.lang.resolve.processors.SubstitutorComputer; import java.util.*; @@ -288,7 +289,7 @@ public class CompleteReferenceExpression { private static void addVariantsWithSameQualifier(PrefixMatcher matcher, PsiElement element, GrReferenceExpression patternExpression, - GrExpression patternQualifier, + @Nullable GrExpression patternQualifier, Set result) { if (element instanceof GrReferenceExpression && element != patternExpression && !PsiUtil.isLValue((GroovyPsiElement)element)) { final GrReferenceExpression refExpr = (GrReferenceExpression)element; @@ -377,6 +378,7 @@ public class CompleteReferenceExpression { private final boolean myMethodPointerOperator; private final boolean myIsMap; private Set myNonDeclaredVars = new com.intellij.util.containers.HashSet(); + private final SubstitutorComputer mySubstitutorComputer; protected CompleteReferenceProcessor(GrReferenceExpression place, Consumer consumer, @NotNull PrefixMatcher matcher, CompletionParameters parameters) { super(null, EnumSet.allOf(ResolveKind.class), place, PsiType.EMPTY_ARRAY); @@ -391,6 +393,8 @@ public class CompleteReferenceExpression { myFieldPointerOperator = place.hasAt(); myMethodPointerOperator = place.getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER; myIsMap = isMap(place); + final PsiType thisType = GrReferenceResolveUtil.getThisType(place); + mySubstitutorComputer = new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, PsiType.EMPTY_ARRAY, true, place, place.getParent()); } private static boolean shouldSkipPackages(GrReferenceExpression place) { @@ -416,6 +420,9 @@ public class CompleteReferenceExpression { PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY); if (substitutor == null) substitutor = PsiSubstitutor.EMPTY; + if (element instanceof PsiMethod) { + substitutor = mySubstitutorComputer.obtainSubstitutor(substitutor, (PsiMethod)element, state); + } consume(new GroovyResolveResultImpl(namedElement, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK)); } 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 b22ee5d0595d..c3130dac83d7 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 @@ -189,7 +189,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl accessorResults = new ArrayList(); for (String accessorName : accessorNames) { AccessorResolverProcessor accessorResolver = - new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments()); + new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, GrReferenceResolveUtil.getThisType(this), getTypeArguments()); GrReferenceResolveUtil.resolveImpl(accessorResolver, this); final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); @@ -300,7 +300,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl