diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index fbcbccc3a5a..9951ee8b37d 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -94,7 +94,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, private val smartCompletion = expression?.let { SmartCompletion( it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, prefixMatcher, - GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory, callTypeAndReceiver, + GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, callTypeAndReceiver, isJvmModule, forBasicCompletion = true ) } @@ -197,7 +197,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) { if (smartCompletion != null) { - val (additionalItems, @Suppress("UNUSED_VARIABLE") inheritanceSearcher) = smartCompletion.additionalItems() + val (additionalItems, @Suppress("UNUSED_VARIABLE") inheritanceSearcher) = smartCompletion.additionalItems(lookupElementFactory) // all additional items should have SMART_COMPLETION_ITEM_PRIORITY_KEY to be recognized by SmartCompletionInBasicWeigher for (item in additionalItems) { @@ -211,8 +211,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, referenceVariants?.let { val (imported, notImported) = it - collector.addDescriptorElements(imported) - collector.addDescriptorElements(notImported, notImported = true) + collector.addDescriptorElements(imported, lookupElementFactory) + collector.addDescriptorElements(notImported, lookupElementFactory, notImported = true) } completeKeywords() @@ -243,10 +243,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, flushToResultSet() if (position.getContainingFile() is KtCodeFragment) { - val variants = getRuntimeReceiverTypeReferenceVariants() - if (variants != null) { - collector.addDescriptorElements(variants.imported, withReceiverCast = true) - collector.addDescriptorElements(variants.notImportedExtensions, withReceiverCast = true, notImported = true) + val variantsAndFactory = getRuntimeReceiverTypeReferenceVariants() + if (variantsAndFactory != null) { + val variants = variantsAndFactory.first + val lookupElementFactory = variantsAndFactory.second + collector.addDescriptorElements(variants.imported, lookupElementFactory, withReceiverCast = true) + collector.addDescriptorElements(variants.notImportedExtensions, lookupElementFactory, withReceiverCast = true, notImported = true) flushToResultSet() } } @@ -380,7 +382,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, private fun completeNonImported() { if (shouldCompleteTopLevelCallablesFromIndex()) { - collector.addDescriptorElements(getTopLevelCallables(), notImported = true) + collector.addDescriptorElements(getTopLevelCallables(), lookupElementFactory, notImported = true) } val classKindFilter: ((ClassKind) -> Boolean)? diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index 3163d469f9a..efc75036d89 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -143,7 +143,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC // LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) { - LookupElementsCollector(prefixMatcher, parameters, resultSet, lookupElementFactory, createSorter()) + LookupElementsCollector(prefixMatcher, parameters, resultSet, createSorter()) } protected val originalSearchScope: GlobalSearchScope = getResolveScope(parameters.getOriginalFile() as KtFile) @@ -329,7 +329,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC return this } - protected fun getRuntimeReceiverTypeReferenceVariants(): ReferenceVariants? { + protected fun getRuntimeReceiverTypeReferenceVariants(): Pair? { val explicitReceiver = callTypeAndReceiver.receiver as? KtExpression ?: return null val type = bindingContext.getType(explicitReceiver) ?: return null if (!TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, type)) return null @@ -340,7 +340,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC val (variants, notImportedExtensions) = collectReferenceVariants(descriptorKindFilter!!, ExpressionReceiver(explicitReceiver, runtimeType)) val filteredVariants = filterVariantsForRuntimeReceiverType(variants, referenceVariants!!.imported) val filteredNotImportedExtensions = filterVariantsForRuntimeReceiverType(notImportedExtensions, referenceVariants!!.notImportedExtensions) - return ReferenceVariants(filteredVariants, filteredNotImportedExtensions) + + val referenceVariants = ReferenceVariants(filteredVariants, filteredNotImportedExtensions) + return Pair(referenceVariants, lookupElementFactory.copy(receiverTypes = listOf(runtimeType))) } private fun filterVariantsForRuntimeReceiverType( @@ -383,7 +385,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC protected fun addClassesFromIndex(kindFilter: (ClassKind) -> Boolean) { AllClassesCompletion(parameters, indicesHelper, prefixMatcher, resolutionFacade, kindFilter) .collect( - { descriptor -> collector.addDescriptorElements(descriptor, notImported = true) }, + { descriptor -> collector.addDescriptorElements(descriptor, lookupElementFactory, notImported = true) }, { javaClass -> collector.addElement(lookupElementFactory.createLookupElementForJavaClass(javaClass), notImported = true) } ) } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index 2d047c5c714..f077f55e5fd 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -42,13 +42,14 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf +data /* we need copy() */ class LookupElementFactory( private val resolutionFacade: ResolutionFacade, private val receiverTypes: Collection?, private val callType: CallType<*>?, private val isInStringTemplateAfterDollar: Boolean, public val insertHandlerProvider: InsertHandlerProvider, - contextVariablesProvider: () -> Collection + private val contextVariablesProvider: () -> Collection ) { private val basicFactory = BasicLookupElementFactory(resolutionFacade.project, insertHandlerProvider) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt index 47fff4ec60a..ad5f4c47fde 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt @@ -31,7 +31,6 @@ class LookupElementsCollector( private val prefixMatcher: PrefixMatcher, private val completionParameters: CompletionParameters, resultSet: CompletionResultSet, - private val lookupElementFactory: LookupElementFactory, private val sorter: CompletionSorter ) { @@ -59,24 +58,28 @@ class LookupElementsCollector( } public fun addDescriptorElements(descriptors: Iterable, + lookupElementFactory: LookupElementFactory, notImported: Boolean = false, withReceiverCast: Boolean = false ) { for (descriptor in descriptors) { - addDescriptorElements(descriptor, notImported, withReceiverCast) + addDescriptorElements(descriptor, lookupElementFactory, notImported, withReceiverCast) } } - public fun addDescriptorElements(descriptor: DeclarationDescriptor, notImported: Boolean = false, withReceiverCast: Boolean = false) { - run { - var lookupElements = lookupElementFactory.createStandardLookupElementsForDescriptor(descriptor, useReceiverTypes = true) + public fun addDescriptorElements( + descriptor: DeclarationDescriptor, + lookupElementFactory: LookupElementFactory, + notImported: Boolean = false, + withReceiverCast: Boolean = false + ) { + var lookupElements = lookupElementFactory.createStandardLookupElementsForDescriptor(descriptor, useReceiverTypes = true) - if (withReceiverCast) { - lookupElements = lookupElements.map { it.withReceiverCast() } - } - - addElements(lookupElements, notImported) + if (withReceiverCast) { + lookupElements = lookupElements.map { it.withReceiverCast() } } + + addElements(lookupElements, notImported) } public fun addElement(element: LookupElement, notImported: Boolean = false) { 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 c9ec85a1200..cb942a1ede8 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 @@ -56,7 +56,6 @@ class SmartCompletion( private val prefixMatcher: PrefixMatcher, private val inheritorSearchScope: GlobalSearchScope, private val toFromOriginalFileMapper: ToFromOriginalFileMapper, - private val lookupElementFactory: LookupElementFactory, private val callTypeAndReceiver: CallTypeAndReceiver<*, *>, private val isJvmModule: Boolean, private val forBasicCompletion: Boolean = false @@ -83,11 +82,13 @@ class SmartCompletion( SmartCastCalculator(bindingContext, resolutionFacade.moduleDescriptor, expression, resolutionFacade) } - public val descriptorFilter: ((DeclarationDescriptor) -> Collection)? - = { descriptor: DeclarationDescriptor -> filterDescriptor(descriptor).map { postProcess(it) } }.check { expectedInfos.isNotEmpty() } + public val descriptorFilter: ((DeclarationDescriptor, LookupElementFactory) -> Collection)? = + { descriptor: DeclarationDescriptor, lookupElementFactory: LookupElementFactory -> + filterDescriptor(descriptor, lookupElementFactory).map { postProcess(it) } + }.check { expectedInfos.isNotEmpty() } - public fun additionalItems(): Pair, InheritanceItemsSearcher?> { - val (items, inheritanceSearcher) = additionalItemsNoPostProcess() + public fun additionalItems(lookupElementFactory: LookupElementFactory): Pair, InheritanceItemsSearcher?> { + val (items, inheritanceSearcher) = additionalItemsNoPostProcess(lookupElementFactory) val postProcessedItems = items.map { postProcess(it) } //TODO: could not use "let" because of KT-8754 val postProcessedSearcher = if (inheritanceSearcher != null) @@ -152,7 +153,7 @@ class SmartCompletion( return@lazy emptySet() } - private fun filterDescriptor(descriptor: DeclarationDescriptor): Collection { + private fun filterDescriptor(descriptor: DeclarationDescriptor, lookupElementFactory: LookupElementFactory): Collection { val callType = callTypeAndReceiver.callType if (descriptor in descriptorsToSkip) return emptyList() @@ -165,14 +166,14 @@ class SmartCompletion( } if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { - result.addCallableReferenceLookupElements(descriptor) + result.addCallableReferenceLookupElements(descriptor, lookupElementFactory) } return result } - private fun additionalItemsNoPostProcess(): Pair, InheritanceItemsSearcher?> { - val asTypePositionItems = buildForAsTypePosition() + private fun additionalItemsNoPostProcess(lookupElementFactory: LookupElementFactory): Pair, InheritanceItemsSearcher?> { + val asTypePositionItems = buildForAsTypePosition(lookupElementFactory) if (asTypePositionItems != null) { assert(expectedInfos.isEmpty()) return Pair(asTypePositionItems, null) @@ -320,7 +321,7 @@ class SmartCompletion( return null } - private fun MutableCollection.addCallableReferenceLookupElements(descriptor: DeclarationDescriptor) { + private fun MutableCollection.addCallableReferenceLookupElements(descriptor: DeclarationDescriptor, lookupElementFactory: LookupElementFactory) { if (callableTypeExpectedInfo.isEmpty()) return fun toLookupElement(descriptor: CallableDescriptor): LookupElement? { @@ -367,7 +368,7 @@ class SmartCompletion( } } - private fun buildForAsTypePosition(): Collection? { + private fun buildForAsTypePosition(lookupElementFactory: LookupElementFactory): Collection? { val binaryExpression = ((expression.getParent() as? KtUserType) ?.getParent() as? KtTypeReference) ?.getParent() as? KtBinaryExpressionWithTypeRHS diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt index 28a34af87ff..4a0fcf2606a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt @@ -50,7 +50,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para private val smartCompletion by lazy(LazyThreadSafetyMode.NONE) { expression?.let { SmartCompletion(it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, - prefixMatcher, originalSearchScope, toFromOriginalFileMapper, lookupElementFactory, + prefixMatcher, originalSearchScope, toFromOriginalFileMapper, callTypeAndReceiver, isJvmModule) } } @@ -67,28 +67,30 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para if (expression != null) { addFunctionLiteralArgumentCompletions() - val (additionalItems, inheritanceSearcher) = smartCompletion!!.additionalItems() + val (additionalItems, inheritanceSearcher) = smartCompletion!!.additionalItems(lookupElementFactory) collector.addElements(additionalItems) if (nameExpression != null) { val filter = smartCompletion!!.descriptorFilter if (filter != null) { val (imported, notImported) = referenceVariants!! - imported.forEach { collector.addElements(filter(it)) } - notImported.forEach { collector.addElements(filter(it), notImported = true) } + imported.forEach { collector.addElements(filter(it, lookupElementFactory)) } + notImported.forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) } flushToResultSet() if (shouldCompleteTopLevelCallablesFromIndex()) { - getTopLevelCallables().forEach { collector.addElements(filter(it), notImported = true) } + getTopLevelCallables().forEach { collector.addElements(filter(it, lookupElementFactory), notImported = true) } flushToResultSet() } if (position.getContainingFile() is KtCodeFragment) { - val variants = getRuntimeReceiverTypeReferenceVariants() - if (variants != null) { - variants.imported.forEach { collector.addElements(filter(it).map { it.withReceiverCast() }) } - variants.notImportedExtensions.forEach { collector.addElements(filter(it).map { it.withReceiverCast() }, notImported = true) } + val variantsAndFactory = getRuntimeReceiverTypeReferenceVariants() + if (variantsAndFactory != null) { + val variants = variantsAndFactory.first + val lookupElementFactory = variantsAndFactory.second + variants.imported.forEach { collector.addElements(filter(it, lookupElementFactory).map { it.withReceiverCast() }) } + variants.notImportedExtensions.forEach { collector.addElements(filter(it, lookupElementFactory).map { it.withReceiverCast() }, notImported = true) } flushToResultSet() } } diff --git a/idea/idea-completion/testData/basic/codeFragments/runtimeType/notImportedExtension.kt b/idea/idea-completion/testData/basic/codeFragments/runtimeType/notImportedExtension.kt index 1a4230d3440..3b148e044de 100644 --- a/idea/idea-completion/testData/basic/codeFragments/runtimeType/notImportedExtension.kt +++ b/idea/idea-completion/testData/basic/codeFragments/runtimeType/notImportedExtension.kt @@ -3,6 +3,7 @@ fun foo(o: Any) { } // INVOCATION_COUNT: 1 -// EXIST: read, write +// EXIST: { itemText: "read", attributes: "bold" } +// EXIST: { itemText: "write", attributes: "bold" } // RUNTIME_TYPE: java.util.concurrent.locks.ReentrantReadWriteLock \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt b/idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt index 08b83c17a37..fd174b5d711 100644 --- a/idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt +++ b/idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt @@ -12,7 +12,11 @@ open class Base { fun funInBoth() { } } -class Derived: Base() { +open class Intermediate : Base() { + fun funInIntermediate(){} +} + +class Derived : Intermediate() { fun funInDerived() { } override fun funWithOverride() { } @@ -21,12 +25,13 @@ class Derived: Base() { } // INVOCATION_COUNT: 1 -// EXIST: funInBase -// EXIST: funWithOverride -// EXIST: funWithoutOverride -// EXIST: funInDerived +// EXIST: { itemText: "funInBase", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funWithOverride", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funWithoutOverride", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funInDerived", tailText: "()", attributes: "bold" } // EXIST: { itemText: "funInBoth", tailText: "()", attributes: "bold" } -// EXIST: { itemText: "funInBoth", tailText: "(p: Int)", attributes: "grayed" } +// EXIST: { itemText: "funInBoth", tailText: "(p: Int)", attributes: "bold" } +// EXIST: { itemText: "funInIntermediate", tailText: "()", attributes: "" } // NOTHING_ELSE diff --git a/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt b/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt new file mode 100644 index 00000000000..92e3101099f --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt @@ -0,0 +1,41 @@ +fun main(args: Array) { + val b: Base = Derived() + val a = 1 +} + +open class Base { + fun funInBase(): Int = 0 + + open fun funWithOverride(): Int = 0 + open fun funWithoutOverride(): Int = 0 + + fun funInBoth(): Int = 0 +} + +open class Intermediate : Base() { + fun funInIntermediate() = 0 +} + +class Derived : Intermediate() { + fun funInDerived(): Int = 0 + + override fun funWithOverride(): Int = 0 + + fun funInBoth(p: Int): Int = 0 + + fun funWrongType(): String = "" +} + +// COMPLETION_TYPE: SMART +// INVOCATION_COUNT: 1 +// EXIST: { itemText: "funInBase", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funWithOverride", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funWithoutOverride", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funInDerived", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funInBoth", tailText: "()", attributes: "bold" } +// EXIST: { itemText: "funInBoth", tailText: "(p: Int)", attributes: "bold" } +// EXIST: { itemText: "funInIntermediate", tailText: "()", attributes: "" } +// NOTHING_ELSE + + +// RUNTIME_TYPE: Derived \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt.fragment b/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt.fragment new file mode 100644 index 00000000000..2df9e39aeac --- /dev/null +++ b/idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt.fragment @@ -0,0 +1 @@ +"".substring(b.fun) \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractCompiledKotlinInJavaCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractCompiledKotlinInJavaCompletionTest.kt index d48bebec996..3d6f4461987 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractCompiledKotlinInJavaCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractCompiledKotlinInJavaCompletionTest.kt @@ -24,6 +24,5 @@ public abstract class AbstractCompiledKotlinInJavaCompletionTest : JetFixtureCom override fun getPlatform() = JvmPlatform override fun getProjectDescriptor() = JdkAndMockLibraryProjectDescriptor(COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib", false) - - override fun complete(invocationCount: Int) = myFixture.complete(CompletionType.BASIC, invocationCount) + override fun defaultCompletionType() = CompletionType.BASIC } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java index a3e1f3e90ca..da5840f40e9 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJSBasicCompletionTest.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.testFramework.LightProjectDescriptor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager; import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor; import org.jetbrains.kotlin.js.resolve.JsPlatform; @@ -44,8 +45,9 @@ public abstract class AbstractJSBasicCompletionTest extends JetFixtureCompletion KotlinJavaScriptLibraryManager.getInstance(getProject()).syncUpdateProjectLibrary(); } + @NotNull @Override - protected LookupElement[] complete(int invocationCount) { - return myFixture.complete(CompletionType.BASIC, invocationCount); + protected CompletionType defaultCompletionType() { + return CompletionType.BASIC; } } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.java index dc69463bf51..3299a3a6816 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmBasicCompletionTest.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.completion.test; import com.intellij.codeInsight.completion.CompletionType; -import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.testFramework.LightProjectDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor; @@ -37,8 +36,9 @@ public abstract class AbstractJvmBasicCompletionTest extends JetFixtureCompletio return JvmPlatform.INSTANCE$; } + @NotNull @Override - protected LookupElement[] complete(int invocationCount) { - return myFixture.complete(CompletionType.BASIC, invocationCount); + protected CompletionType defaultCompletionType() { + return CompletionType.BASIC; } } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmSmartCompletionTest.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmSmartCompletionTest.java index ac37ec45df2..d28b3af3fde 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmSmartCompletionTest.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmSmartCompletionTest.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.completion.test; import com.intellij.codeInsight.completion.CompletionType; -import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.testFramework.LightProjectDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor; @@ -37,8 +36,9 @@ public abstract class AbstractJvmSmartCompletionTest extends JetFixtureCompletio return JvmPlatform.INSTANCE$; } + @NotNull @Override - protected LookupElement[] complete(int invocationCount) { - return myFixture.complete(CompletionType.SMART, invocationCount); + protected CompletionType defaultCompletionType() { + return CompletionType.SMART; } } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmWithLibBasicCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmWithLibBasicCompletionTest.kt index 0928c5faa70..a17a3f63044 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmWithLibBasicCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractJvmWithLibBasicCompletionTest.kt @@ -33,6 +33,5 @@ public abstract class AbstractJvmWithLibBasicCompletionTest : JetFixtureCompleti } override fun getPlatform() = JvmPlatform - - override fun complete(invocationCount: Int) = myFixture.complete(CompletionType.BASIC, invocationCount) + override fun defaultCompletionType() = CompletionType.BASIC } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKeywordCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKeywordCompletionTest.kt index b9c7ee54f11..66898683555 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKeywordCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKeywordCompletionTest.kt @@ -25,9 +25,11 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform public abstract class AbstractKeywordCompletionTest : JetFixtureCompletionBaseTestCase() { override fun getPlatform() = JvmPlatform - override fun complete(invocationCount: Int): Array? { - val items = myFixture.complete(CompletionType.BASIC) ?: return null - return items.filter { it.getObject() is KeywordLookupObject }.toTypedArray() + override fun defaultCompletionType() = CompletionType.BASIC + + override fun complete(completionType: CompletionType, invocationCount: Int): Array? { + val items = myFixture.complete(completionType) ?: return null + return items.filter { it.`object` is KeywordLookupObject }.toTypedArray() } override fun getProjectDescriptor() = JetLightProjectDescriptor.INSTANCE diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKotlinSourceInJavaCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKotlinSourceInJavaCompletionTest.kt index 0feb7d94153..6b71bc4820c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKotlinSourceInJavaCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractKotlinSourceInJavaCompletionTest.kt @@ -43,6 +43,5 @@ public abstract class AbstractKotlinSourceInJavaCompletionTest : JetFixtureCompl } override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST - - override fun complete(invocationCount: Int) = myFixture.complete(CompletionType.BASIC, invocationCount) + override fun defaultCompletionType() = CompletionType.BASIC } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileJvmBasicCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileJvmBasicCompletionTest.kt index 408520f1abb..96943b047c0 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileJvmBasicCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileJvmBasicCompletionTest.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.completion.test +import com.intellij.codeInsight.completion.CompletionType import org.jetbrains.kotlin.idea.test.AstAccessControl import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform @@ -24,10 +25,11 @@ public abstract class AbstractMultiFileJvmBasicCompletionTest : KotlinCompletion configureByFile(getTestName(false) + ".kt", "") val shouldFail = testPath.contains("NoSpecifiedType") AstAccessControl.testWithControlledAccessToAst(shouldFail, getFile().getVirtualFile(), getProject(), getTestRootDisposable(), { - testCompletion(getFile().getText(), JvmPlatform, { invocationCount -> + testCompletion(getFile().getText(), JvmPlatform, { completionType, invocationCount -> + setType(completionType) complete(invocationCount) myItems - }, 0) + }, CompletionType.BASIC, 0) }) } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileSmartCompletionTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileSmartCompletionTest.kt index f101a7e7b6b..d66dd4baa9c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileSmartCompletionTest.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/AbstractMultiFileSmartCompletionTest.kt @@ -29,10 +29,11 @@ public abstract class AbstractMultiFileSmartCompletionTest : KotlinCompletionTes protected fun doTest(testPath: String) { configureByFile(getTestName(false) + ".kt", "") AstAccessControl.testWithControlledAccessToAst(false, getFile().getVirtualFile(), getProject(), getTestRootDisposable(), { - testCompletion(getFile().getText(), JvmPlatform, { invocationCount -> + testCompletion(getFile().getText(), JvmPlatform, { completionType, invocationCount -> + setType(completionType) complete(invocationCount) myItems - }, 1) + }, CompletionType.SMART, 1) }) } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompletionTestUtil.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompletionTestUtil.kt index 57ad5508568..ec9db294175 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompletionTestUtil.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompletionTestUtil.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.completion.test import com.intellij.codeInsight.CodeInsightSettings +import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.lookup.LookupElement import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.test.JetTestUtils @@ -26,10 +27,11 @@ val RELATIVE_COMPLETION_TEST_DATA_BASE_PATH = "idea/idea-completion/testData" val COMPLETION_TEST_DATA_BASE_PATH = JetTestUtils.getHomeDirectory() + "/" + RELATIVE_COMPLETION_TEST_DATA_BASE_PATH -fun testCompletion(fileText: String, platform: TargetPlatform?, complete: (Int) -> Array?, defaultInvocationCount: Int = 0) { +fun testCompletion(fileText: String, platform: TargetPlatform?, complete: (CompletionType, Int) -> Array?, defaultCompletionType: CompletionType = CompletionType.BASIC, defaultInvocationCount: Int = 0) { testWithAutoCompleteSetting(fileText) { + val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType val invocationCount = ExpectedCompletionUtils.getInvocationCount(fileText) ?: defaultInvocationCount - val items = complete(invocationCount) ?: emptyArray() + val items = complete(completionType, invocationCount) ?: emptyArray() ExpectedCompletionUtils.assertDirectivesValid(fileText) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt index 4840390bcd9..305b3beb55c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList import com.google.gson.JsonNull import com.google.gson.JsonObject import com.google.gson.JsonParser +import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.lookup.impl.LookupCellRenderer @@ -113,6 +114,8 @@ public object ExpectedCompletionUtils { public val RUNTIME_TYPE: String = "RUNTIME_TYPE:" + private val COMPLETION_TYPE_PREFIX = "COMPLETION_TYPE:" + public val KNOWN_PREFIXES: List = ImmutableList.of( EXIST_LINE_PREFIX, ABSENT_LINE_PREFIX, @@ -128,6 +131,7 @@ public object ExpectedCompletionUtils { AUTOCOMPLETE_SETTING_PREFIX, NOTHING_ELSE_PREFIX, RUNTIME_TYPE, + COMPLETION_TYPE_PREFIX, AstAccessControl.ALLOW_AST_ACCESS_DIRECTIVE) public fun itemsShouldExist(fileText: String, platform: TargetPlatform?): Array { @@ -186,6 +190,16 @@ public object ExpectedCompletionUtils { return InTextDirectivesUtils.getPrefixedInt(fileText, INVOCATION_COUNT_PREFIX) } + public fun getCompletionType(fileText: String): CompletionType? { + val completionTypeString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_TYPE_PREFIX) + return when (completionTypeString) { + "BASIC" -> CompletionType.BASIC + "SMART" -> CompletionType.SMART + null -> null + else -> error("Unknown completion type: $completionTypeString") + } + } + public fun getAutocompleteSetting(fileText: String): Boolean? { return InTextDirectivesUtils.getPrefixedBoolean(fileText, AUTOCOMPLETE_SETTING_PREFIX) } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JetFixtureCompletionBaseTestCase.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JetFixtureCompletionBaseTestCase.kt index d17d4afda3b..261b00e7862 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JetFixtureCompletionBaseTestCase.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JetFixtureCompletionBaseTestCase.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.completion.test +import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.lookup.LookupElement import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker @@ -26,15 +27,17 @@ import java.io.File public abstract class JetFixtureCompletionBaseTestCase : JetLightCodeInsightFixtureTestCase() { public abstract fun getPlatform(): TargetPlatform - protected abstract fun complete(invocationCount: Int): Array? + protected open fun complete(completionType: CompletionType, invocationCount: Int): Array? + = myFixture.complete(completionType, invocationCount) + protected abstract fun defaultCompletionType(): CompletionType protected open fun defaultInvocationCount(): Int = 0 public open fun doTest(testPath: String) { setUpFixture(testPath) val fileText = FileUtil.loadFile(File(testPath), true) - testCompletion(fileText, getPlatform(), { complete(it) }, defaultInvocationCount()) + testCompletion(fileText, getPlatform(), { completionType, count -> complete(completionType, count) }, defaultCompletionType(), defaultInvocationCount()) } protected open fun setUpFixture(testPath: String) { diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt index 56531b30b42..8f7196251d1 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.completion.test.handlers import com.intellij.codeInsight.completion.CompletionType import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import org.jetbrains.kotlin.idea.completion.test.ExpectedCompletionUtils import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.test.InTextDirectivesUtils @@ -31,7 +32,6 @@ public abstract class AbstractCompletionHandlerTest(private val defaultCompletio private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:" private val TAIL_TEXT_PREFIX = "TAIL_TEXT:" private val COMPLETION_CHAR_PREFIX = "CHAR:" - private val COMPLETION_TYPE_PREFIX = "COMPLETION_TYPE:" private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:" protected open fun doTest(testPath: String) { @@ -54,13 +54,7 @@ public abstract class AbstractCompletionHandlerTest(private val defaultCompletio else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"") } - val completionTypeString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_TYPE_PREFIX) - val completionType = when (completionTypeString) { - "BASIC" -> CompletionType.BASIC - "SMART" -> CompletionType.SMART - null -> defaultCompletionType - else -> error("Unknown completion type: $completionTypeString") - } + val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType val codeStyleSettings = JetCodeStyleSettings.getInstance(getProject()) for (line in InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, CODE_STYLE_SETTING_PREFIX)) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt index 05f6116c70e..7662f1e8ec7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt @@ -36,7 +36,6 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.JetTestUtils import java.io.File -import kotlin.test.fail public abstract class AbstractCodeFragmentHighlightingTest : AbstractJetPsiCheckerTest() { override fun doTest(filePath: String) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt index f11529f53e9..9838fef68b3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionInLibraryTest.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.idea.debugger.evaluate -import com.intellij.codeInsight.completion.CompletionType import com.intellij.openapi.module.Module import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.OrderRootType @@ -68,9 +67,7 @@ public class CodeFragmentCompletionInLibraryTest : AbstractJvmBasicCompletionTes private fun testCompletionInLibraryCodeFragment(fragmentText: String, vararg completionDirectives: String) { setupFixtureByCodeFragment(fragmentText) val directives = completionDirectives.map { "//$it" }.joinToString(separator = "\n") - testCompletion(directives, JvmPlatform, { - myFixture.complete(CompletionType.BASIC) - }) + testCompletion(directives, JvmPlatform, { completionType, count -> myFixture.complete(completionType, count) }) } private fun setupFixtureByCodeFragment(fragmentText: String) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java index 778bb0de3a4..8ee316fc2d1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentCompletionTestGenerated.java @@ -126,5 +126,11 @@ public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCom String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/runtimeType/runtimeCast.kt"); doTest(fileName); } + + @TestMetadata("smartCompletion.kt") + public void testSmartCompletion() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/codeFragments/runtimeType/smartCompletion.kt"); + doTest(fileName); + } } } diff --git a/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractAndroidCompletionTest.kt b/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractAndroidCompletionTest.kt index 257c9b63b64..eacd88e917c 100644 --- a/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractAndroidCompletionTest.kt +++ b/plugins/android-idea-plugin/tests/org/jetbrains/kotlin/android/AbstractAndroidCompletionTest.kt @@ -48,9 +48,7 @@ public abstract class AbstractAndroidCompletionTest : KotlinAndroidTestCase() { val virtualFile = myFixture.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt"); myFixture.configureFromExistingVirtualFile(virtualFile) val fileText = FileUtil.loadFile(File(path + getTestName(true) + ".kt"), true) - testCompletion(fileText, JvmPlatform, { - count -> myFixture.complete(completionType()) - }) + testCompletion(fileText, JvmPlatform, { completionType, count -> myFixture.complete(completionType, count) }) }