From a843c23f205260f3540e41ef543923dae45bb112 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Mon, 2 Sep 2019 13:10:07 +0700 Subject: [PATCH] Completion: add root prefix support #KT-10340 Fixed --- .../handlers/KotlinCallableInsertHandler.kt | 20 ++++--------- .../handlers/KotlinClassifierInsertHandler.kt | 28 +++++++++---------- .../ClassNameForMethodWithPackageConflict.kt | 9 ++++++ ...sNameForMethodWithPackageConflict.kt.after | 9 ++++++ .../ClassNameForMethodWithPackageConflict2.kt | 8 ++++++ ...NameForMethodWithPackageConflict2.kt.after | 8 ++++++ .../basic/ClassNameWithPackageConflict.kt | 7 +++++ .../ClassNameWithPackageConflict.kt.after | 9 ++++++ .../StaticFunctionFromJavaWithConflict.kt | 7 +++++ ...taticFunctionFromJavaWithConflict.kt.after | 9 ++++++ .../ClassNameFromKotlinWithPackageConflict.kt | 13 +++++++++ ...NameFromKotlinWithPackageConflict.kt.after | 13 +++++++++ .../BasicCompletionHandlerTestGenerated.java | 20 +++++++++++++ .../SmartCompletionHandlerTestGenerated.java | 5 ++++ ...ceBasicCompletionHandlerTestGenerated.java | 20 +++++++++++++ ...ceSmartCompletionHandlerTestGenerated.java | 5 ++++ 16 files changed, 160 insertions(+), 30 deletions(-) create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt create mode 100644 idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt create mode 100644 idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt.after create mode 100644 idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt create mode 100644 idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt.after diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt index 182194898dc..3677ba9215a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinCallableInsertHandler.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.idea.completion.handlers @@ -23,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.completion.isArtificialImportAliasedDescriptor import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject +import org.jetbrains.kotlin.idea.core.withRootPrefixIfNeeded import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.ImportInsertHelper @@ -32,7 +22,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDeclarationInsertHandler() { companion object { - private val shortenReferences = ShortenReferences({ ShortenReferences.Options.DEFAULT.copy(dropBracesInStringTemplates = false) }) + private val shortenReferences = ShortenReferences { ShortenReferences.Options.DEFAULT.copy(dropBracesInStringTemplates = false) } } override fun handleInsert(context: InsertionContext, item: LookupElement) { @@ -59,7 +49,7 @@ abstract class KotlinCallableInsertHandler(val callType: CallType<*>) : BaseDecl context.document.replaceString( context.startOffset, context.tailOffset, - fqName.render() + " " + fqName.withRootPrefixIfNeeded().render() + " " ) // insert space after for correct parsing psiDocumentManager.commitAllDocuments() diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt index 2c6dc3b462c..dd23592c56f 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinClassifierInsertHandler.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.idea.completion.handlers @@ -27,14 +16,17 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.completion.isAfterDot import org.jetbrains.kotlin.idea.completion.isArtificialImportAliasedDescriptor import org.jetbrains.kotlin.idea.core.ShortenReferences +import org.jetbrains.kotlin.idea.core.canAddRootPrefix import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver.Companion.ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE_WITH_DOT import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { @@ -76,12 +68,18 @@ object KotlinClassifierInsertHandler : BaseDeclarationInsertHandler() { "$;val v:" // if we have no reference in the current context we have a more complicated prefix to get one } val tempSuffix = ".xxx" // we add "xxx" after dot because of KT-9606 - document.replaceString(startOffset, context.tailOffset, tempPrefix + qualifiedName + tempSuffix) + val qualifierNameWithRootPrefix = qualifiedName.let { + if (FqName(it).canAddRootPrefix()) + ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE_WITH_DOT + it + else + it + } + document.replaceString(startOffset, context.tailOffset, tempPrefix + qualifierNameWithRootPrefix + tempSuffix) psiDocumentManager.commitAllDocuments() val classNameStart = startOffset + tempPrefix.length - val classNameEnd = classNameStart + qualifiedName.length + val classNameEnd = classNameStart + qualifierNameWithRootPrefix.length val rangeMarker = document.createRangeMarker(classNameStart, classNameEnd) val wholeRangeMarker = document.createRangeMarker(startOffset, classNameEnd + tempSuffix.length) diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt new file mode 100644 index 00000000000..ffa2029e0c8 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +fun buildTemplates() { + val kotlin = 42 + printl +} + +// ELEMENT: println +// TAIL_TEXT: "() (kotlin.io)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt.after b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt.after new file mode 100644 index 00000000000..4e7c6e2e225 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt.after @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +fun buildTemplates() { + val kotlin = 42 + println() +} + +// ELEMENT: println +// TAIL_TEXT: "() (kotlin.io)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt new file mode 100644 index 00000000000..d2afd813310 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +class kotlin +fun buildTemplates() { + printl +} + +// ELEMENT: println +// TAIL_TEXT: "() (kotlin.io)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt.after b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt.after new file mode 100644 index 00000000000..89e922d2125 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME +class kotlin +fun buildTemplates() { + println() +} + +// ELEMENT: println +// TAIL_TEXT: "() (kotlin.io)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt b/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt new file mode 100644 index 00000000000..66c5d82fc2e --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt @@ -0,0 +1,7 @@ +fun buildTemplates() { + val java = 1123 + Coll +} + +// ELEMENT: Collections +// TAIL_TEXT: " (java.util)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt.after b/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt.after new file mode 100644 index 00000000000..025b8f1ad99 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt.after @@ -0,0 +1,9 @@ +import java.util.Collections + +fun buildTemplates() { + val java = 1123 + Collections +} + +// ELEMENT: Collections +// TAIL_TEXT: " (java.util)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt b/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt new file mode 100644 index 00000000000..41337dd93fe --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt @@ -0,0 +1,7 @@ +fun buildTemplates() { + val java = 42 + Arrays.bina +} + +// ELEMENT: binarySearch +// TAIL_TEXT: "(a: IntArray!, key: Int) (java.util)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt.after b/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt.after new file mode 100644 index 00000000000..38177e6da72 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt.after @@ -0,0 +1,9 @@ +import java.util.Arrays + +fun buildTemplates() { + val java = 42 + Arrays.binarySearch() +} + +// ELEMENT: binarySearch +// TAIL_TEXT: "(a: IntArray!, key: Int) (java.util)" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt b/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt new file mode 100644 index 00000000000..77990e80b07 --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt @@ -0,0 +1,13 @@ +package templates + +enum class Family { + Collections +} + +fun buildTemplates(): List { + val templates = arrayListOf() + templates.add(Collection) + return templates +} + +// ELEMENT: Family.Collections \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt.after b/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt.after new file mode 100644 index 00000000000..af8091dd999 --- /dev/null +++ b/idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt.after @@ -0,0 +1,13 @@ +package templates + +enum class Family { + Collections +} + +fun buildTemplates(): List { + val templates = arrayListOf() + templates.add(Family.Collections) + return templates +} + +// ELEMENT: Family.Collections \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index dc927ca2528..40d27792f31 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -39,6 +39,21 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion runTest("idea/idea-completion/testData/handlers/basic/ClassKeywordBeforeName.kt"); } + @TestMetadata("ClassNameForMethodWithPackageConflict.kt") + public void testClassNameForMethodWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt"); + } + + @TestMetadata("ClassNameForMethodWithPackageConflict2.kt") + public void testClassNameForMethodWithPackageConflict2() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt"); + } + + @TestMetadata("ClassNameWithPackageConflict.kt") + public void testClassNameWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt"); + } + @TestMetadata("ClassWithClassObject.kt") public void testClassWithClassObject() throws Exception { runTest("idea/idea-completion/testData/handlers/basic/ClassWithClassObject.kt"); @@ -169,6 +184,11 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion runTest("idea/idea-completion/testData/handlers/basic/SpaceAfterParenthesisBug.kt"); } + @TestMetadata("StaticFunctionFromJavaWithConflict.kt") + public void testStaticFunctionFromJavaWithConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt"); + } + @TestMetadata("StringFakeConstructor.kt") public void testStringFakeConstructor() throws Exception { runTest("idea/idea-completion/testData/handlers/basic/StringFakeConstructor.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java index b0f7540ee98..edc17c8317e 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/SmartCompletionHandlerTestGenerated.java @@ -129,6 +129,11 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion runTest("idea/idea-completion/testData/handlers/smart/ClassInObject.kt"); } + @TestMetadata("ClassNameFromKotlinWithPackageConflict.kt") + public void testClassNameFromKotlinWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt"); + } + @TestMetadata("ClassObjectFieldKeywordName.kt") public void testClassObjectFieldKeywordName() throws Exception { runTest("idea/idea-completion/testData/handlers/smart/ClassObjectFieldKeywordName.kt"); diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceBasicCompletionHandlerTestGenerated.java b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceBasicCompletionHandlerTestGenerated.java index 38976a2667a..4e396647cac 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceBasicCompletionHandlerTestGenerated.java +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceBasicCompletionHandlerTestGenerated.java @@ -39,6 +39,21 @@ public class PerformanceBasicCompletionHandlerTestGenerated extends AbstractPerf runTest("idea/idea-completion/testData/handlers/basic/ClassKeywordBeforeName.kt"); } + @TestMetadata("ClassNameForMethodWithPackageConflict.kt") + public void testClassNameForMethodWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict.kt"); + } + + @TestMetadata("ClassNameForMethodWithPackageConflict2.kt") + public void testClassNameForMethodWithPackageConflict2() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameForMethodWithPackageConflict2.kt"); + } + + @TestMetadata("ClassNameWithPackageConflict.kt") + public void testClassNameWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/ClassNameWithPackageConflict.kt"); + } + @TestMetadata("ClassWithClassObject.kt") public void testClassWithClassObject() throws Exception { runTest("idea/idea-completion/testData/handlers/basic/ClassWithClassObject.kt"); @@ -169,6 +184,11 @@ public class PerformanceBasicCompletionHandlerTestGenerated extends AbstractPerf runTest("idea/idea-completion/testData/handlers/basic/SpaceAfterParenthesisBug.kt"); } + @TestMetadata("StaticFunctionFromJavaWithConflict.kt") + public void testStaticFunctionFromJavaWithConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/basic/StaticFunctionFromJavaWithConflict.kt"); + } + @TestMetadata("StringFakeConstructor.kt") public void testStringFakeConstructor() throws Exception { runTest("idea/idea-completion/testData/handlers/basic/StringFakeConstructor.kt"); diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceSmartCompletionHandlerTestGenerated.java b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceSmartCompletionHandlerTestGenerated.java index 930c1c063a8..7abbb8c850f 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceSmartCompletionHandlerTestGenerated.java +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceSmartCompletionHandlerTestGenerated.java @@ -129,6 +129,11 @@ public class PerformanceSmartCompletionHandlerTestGenerated extends AbstractPerf runTest("idea/idea-completion/testData/handlers/smart/ClassInObject.kt"); } + @TestMetadata("ClassNameFromKotlinWithPackageConflict.kt") + public void testClassNameFromKotlinWithPackageConflict() throws Exception { + runTest("idea/idea-completion/testData/handlers/smart/ClassNameFromKotlinWithPackageConflict.kt"); + } + @TestMetadata("ClassObjectFieldKeywordName.kt") public void testClassObjectFieldKeywordName() throws Exception { runTest("idea/idea-completion/testData/handlers/smart/ClassObjectFieldKeywordName.kt");