From 209dea1eda2e09b81c49845119131a41ff9d61d9 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Jul 2015 16:01:32 +0200 Subject: [PATCH] IDEA-140731 Second invocation of Smart Type completion should suggest to convert array to Stream --- ...erenceExpressionCompletionContributor.java | 55 ++++++++++++++----- .../smartType/ConvertToDoubleStream-out.java | 8 +++ .../smartType/ConvertToDoubleStream.java | 7 +++ .../smartType/ConvertToObjectStream-out.java | 8 +++ .../smartType/ConvertToObjectStream.java | 7 +++ .../completion/SmartType18CompletionTest.java | 14 +++++ .../com/intellij/psi/CommonClassNames.java | 2 + 7 files changed, 86 insertions(+), 15 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index f68c8b046079..0d362c864a7b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -293,7 +293,7 @@ public class ReferenceExpressionCompletionContributor { final String prefix = getItemText(object); if (prefix == null) return; - addArraysAsListConversions(element, prefix, itemType, result, qualifier, expectedType); + addConversionsToArray(element, prefix, itemType, result, qualifier, expectedType); addToArrayConversions(element, object, prefix, itemType, result, qualifier, expectedType); @@ -345,24 +345,23 @@ public class ReferenceExpressionCompletionContributor { return false; } - private static void addArraysAsListConversions(final PsiElement element, final String prefix, final PsiType itemType, final Consumer result, - @Nullable PsiElement qualifier, - final PsiType expectedType) throws IncorrectOperationException { - PsiType componentType = PsiUtil.extractIterableTypeParameter(expectedType, true); - if (componentType == null || - !(itemType instanceof PsiArrayType) || - !componentType.isAssignableFrom(((PsiArrayType)itemType).getComponentType())) { - return; - - } + private static void addConversionsToArray(final PsiElement element, + final String prefix, + final PsiType itemType, + final Consumer result, + @Nullable PsiElement qualifier, + final PsiType expectedType) throws IncorrectOperationException { + final String methodName = getArraysConversionMethod(itemType, expectedType); + if (methodName == null) return; + final String qualifierText = getQualifierText(qualifier); - final PsiExpression conversion = createExpression("java.util.Arrays.asList(" + qualifierText + prefix + ")", element); + final PsiExpression conversion = createExpression("java.util.Arrays." + methodName + "(" + qualifierText + prefix + ")", element); final LookupItem item = new ExpressionLookupItem(conversion); - @NonNls final String presentable = "Arrays.asList(" + qualifierText + prefix + ")"; + @NonNls final String presentable = "Arrays." + methodName + "(" + qualifierText + prefix + ")"; item.setLookupString(StringUtil.isEmpty(qualifierText) ? presentable : prefix); item.setPresentableText(presentable); - item.addLookupStrings(prefix, presentable, "asList(" + prefix + ")"); + item.addLookupStrings(prefix, presentable, methodName + "(" + prefix + ")"); item.setIcon(PlatformIcons.METHOD_ICON); item.setInsertHandler(new InsertHandler() { @Override @@ -376,7 +375,7 @@ public class ReferenceExpressionCompletionContributor { startOffset -= qualifierText.length(); final Project project = element.getProject(); final String callSpace = getSpace(CodeStyleSettingsManager.getSettings(project).SPACE_WITHIN_METHOD_CALL_PARENTHESES); - @NonNls final String newText = "java.util.Arrays.asList(" + callSpace + qualifierText + prefix + callSpace + ")"; + @NonNls final String newText = "java.util.Arrays." + methodName + "(" + callSpace + qualifierText + prefix + callSpace + ")"; document.replaceString(startOffset, tailOffset, newText); PsiDocumentManager.getInstance(project).commitDocument(document); @@ -394,6 +393,32 @@ public class ReferenceExpressionCompletionContributor { result.consume(item); } + @Nullable + private static String getArraysConversionMethod(PsiType itemType, PsiType expectedType) { + String methodName = "asList"; + PsiType componentType = PsiUtil.extractIterableTypeParameter(expectedType, true); + if (componentType == null) { + methodName = "stream"; + componentType = getStreamComponentType(expectedType); + PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(componentType); + if (unboxedType != null) { + componentType = unboxedType; + } + } + + if (componentType == null || + !(itemType instanceof PsiArrayType) || + !componentType.isAssignableFrom(((PsiArrayType)itemType).getComponentType())) { + return null; + + } + return methodName; + } + + private static PsiType getStreamComponentType(PsiType expectedType) { + return PsiUtil.substituteTypeParameter(expectedType, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM, 0, true); + } + private static void addToArrayConversions(final PsiElement element, final Object object, final String prefix, final PsiType itemType, final Consumer result, @Nullable final PsiElement qualifier, final PsiType expectedType) { diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream-out.java new file mode 100644 index 000000000000..caa00e5e3d20 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream-out.java @@ -0,0 +1,8 @@ +import java.util.Arrays; +import java.util.stream.DoubleStream; + +class Test { + DoubleStream m(double[] a) { + return Arrays.stream(a); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream.java b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream.java new file mode 100644 index 000000000000..39f46912bc2d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToDoubleStream.java @@ -0,0 +1,7 @@ +import java.util.stream.DoubleStream; + +class Test { + DoubleStream m(double[] a) { + return a; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream-out.java new file mode 100644 index 000000000000..304d314abd03 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream-out.java @@ -0,0 +1,8 @@ +import java.util.Arrays; +import java.util.stream.Stream; + +class Test { + Stream m(String[] a) { + return Arrays.stream(a); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream.java b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream.java new file mode 100644 index 000000000000..9c2728472078 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConvertToObjectStream.java @@ -0,0 +1,7 @@ +import java.util.stream.Stream; + +class Test { + Stream m(String[] a) { + return a; + } +} \ 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 472a53ef77a9..fa415652b9bb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java @@ -132,6 +132,20 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase { assertEmpty(myItems); } +public void testConvertToObjectStream() { + configureByTestName(); + myFixture.complete(CompletionType.SMART, 2); + myFixture.type('\n'); + checkResultByFile("/" + getTestName(false) + "-out.java"); + } + + public void testConvertToDoubleStream() { + configureByTestName(); + myFixture.complete(CompletionType.SMART, 2); + myFixture.type('\n'); + checkResultByFile("/" + getTestName(false) + "-out.java"); + } + private void doTest() { doTest(true); } diff --git a/platform/core-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java index 8d8aa6c85d77..fe3bcc25c065 100644 --- a/platform/core-api/src/com/intellij/psi/CommonClassNames.java +++ b/platform/core-api/src/com/intellij/psi/CommonClassNames.java @@ -100,6 +100,8 @@ public interface CommonClassNames { @NonNls String JAVA_UTIL_CONCURRENT_FUTURE = "java.util.concurrent.Future"; @NonNls String JAVA_UTIL_CONCURRENT_CALLABLE = "java.util.concurrent.Callable"; + @NonNls String JAVA_UTIL_STREAM_BASE_STREAM = "java.util.stream.BaseStream"; + @NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature"; @NonNls String CLASS_FILE_EXTENSION = ".class";