dumb smart lambda completion (IDEA-112553)

This commit is contained in:
Anna Kozlova
2013-08-27 13:30:58 +04:00
parent 5647d35859
commit e9b1dfce36
6 changed files with 100 additions and 4 deletions
@@ -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<PsiElement> IN_TYPE_ARGS =
psiElement().inside(psiElement(PsiReferenceParameterList.class));
static final PsiElementPattern.Capture<PsiElement> 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,
@@ -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<CompletionParameters> {
@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<PsiParameter, String>() {
@Override
public String fun(PsiParameter parameter) {
return parameter.getName();
}
}, ",") + ")";
final LookupElementBuilder builder =
LookupElementBuilder.create(paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler<LookupElement>() {
@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));
}
}
}
}
}
@@ -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 ||
@@ -0,0 +1,3 @@
class Test {
Runnable r = () -> <caret>
}
@@ -0,0 +1,3 @@
class Test {
Runnable r = <caret>
}
@@ -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);