resolve groovy method references to non-reflected methods (IDEA-138048 partial)

This commit is contained in:
peter
2015-04-01 15:54:25 +02:00
parent 7a607f9a68
commit ac2298deed
5 changed files with 44 additions and 22 deletions
@@ -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());
}
}
@@ -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<GrExpressi
@NotNull
private static GroovyResolveResult[] collapseReflectedMethods(GroovyResolveResult[] candidates) {
List<GroovyResolveResult> filtered = ContainerUtil.filter(candidates, new Condition<GroovyResolveResult>() {
@Override
public boolean value(GroovyResolveResult result) {
PsiElement element = result.getElement();
return !(element instanceof GrReflectedMethod && hasMoreCompleteOverload((GrReflectedMethod)element));
Set<GrMethod> visited = ContainerUtil.newHashSet();
List<GroovyResolveResult> 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<GrReflectedMethod>() {
@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) {
@@ -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)) {
@@ -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{} <warning descr="Empty \'catch\' block">catch</warning>(IOException e) {/*comment*/}')
}
public void testInvokingMethodReferenceWithDefaultParameters() { doTest(new GroovyAssignabilityCheckInspection()) }
}
@@ -0,0 +1,8 @@
class A {
def foo(int x = 0) {}
}
def v = new A().&foo
v(0)
v()