diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/FunctionalExpressionCompletionProvider.java similarity index 50% rename from java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java rename to java/java-impl/src/com/intellij/codeInsight/completion/FunctionalExpressionCompletionProvider.java index 51990eafa3de..43789e6e4975 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/FunctionalExpressionCompletionProvider.java @@ -20,6 +20,8 @@ import com.intellij.codeInsight.generation.GenerateMembersUtil; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.project.Project; @@ -27,28 +29,32 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * User: anna */ -public class LambdaCompletionProvider extends CompletionProvider { +public class FunctionalExpressionCompletionProvider extends CompletionProvider { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { - result.addAllElements(getLambdaVariants(parameters)); + result.addAllElements(getLambdaVariants(parameters, false)); } - static List getLambdaVariants(@NotNull CompletionParameters parameters) { + static List getLambdaVariants(@NotNull CompletionParameters parameters, boolean prioritize) { if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return Collections.emptyList(); List result = ContainerUtil.newArrayList(); @@ -56,15 +62,15 @@ public class LambdaCompletionProvider extends CompletionProvider {}").withInsertHandler(new InsertHandler() { + LookupElementBuilder.create(functionalInterfaceMethod, paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler() { @Override public void handleInsert(InsertionContext context, LookupElement item) { final Editor editor = context.getEditor(); EditorModificationUtil.insertStringAtCaret(editor, " -> "); } - }); - result.add(builder.withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE)); + }).withIcon(AllIcons.Nodes.AnonymousClass); + LookupElement lambdaElement = builder.withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + if (prioritize) { + lambdaElement = PrioritizedLookupElement.withPriority(lambdaElement, 1); + } + result.add(lambdaElement); + + if (params.length == 1) { + final PsiType expectedReturnType = substitutor.substitute(functionalInterfaceMethod.getReturnType()); + if (expectedReturnType != null) { + final PsiClass paramClass = PsiUtil.resolveClassInClassTypeOnly(params[0].getType()); + if (paramClass != null && !paramClass.hasTypeParameters()) { + final Set visited = new HashSet(); + for (PsiMethod psiMethod : paramClass.getAllMethods()) { + final PsiType returnType = psiMethod.getReturnType(); + if (returnType != null && + psiMethod.getParameterList().getParametersCount() == 0 && + visited.add(psiMethod.getName()) && + !psiMethod.hasModifierProperty(PsiModifier.STATIC) && + JavaResolveUtil.isAccessible(psiMethod, null, psiMethod.getModifierList(), originalPosition, null, null) && + TypeConversionUtil.isAssignable(expectedReturnType, returnType)) { + LookupElement methodRefLookupElement = LookupElementBuilder + .create(psiMethod) + .withPresentableText(paramClass.getName() + "::" + psiMethod.getName()) + .withInsertHandler(new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + final int startOffset = context.getStartOffset(); + final Document document = context.getDocument(); + final PsiFile file = context.getFile(); + document.insertString(startOffset, "::"); + JavaCompletionUtil.insertClassReference(paramClass, file, startOffset); + } + }) + .withIcon(AllIcons.Nodes.AnonymousClass) + .withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + if (prioritize && psiMethod.getContainingClass() == paramClass) { + methodRefLookupElement = PrioritizedLookupElement.withPriority(methodRefLookupElement, 1); + } + result.add(methodRefLookupElement); + } + } + } + } + } } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 9789ec76a99a..5c42a1f0deaa 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -225,9 +225,7 @@ public class JavaCompletionContributor extends CompletionContributor { } if (JavaSmartCompletionContributor.LAMBDA.accepts(parameters.getPosition())) { - for (LookupElement element : LambdaCompletionProvider.getLambdaVariants(parameters)) { - result.addElement(PrioritizedLookupElement.withPriority(element, 1)); - } + result.addAllElements(FunctionalExpressionCompletionProvider.getLambdaVariants(parameters, true)); } PrefixMatcher matcher = result.getPrefixMatcher(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 21ffb966c1a4..6e6c2d7611ff 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -359,7 +359,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } }); - extend(CompletionType.SMART, LAMBDA, new LambdaCompletionProvider()); + extend(CompletionType.SMART, LAMBDA, new FunctionalExpressionCompletionProvider()); extend(CompletionType.SMART, METHOD_REFERENCE, new MethodReferenceCompletionProvider()); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference-out.java b/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference-out.java new file mode 100644 index 000000000000..2d2ee0535d75 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference-out.java @@ -0,0 +1,13 @@ +import java.util.List; + +class MyTest { + + void m(List l) { + l.stream().map(Person::getName) + } + +} + +interface Person { + String getName(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference.java b/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference.java new file mode 100644 index 000000000000..b654ed02ddb3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SimpleMethodReference.java @@ -0,0 +1,13 @@ +import java.util.List; + +class MyTest { + + void m(List l) { + l.stream().map() + } + +} + +interface Person { + String getName(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java index 68aba5eca978..7b9422407253 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java @@ -123,6 +123,10 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase { doTest(false); } + public void testSimpleMethodReference() throws Exception { + doTest(true); + } + private void doTest() { doTest(true); }