From 404d2487f1e243dc6bcb994effceb26d92416f20 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 9 Mar 2012 22:30:24 +0400 Subject: [PATCH] suggest to fill all the required type arguments at once (IDEA-26763) --- .../TypeArgumentCompletionProvider.java | 65 ++++++++++++++++--- .../smartType/SeveralTypeArguments-out.java | 5 ++ .../smartType/SeveralTypeArguments.java | 5 ++ .../SeveralTypeArgumentsSomeUnknown-out.java | 3 + .../SeveralTypeArgumentsSomeUnknown.java | 3 + .../smartType/afterNew/after13.java | 2 +- .../completion/SmartTypeCompletionTest.java | 6 +- 7 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java index 31d7b410b4ca..0a1990795a09 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java @@ -17,9 +17,9 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.CharTailType; import com.intellij.codeInsight.TailType; -import com.intellij.codeInsight.lookup.PsiTypeLookupItem; -import com.intellij.codeInsight.lookup.TailTypeDecorator; +import com.intellij.codeInsight.lookup.*; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.filters.getters.ExpectedTypesGetter; import com.intellij.psi.util.InheritanceUtil; @@ -27,10 +27,12 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Consumer; +import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -59,8 +61,8 @@ class TypeArgumentCompletionProvider extends CompletionProvider typeItems = new ArrayList(); + for (int i = index; i < params.length; i++) { + PsiType arg = getExpectedTypeArg(context, i, expectedType, currentSubstitutor, params); + if (arg == null) { + arg = getExpectedTypeArg(context, index, expectedType, currentSubstitutor, params); + if (arg != null) { + resultSet.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(arg, context), getTail(index == params.length - 1))); + } + return; + } + typeItems.add(PsiTypeLookupItem.createLookupItem(arg, context)); + } + + resultSet.addElement(LookupElementBuilder.create(typeItems.get(0).getObject(), typeItems.get(0).getLookupString()).setRenderer(new LookupElementRenderer() { + @Override + public void renderElement(LookupElement element, LookupElementPresentation presentation) { + typeItems.get(0).renderElement(presentation); + presentation.setItemText(StringUtil.join(typeItems, new Function() { + @Override + public String fun(PsiTypeLookupItem item) { + return item.getLookupString(); + } + }, ", ")); + presentation.setTailText(null); + presentation.setTypeText(null); + } + }).setInsertHandler(new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); + for (int i = 0; i < typeItems.size(); i++) { + CompletionUtil.emulateInsertion(context, context.getTailOffset(), typeItems.get(i)); + getTail(i == typeItems.size() - 1).processTail(context.getEditor(), context.getTailOffset()); + } + context.setAddCompletionChar(false); + } + })); + } + + @Nullable + private static PsiType getExpectedTypeArg(PsiElement context, + int index, + PsiClassType.ClassResolveResult expectedType, + PsiSubstitutor currentSubstitutor, PsiTypeParameter[] params) { + PsiClass expectedClass = expectedType.getElement(); + assert expectedClass != null; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(expectedClass)) { final PsiType argSubstitution = expectedType.getSubstitutor().substitute(parameter); final PsiType paramSubstitution = currentSubstitutor.substitute(parameter); final PsiType substitution = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper() .getSubstitutionForTypeParameter(params[index], paramSubstitution, argSubstitution, false, PsiUtil.getLanguageLevel(context)); if (substitution != null && substitution != PsiType.NULL) { - resultSet.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(substitution, context), getTail(actualClass, index))); + return substitution; } } + return null; } private static void addInheritors(CompletionParameters parameters, @@ -94,13 +143,13 @@ class TypeArgumentCompletionProvider extends CompletionProvider') : TailType.COMMA; + private static TailType getTail(boolean last) { + return last ? new CharTailType('>') : TailType.COMMA; } @Nullable diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments-out.java b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments-out.java new file mode 100644 index 000000000000..2c3c66313e77 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments-out.java @@ -0,0 +1,5 @@ +class HashMap {} + +public class A { + private HashMap m = new HashMap(); +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments.java b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments.java new file mode 100644 index 000000000000..5e62309ae3d4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArguments.java @@ -0,0 +1,5 @@ +class HashMap {} + +public class A { + private HashMap m = new HashMap<>(); +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown-out.java b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown-out.java new file mode 100644 index 000000000000..0a148ef74763 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown-out.java @@ -0,0 +1,3 @@ +class AAAAA{ + AAAAA asd = new AAAAA +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown.java b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown.java new file mode 100644 index 000000000000..915b39d94441 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/SeveralTypeArgumentsSomeUnknown.java @@ -0,0 +1,3 @@ +class AAAAA{ + AAAAA asd = new AAAAA< +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after13.java b/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after13.java index 4ffffb2667f1..aa55d681d903 100644 --- a/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after13.java +++ b/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after13.java @@ -1,3 +1,3 @@ class AAAAA{ - AAAAA asd = new AAAAA + AAAAA asd = new AAAAA } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 323952086592..408c85d3bbe3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -909,9 +909,9 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { doTest(); } - public void testExcessiveTail() throws Exception { - doTest(); - } + public void testExcessiveTail() throws Exception { doTest(); } + public void testSeveralTypeArguments() throws Exception { doTest(); } + public void testSeveralTypeArgumentsSomeUnknown() throws Exception { doTest(); } public void testExtendsInTypeCast() throws Exception { doTest();