From ce3492f270fa702ef4226695b2c85c1b08feace6 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 8 May 2015 11:36:30 +0300 Subject: [PATCH] KT-6393 Smart completion of anonymous object inserts type with "!" for type parameter #KT-6393 Fixed --- .../renderer/DescriptorRendererImpl.java | 2 +- .../jetbrains/kotlin/idea/util/TypeUtils.kt | 14 ++++- .../idea/completion/smart/SmartCompletion.kt | 2 +- .../smart/TypeInstantiationItems.kt | 2 +- .../smart/AnonymousObjectGenericJava-1.kt | 3 + .../smart/AnonymousObjectGenericJava-2.kt | 3 + .../smart/AnonymousObjectGenericJava.java | 4 ++ .../smart/AnonymousObjectGenericJava.kt.after | 7 +++ .../AnonymousObjectGenericJava.java | 4 ++ .../AnonymousObjectGenericJava.kt | 5 ++ .../AnonymousObjectGenericJava/Comparator.kt | 3 + ...MultiFileSmartCompletionTestGenerated.java | 6 ++ .../SmartCompletionMultifileHandlerTest.java | 52 ------------------ .../SmartCompletionMultifileHandlerTest.kt | 55 +++++++++++++++++++ 14 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-1.kt create mode 100644 idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-2.kt create mode 100644 idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.java create mode 100644 idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.kt.after create mode 100644 idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.java create mode 100644 idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.kt create mode 100644 idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/Comparator.kt delete mode 100644 idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.java create mode 100644 idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.kt diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java index b2391b3ad4f..eea4adfd806 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java @@ -485,7 +485,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer { if (typeProjection.getProjectionKind() != Variance.INVARIANT) { builder.append(typeProjection.getProjectionKind()).append(" "); } - builder.append(renderNormalizedType(typeProjection.getType())); + builder.append(renderType(typeProjection.getType())); } if (iterator.hasNext()) { builder.append(", "); diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt index 8c0b5fe3706..2d617507d2e 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt @@ -47,13 +47,21 @@ public fun approximateFlexibleTypes(jetType: JetType, outermost: Boolean = true) // Foo<(Mutable)Collection!>! -> Foo>? // Foo! -> Foo? // Foo! -> Foo? - val approximation = + var approximation = if (isCollection) TypeUtils.makeNullableAsSpecified(if (jetType.isMarkedReadOnly()) flexible.upperBound else flexible.lowerBound, outermost) else if (outermost) flexible.upperBound else flexible.lowerBound - val approximated = approximateFlexibleTypes(approximation) - return if (jetType.isMarkedNotNull()) approximated.makeNotNullable() else approximated + + approximation = approximateFlexibleTypes(approximation) + + approximation = if (jetType.isMarkedNotNull()) approximation.makeNotNullable() else approximation + + if (approximation.isMarkedNullable() && !flexible.lowerBound.isMarkedNullable() && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)) { + approximation = approximation.makeNotNullable() + } + + return approximation } return JetTypeImpl( jetType.getAnnotations(), diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index 111614cf0cc..2352a70ddad 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -455,7 +455,7 @@ class SmartCompletion( val lookupString = lookupElement.getLookupString() val typeArgs = jetType.getArguments() - var itemText = lookupString + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgs) + var itemText = lookupString + IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgs) val typeText = DescriptorUtils.getFqName(classifier).toString() + IdeDescriptorRenderers.SOURCE_CODE.renderTypeArguments(typeArgs) val insertHandler: InsertHandler = object : InsertHandler { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt index 249f64b4dcc..b194c7bb9e4 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt @@ -147,7 +147,7 @@ class TypeInstantiationItems( // drop "in" and "out" from type arguments - they cannot be used in constructor call val typeArgsToUse = typeArgs.map { TypeProjectionImpl(Variance.INVARIANT, it.getType()) } - var itemText = lookupString + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgsToUse) + var itemText = lookupString + IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgsToUse) var signatureText: String? = null val insertHandler: InsertHandler diff --git a/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-1.kt b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-1.kt new file mode 100644 index 00000000000..503e2378680 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-1.kt @@ -0,0 +1,3 @@ +fun f(){ + JavaClass(obj) +} diff --git a/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-2.kt b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-2.kt new file mode 100644 index 00000000000..6e31f064fcb --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava-2.kt @@ -0,0 +1,3 @@ +public trait Comparator { + public fun compare(var1: T, var2: T): Int +} diff --git a/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.java b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.java new file mode 100644 index 00000000000..c088dac0b8d --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.java @@ -0,0 +1,4 @@ +class JavaClass { + JavaClass(Comparator comparator) { + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.kt.after b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.kt.after new file mode 100644 index 00000000000..bc587464227 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/smart/AnonymousObjectGenericJava.kt.after @@ -0,0 +1,7 @@ +fun f(){ + JavaClass(object: Comparator { + override fun compare(var1: T, var2: T): Int { + throw UnsupportedOperationException() + } + }) +} diff --git a/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.java b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.java new file mode 100644 index 00000000000..c088dac0b8d --- /dev/null +++ b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.java @@ -0,0 +1,4 @@ +class JavaClass { + JavaClass(Comparator comparator) { + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.kt b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.kt new file mode 100644 index 00000000000..7fbff60b70f --- /dev/null +++ b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/AnonymousObjectGenericJava.kt @@ -0,0 +1,5 @@ +fun f(){ + JavaClass() +} + +// EXIST: { itemText: "object: Comparator{...}" } diff --git a/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/Comparator.kt b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/Comparator.kt new file mode 100644 index 00000000000..6e31f064fcb --- /dev/null +++ b/idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/Comparator.kt @@ -0,0 +1,3 @@ +public trait Comparator { + public fun compare(var1: T, var2: T): Int +} diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/MultiFileSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/MultiFileSmartCompletionTestGenerated.java index f046171198e..44a8e4b6f6c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/MultiFileSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/MultiFileSmartCompletionTestGenerated.java @@ -35,6 +35,12 @@ public class MultiFileSmartCompletionTestGenerated extends AbstractMultiFileSmar JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/smartMultiFile"), Pattern.compile("^([^\\.]+)$"), false); } + @TestMetadata("AnonymousObjectGenericJava") + public void testAnonymousObjectGenericJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smartMultiFile/AnonymousObjectGenericJava/"); + doTest(fileName); + } + @TestMetadata("FunctionFromAnotherPackage") public void testFunctionFromAnotherPackage() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smartMultiFile/FunctionFromAnotherPackage/"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.java deleted file mode 100644 index 84a207d53a5..00000000000 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2010-2015 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 org.jetbrains.kotlin.idea.completion.test.handlers; - -import com.intellij.codeInsight.completion.CompletionType; -import org.jetbrains.kotlin.idea.completion.test.KotlinCompletionTestCase; -import org.jetbrains.kotlin.idea.completion.test.TestPackage; - -import java.io.File; - -public class SmartCompletionMultifileHandlerTest extends KotlinCompletionTestCase { - public void testImportExtensionFunction() throws Exception { - doTest(); - } - - public void testImportExtensionProperty() throws Exception { - doTest(); - } - - @Override - protected void setUp() throws Exception { - setType(CompletionType.SMART); - super.setUp(); - } - - public void doTest() throws Exception { - String fileName = getTestName(false); - - configureByFiles(null, fileName + "-1.kt", fileName + "-2.kt"); - complete(1); - checkResultByFile(fileName + ".kt.after"); - } - - @Override - protected String getTestDataPath() { - return new File(TestPackage.getCOMPLETION_TEST_DATA_BASE_PATH(), "/handlers/multifile/smart/").getPath() + File.separator; - } -} diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.kt new file mode 100644 index 00000000000..9fa9d8da59c --- /dev/null +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionMultifileHandlerTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2015 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 org.jetbrains.kotlin.idea.completion.test.handlers + +import com.intellij.codeInsight.completion.CompletionType +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.completion.test.COMPLETION_TEST_DATA_BASE_PATH +import org.jetbrains.kotlin.idea.completion.test.KotlinCompletionTestCase +import java.io.File +import kotlin.test.assertTrue + +public class SmartCompletionMultifileHandlerTest : KotlinCompletionTestCase() { + public fun testImportExtensionFunction() { doTest() } + + public fun testImportExtensionProperty() { doTest() } + + public fun testAnonymousObjectGenericJava() { doTest() } + + override fun setUp() { + setType(CompletionType.SMART) + super.setUp() + } + + public fun doTest() { + val fileName = getTestName(false) + + val fileNames = listOf(fileName + "-1.kt", fileName + "-2.kt", fileName + ".java") + + configureByFiles(null, *fileNames.filter { File(getTestDataPath() + it).exists() }.toTypedArray()) + + complete(1) + if (myItems != null) { + assertTrue(myItems.size() == 1, "Multiple items in completion") + selectItem(myItems[0]) + } + + checkResultByFile(fileName + ".kt.after") + } + + override fun getTestDataPath() = File(COMPLETION_TEST_DATA_BASE_PATH, "/handlers/multifile/smart/").getPath() + File.separator +}