completion for method references on raw receiver (IDEA-190839)

This commit is contained in:
Anna.Kozlova
2018-04-25 21:11:37 +02:00
parent a76933f6dd
commit 40af21eaeb
2 changed files with 23 additions and 6 deletions
@@ -240,7 +240,7 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
for (PsiMethod psiMethod : psiClass.getMethods()) {
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC) &&
hasAppropriateReturnType(expectedReturnType, psiMethod) &&
hasAppropriateReturnType(expectedReturnType, psiMethod, substitutor) &&
isSignatureAppropriate(psiMethod, params, substitutor, 0, originalPosition)) {
result.add(createMethodRefOnThis(functionalInterfaceType, psiMethod, first ? null : psiClass));
}
@@ -258,7 +258,7 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
for (PsiClass psiClass : JBIterable.generate(PsiTreeUtil.getParentOfType(originalPosition, PsiClass.class), PsiClass::getContainingClass)) {
for (PsiMethod psiMethod : psiClass.getMethods()) {
if (psiMethod.hasModifierProperty(PsiModifier.STATIC) &&
hasAppropriateReturnType(expectedReturnType, psiMethod) &&
hasAppropriateReturnType(expectedReturnType, psiMethod, substitutor) &&
isSignatureAppropriate(psiMethod, params, substitutor, 0, originalPosition)) {
result.add(createMethodRefOnClass(functionalInterfaceType, psiMethod, psiClass));
}
@@ -276,14 +276,14 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
List<LookupElement> result = new ArrayList<>();
final PsiType functionalInterfaceParamType = substitutor.substitute(params[0].getType());
final PsiClass paramClass = PsiUtil.resolveClassInClassTypeOnly(functionalInterfaceParamType);
if (paramClass != null && !paramClass.hasTypeParameters()) {
if (paramClass != null) {
final Set<String> visited = new HashSet<>();
for (PsiMethod psiMethod : paramClass.getAllMethods()) {
PsiClass containingClass = psiMethod.getContainingClass();
PsiClass qualifierClass = containingClass != null ? containingClass : paramClass;
if (visited.add(psiMethod.getName()) &&
!psiMethod.hasModifierProperty(PsiModifier.STATIC) &&
hasAppropriateReturnType(expectedReturnType, psiMethod) &&
hasAppropriateReturnType(expectedReturnType, psiMethod, substitutor) &&
isSignatureAppropriate(psiMethod, params, substitutor, 1, originalPosition)) {
LookupElement methodRefLookupElement = createMethodRefOnClass(functionalInterfaceType, psiMethod, qualifierClass);
if (prioritize && containingClass == paramClass) {
@@ -296,9 +296,11 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
return result;
}
private static boolean hasAppropriateReturnType(PsiType expectedReturnType, PsiMethod psiMethod) {
private static boolean hasAppropriateReturnType(PsiType expectedReturnType,
PsiMethod psiMethod,
PsiSubstitutor substitutor) {
PsiType returnType = psiMethod.getReturnType();
return returnType != null && TypeConversionUtil.isAssignable(expectedReturnType, returnType);
return returnType != null && TypeConversionUtil.isAssignable(expectedReturnType, substitutor.substitute(returnType));
}
private static boolean isSignatureAppropriate(PsiMethod psiMethod, PsiParameter[] params, PsiSubstitutor substitutor, int offset, PsiElement place) {
@@ -132,6 +132,21 @@ class MethodRef {
assert items.find {LookupElementPresentation.renderElement(it).itemText.contains('MethodRef::boo')}
}
void "test suggest receiver method reference for generic methods"() {
myFixture.configureByText "a.java", """
import java.util.*;
import java.util.stream.Stream;
class MethodRef {
private void m(Stream<Map.Entry<String, Integer>> stream) {
stream.map(<caret>);
}
}
"""
def items = myFixture.completeBasic()
assert items.find {LookupElementPresentation.renderElement(it).itemText.contains('Entry::getKey')}
}
void "test constructor ref"() {
myFixture.configureByText "a.java", """
interface Foo9 {