From e9b1dfce3670ebeaa8928a8335a5fd15d9c89151 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 27 Aug 2013 13:27:54 +0400 Subject: [PATCH] dumb smart lambda completion (IDEA-112553) --- .../JavaSmartCompletionContributor.java | 21 +++++- .../completion/LambdaCompletionProvider.java | 67 +++++++++++++++++++ .../src/com/intellij/psi/LambdaUtil.java | 4 +- .../smartType/InLambdaPosition-out.java | 3 + .../smartType/InLambdaPosition.java | 3 + .../completion/SmartType18CompletionTest.java | 6 +- 6 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java 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 9710f7550c99..ac752ed54ac1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.lookup.*; import com.intellij.openapi.util.Key; import com.intellij.patterns.ElementPattern; +import com.intellij.patterns.ElementPatternCondition; import com.intellij.patterns.PsiElementPattern; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; @@ -28,6 +29,7 @@ import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.filters.GeneratorFilter; import com.intellij.psi.filters.OrFilter; import com.intellij.psi.filters.getters.*; +import com.intellij.psi.filters.position.FilterPattern; import com.intellij.psi.filters.types.AssignableFromFilter; import com.intellij.psi.filters.types.AssignableGroupFilter; import com.intellij.psi.filters.types.AssignableToFilter; @@ -92,6 +94,21 @@ public class JavaSmartCompletionContributor extends CompletionContributor { psiElement().withText(")").withParent(PsiTypeCastExpression.class))); static final PsiElementPattern.Capture IN_TYPE_ARGS = psiElement().inside(psiElement(PsiReferenceParameterList.class)); + static final PsiElementPattern.Capture LAMBDA = psiElement().and(new FilterPattern(new ElementFilter() { + @Override + public boolean isAcceptable(Object element, @Nullable PsiElement context) { + if (context == null) return false; + final PsiElement originalElement = context.getOriginalElement(); + if (originalElement == null) return false; + final PsiElement rulezzRef = originalElement.getParent(); + return LambdaUtil.isValidLambdaContext(rulezzRef.getParent()); + } + + @Override + public boolean isClassAcceptable(Class hintClass) { + return true; + } + })); @Nullable private static ElementFilter getReferenceFilter(PsiElement element) { @@ -313,6 +330,8 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } } }); + + extend(CompletionType.SMART, LAMBDA, new LambdaCompletionProvider()); } private static void addExpectedTypeMembers(CompletionParameters params, diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java new file mode 100644 index 000000000000..eca5453c20f8 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorModificationUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Function; +import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class LambdaCompletionProvider extends CompletionProvider { + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return; + final ExpectedTypeInfo[] expectedTypes = JavaSmartCompletionContributor.getExpectedTypes(parameters); + for (ExpectedTypeInfo expectedType : expectedTypes) { + final PsiType defaultType = expectedType.getDefaultType(); + if (LambdaHighlightingUtil.checkInterfaceFunctional(defaultType) == null) { + final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(defaultType); + if (method != null) { + final PsiParameter[] params = method.getParameterList().getParameters(); + final String paramsString = "(" + StringUtil.join(params, new Function() { + @Override + public String fun(PsiParameter parameter) { + return parameter.getName(); + } + }, ",") + ")"; + final LookupElementBuilder builder = + LookupElementBuilder.create(paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + final Editor editor = context.getEditor(); + EditorModificationUtil.insertStringAtCaret(editor, " -> "); + PsiDocumentManager.getInstance(context.getProject()).commitDocument(editor.getDocument()); + } + }); + result.addElement(builder.withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE)); + } + } + } + } +} diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 2bfe47080530..b0a014949f75 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,7 +93,7 @@ public class LambdaUtil { return initialSubst; } - public static boolean isValidLambdaContext(PsiElement context) { + public static boolean isValidLambdaContext(@Nullable PsiElement context) { return context instanceof PsiTypeCastExpression || context instanceof PsiAssignmentExpression || context instanceof PsiVariable || diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java new file mode 100644 index 000000000000..8b6864c5e474 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition-out.java @@ -0,0 +1,3 @@ +class Test { + Runnable r = () -> +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java new file mode 100644 index 000000000000..8bda0afcc1d6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPosition.java @@ -0,0 +1,3 @@ +class Test { + Runnable r = +} \ 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 f8ea1ba949bc..c386bd3c0f7a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,10 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testInLambdaPosition() throws Exception { + doTest(); + } + private void doTest() { configureByFile("/" + getTestName(false) + ".java"); assertNotNull(myItems);