diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index b0aeaf89816d..afc0f194d8cd 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -972,4 +972,19 @@ public class PsiImplUtil { } return null; } + + @NotNull + public static GroovyResolveResult reflectedToBase(GroovyResolveResult result, GrMethod baseMethod, GrReflectedMethod reflectedMethod) { + PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; + PsiTypeParameter[] reflectedParameters = reflectedMethod.getTypeParameters(); + PsiTypeParameter[] baseParameters = baseMethod.getTypeParameters(); + assert baseParameters.length == reflectedParameters.length; + for (int i = 0; i < baseParameters.length; i++) { + substitutor = substitutor.put(baseParameters[i], result.getSubstitutor().substitute(reflectedParameters[i])); + } + + return new GroovyResolveResultImpl(baseMethod, result.getCurrentFileResolveContext(), result.getSpreadState(), + substitutor, result.isAccessible(), result.isStaticsOK(), + result.isInvokedOnProperty(), result.isValidResult()); + } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index b4381a090090..141c5e2f6659 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -49,6 +49,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList; @@ -403,24 +404,20 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl filtered = ContainerUtil.filter(candidates, new Condition() { - @Override - public boolean value(GroovyResolveResult result) { - PsiElement element = result.getElement(); - return !(element instanceof GrReflectedMethod && hasMoreCompleteOverload((GrReflectedMethod)element)); + Set visited = ContainerUtil.newHashSet(); + List collapsed = ContainerUtil.newArrayList(); + for (GroovyResolveResult result : candidates) { + PsiElement element = result.getElement(); + if (element instanceof GrReflectedMethod) { + GrMethod baseMethod = ((GrReflectedMethod)element).getBaseMethod(); + if (visited.add(baseMethod)) { + collapsed.add(PsiImplUtil.reflectedToBase(result, baseMethod, (GrReflectedMethod)element)); + } + } else { + collapsed.add(result); } - - private boolean hasMoreCompleteOverload(GrReflectedMethod element) { - final int skipped = element.getSkippedParameters().length; - return ContainerUtil.or(element.getBaseMethod().getReflectedMethods(), new Condition() { - @Override - public boolean value(GrReflectedMethod method) { - return method.getSkippedParameters().length > skipped; - } - }); - } - }); - return filtered.toArray(new GroovyResolveResult[filtered.size()]); + } + return collapsed.toArray(new GroovyResolveResult[collapsed.size()]); } private static void assertAllAreValid(@NotNull GroovyResolveResult[] candidates) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java index 15337889bd84..cbd54abfbbbb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java @@ -489,12 +489,11 @@ public class CompleteReferenceExpression { } if (element instanceof GrReflectedMethod) { - element = ((GrReflectedMethod)element).getBaseMethod(); - if (!myProcessedMethodWithOptionalParams.add((GrMethod)element)) return; + GrMethod base = ((GrReflectedMethod)element).getBaseMethod(); + if (!myProcessedMethodWithOptionalParams.add(base)) return; - result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(), result.getSpreadState(), - result.getSubstitutor(), result.isAccessible(), result.isStaticsOK(), - result.isInvokedOnProperty(), result.isValidResult()); + result = PsiImplUtil.reflectedToBase(result, base, (GrReflectedMethod)element); + element = base; } if (myFieldPointerOperator && !(element instanceof PsiVariable)) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy index 246c5ca0b7f5..d294dbf5c047 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.lang.highlighting +import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection import org.jetbrains.plugins.groovy.codeInspection.bugs.* import org.jetbrains.plugins.groovy.codeInspection.confusing.* @@ -324,4 +325,6 @@ try{} catch(IOException e) {/*comment*/} testHighlighting('try{} catch(IOException e) {/*comment*/}') } + public void testInvokingMethodReferenceWithDefaultParameters() { doTest(new GroovyAssignabilityCheckInspection()) } + } diff --git a/plugins/groovy/testdata/highlighting/InvokingMethodReferenceWithDefaultParameters.groovy b/plugins/groovy/testdata/highlighting/InvokingMethodReferenceWithDefaultParameters.groovy new file mode 100644 index 000000000000..06e0848ea731 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/InvokingMethodReferenceWithDefaultParameters.groovy @@ -0,0 +1,8 @@ +class A { + def foo(int x = 0) {} +} + +def v = new A().&foo + +v(0) +v() \ No newline at end of file