Completion: add root prefix support

#KT-10340 Fixed
This commit is contained in:
Dmitry Gridin
2019-09-02 13:10:07 +07:00
parent 7a4c3e4d6a
commit a843c23f20
16 changed files with 160 additions and 30 deletions
@@ -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()
@@ -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)
@@ -0,0 +1,9 @@
// WITH_RUNTIME
fun buildTemplates() {
val kotlin = 42
printl<caret>
}
// ELEMENT: println
// TAIL_TEXT: "() (kotlin.io)"
@@ -0,0 +1,9 @@
// WITH_RUNTIME
fun buildTemplates() {
val kotlin = 42
println()<caret>
}
// ELEMENT: println
// TAIL_TEXT: "() (kotlin.io)"
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class kotlin
fun buildTemplates() {
printl<caret>
}
// ELEMENT: println
// TAIL_TEXT: "() (kotlin.io)"
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class kotlin
fun buildTemplates() {
println()<caret>
}
// ELEMENT: println
// TAIL_TEXT: "() (kotlin.io)"
@@ -0,0 +1,7 @@
fun buildTemplates() {
val java = 1123
Coll<caret>
}
// ELEMENT: Collections
// TAIL_TEXT: " (java.util)"
@@ -0,0 +1,9 @@
import java.util.Collections
fun buildTemplates() {
val java = 1123
Collections<caret>
}
// ELEMENT: Collections
// TAIL_TEXT: " (java.util)"
@@ -0,0 +1,7 @@
fun buildTemplates() {
val java = 42
Arrays.bina<caret>
}
// ELEMENT: binarySearch
// TAIL_TEXT: "(a: IntArray!, key: Int) (java.util)"
@@ -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)"
@@ -0,0 +1,13 @@
package templates
enum class Family {
Collections
}
fun buildTemplates(): List<Family> {
val templates = arrayListOf<Family>()
templates.add(Collection<caret>)
return templates
}
// ELEMENT: Family.Collections
@@ -0,0 +1,13 @@
package templates
enum class Family {
Collections
}
fun buildTemplates(): List<Family> {
val templates = arrayListOf<Family>()
templates.add(Family.Collections)
return templates
}
// ELEMENT: Family.Collections
@@ -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");
@@ -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");
@@ -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");
@@ -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");