diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ImportFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ImportFix.kt index ae4497043c7..69455898198 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ImportFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ImportFix.kt @@ -258,7 +258,67 @@ internal abstract class OrdinaryImportFixBase(expression: T, f internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFixBase(expression, MyFactory) { override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) } - override val importNames = element?.mainReference?.resolvesByNames ?: emptyList() + private fun importNamesForMembers(): Collection { + val element = element ?: return emptyList() + + if (element.getIdentifier() != null) { + val name = element.getReferencedName() + if (Name.isValidIdentifier(name)) { + return Name.identifier(name).singletonList() + } + } + + return emptyList() + } + + override val importNames: Collection = ((element?.mainReference?.resolvesByNames ?: emptyList()) + importNamesForMembers()).distinct() + + private fun collectMemberCandidates( + name: String, + callTypeAndReceiver: CallTypeAndReceiver<*, *>, + indicesHelper: KotlinIndicesHelper + ): List { + + val element = element ?: return emptyList() + if (element.isImportDirectiveExpression() || isSelectorInQualified(element)) return emptyList() + + val result = ArrayList() + + val filterByCallType = callTypeAndReceiver.toFilter() + + indicesHelper.getKotlinEnumsByName(name).filterTo(result, filterByCallType) + + val processor = { descriptor: CallableDescriptor -> + if (descriptor.canBeReferencedViaImport() && filterByCallType(descriptor)) { + result.add(descriptor) + } + } + + indicesHelper.processKotlinCallablesByName( + name, + filter = { declaration -> (declaration.parent as? KtClassBody)?.parent is KtObjectDeclaration }, + processor = processor + ) + + if (TargetPlatformDetector.getPlatform(element.containingKtFile) == JvmPlatform) { + indicesHelper.processJvmCallablesByName( + name, + filter = { it.hasModifierProperty(PsiModifier.STATIC) }, + processor = processor + ) + } + return result + } + + + override fun fillCandidates( + name: String, + callTypeAndReceiver: CallTypeAndReceiver<*, *>, + bindingContext: BindingContext, + indicesHelper: KotlinIndicesHelper + ): List { + return super.fillCandidates(name, callTypeAndReceiver, bindingContext, indicesHelper) + collectMemberCandidates(name, callTypeAndReceiver, indicesHelper) + } companion object MyFactory : Factory() { override fun createAction(diagnostic: Diagnostic) = @@ -417,68 +477,6 @@ internal class ComponentsImportFix( } } -internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBase(expression, MyFactory) { - override fun getText() = "Import member" - - override fun fillCandidates( - name: String, - callTypeAndReceiver: CallTypeAndReceiver<*, *>, - bindingContext: BindingContext, - indicesHelper: KotlinIndicesHelper - ): List { - val element = element ?: return emptyList() - if (element.isImportDirectiveExpression() || isSelectorInQualified(element)) return emptyList() - - val result = ArrayList() - - val filterByCallType = callTypeAndReceiver.toFilter() - - indicesHelper.getKotlinEnumsByName(name).filterTo(result, filterByCallType) - - val processor = { descriptor: CallableDescriptor -> - if (descriptor.canBeReferencedViaImport() && filterByCallType(descriptor)) { - result.add(descriptor) - } - } - - indicesHelper.processKotlinCallablesByName( - name, - filter = { declaration -> (declaration.parent as? KtClassBody)?.parent is KtObjectDeclaration }, - processor = processor - ) - - if (TargetPlatformDetector.getPlatform(element.getContainingKtFile()) == JvmPlatform) { - indicesHelper.processJvmCallablesByName( - name, - filter = { it.hasModifierProperty(PsiModifier.STATIC) }, - processor = processor - ) - } - - return result - } - - override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) } - - override val importNames: Collection = run { - val element = element ?: return@run emptyList() - - if (element.getIdentifier() != null) { - val name = element.getReferencedName() - if (Name.isValidIdentifier(name)) { - return@run Name.identifier(name).singletonList() - } - } - return@run emptyList() - } - - companion object MyFactory : Factory() { - override fun createAction(diagnostic: Diagnostic) = (diagnostic.psiElement as? KtSimpleNameExpression)?.let { - ImportMemberFix(it).apply { computeSuggestions() } - } - } -} - internal class ImportForMismatchingArgumentsFix( expression: KtSimpleNameExpression ) : ImportFixBase(expression, MyFactory) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 5b228f9f909..d1a8b927393 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -138,7 +138,7 @@ class QuickFixRegistrar : QuickFixContributor { DEPRECATED_BINARY_MOD.registerFactory(removeModifierFactory) DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory) - UNRESOLVED_REFERENCE.registerFactory(ImportMemberFix) + UNRESOLVED_REFERENCE.registerFactory(ImportFix) UNRESOLVED_REFERENCE.registerFactory(ImportConstructorReferenceFix) diff --git a/idea/testData/quickfix/autoImports/enumEntries.kt b/idea/testData/quickfix/autoImports/enumEntries.kt index a75fd3aebb1..339f5818d96 100644 --- a/idea/testData/quickfix/autoImports/enumEntries.kt +++ b/idea/testData/quickfix/autoImports/enumEntries.kt @@ -1,4 +1,4 @@ -// "Import member" "true" +// "Import" "true" package e enum class ImportEnum { diff --git a/idea/testData/quickfix/autoImports/enumEntries.kt.after b/idea/testData/quickfix/autoImports/enumEntries.kt.after index 2e194fe3b6e..cfae789b9e7 100644 --- a/idea/testData/quickfix/autoImports/enumEntries.kt.after +++ b/idea/testData/quickfix/autoImports/enumEntries.kt.after @@ -1,4 +1,4 @@ -// "Import member" "true" +// "Import" "true" package e enum class ImportEnum { diff --git a/idea/testData/quickfix/autoImports/enumEntriesImportAbsentJsRuntime.kt b/idea/testData/quickfix/autoImports/enumEntriesImportAbsentJsRuntime.kt deleted file mode 100644 index b1476c268e0..00000000000 --- a/idea/testData/quickfix/autoImports/enumEntriesImportAbsentJsRuntime.kt +++ /dev/null @@ -1,24 +0,0 @@ -// "Import" "false" -// ACTION: Convert property initializer to getter -// ACTION: Create object 'BLUE' -// ACTION: Create property 'BLUE' -// ACTION: Import member -// ACTION: Rename reference -// ERROR: Unresolved reference: BLUE - -// Import should be present only in "Import member" action - - -package e - -enum class ImportEnum { - RED, GREEN, BLUE -} - -class ImportClass { - companion object { - val BLUE = 0 - } -} - -val v5 = BLUE \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt b/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt index d55b103b33c..46f91ac8992 100644 --- a/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt +++ b/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt @@ -1,4 +1,4 @@ -// "Import member" "true" +// "Import" "true" package e enum class ImportEnum { diff --git a/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt.after b/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt.after index 4fc7497d5bb..fea420760ee 100644 --- a/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt.after +++ b/idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt.after @@ -1,4 +1,4 @@ -// "Import member" "true" +// "Import" "true" package e import e.ImportClass.Companion.BLUE diff --git a/idea/testData/quickfix/autoImports/memberImportFunction.test b/idea/testData/quickfix/autoImports/memberImportFunction.test index b1da824df1f..2308f42e17f 100644 --- a/idea/testData/quickfix/autoImports/memberImportFunction.test +++ b/idea/testData/quickfix/autoImports/memberImportFunction.test @@ -1,5 +1,5 @@ // FILE: main.before.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 @@ -20,7 +20,7 @@ object Foo { } // FILE: main.after.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 diff --git a/idea/testData/quickfix/autoImports/memberImportJavaField.test b/idea/testData/quickfix/autoImports/memberImportJavaField.test index ce8083ae9dd..a7fed85e80b 100644 --- a/idea/testData/quickfix/autoImports/memberImportJavaField.test +++ b/idea/testData/quickfix/autoImports/memberImportJavaField.test @@ -1,5 +1,5 @@ // FILE: first.before.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 @@ -19,7 +19,7 @@ public class Bar { // FILE: first.after.kt import foo.Bar.foobar -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 diff --git a/idea/testData/quickfix/autoImports/memberImportJavaMethod.test b/idea/testData/quickfix/autoImports/memberImportJavaMethod.test index 8d06e530020..be3924a5ffe 100644 --- a/idea/testData/quickfix/autoImports/memberImportJavaMethod.test +++ b/idea/testData/quickfix/autoImports/memberImportJavaMethod.test @@ -1,5 +1,5 @@ // FILE: first.before.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 @@ -22,7 +22,7 @@ public class Bar { // FILE: first.after.kt import foo.Bar.foobar -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 diff --git a/idea/testData/quickfix/autoImports/memberImportProperty.test b/idea/testData/quickfix/autoImports/memberImportProperty.test index 0fff4d06118..f372b9feb5c 100644 --- a/idea/testData/quickfix/autoImports/memberImportProperty.test +++ b/idea/testData/quickfix/autoImports/memberImportProperty.test @@ -1,5 +1,5 @@ // FILE: main.before.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 @@ -19,7 +19,7 @@ object Foo { } // FILE: main.after.kt -// "Import member" "true" +// "Import" "true" // ERROR: Unresolved reference: foobar //KT-9009 diff --git a/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt new file mode 100644 index 00000000000..16812b20097 --- /dev/null +++ b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.after.kt @@ -0,0 +1,11 @@ +import p1.sleep + +// "Import" "true" +// WITH_RUNTIME +// FULL_JDK +// ERROR: Unresolved reference: sleep + + +fun usage() { + sleep() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Dependency.kt b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Dependency.kt new file mode 100644 index 00000000000..bab1e34ce37 --- /dev/null +++ b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Dependency.kt @@ -0,0 +1,5 @@ +package p1 + +fun sleep() { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt new file mode 100644 index 00000000000..58c01f5b844 --- /dev/null +++ b/idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt @@ -0,0 +1,9 @@ +// "Import" "true" +// WITH_RUNTIME +// FULL_JDK +// ERROR: Unresolved reference: sleep + + +fun usage() { + sleep() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test b/idea/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test index 75d12dee7b8..81ae6fb1bf3 100644 --- a/idea/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test +++ b/idea/testData/quickfix/autoImports/noMemberFunctionImportOnSimpleName.test @@ -1,5 +1,5 @@ // FILE: main.before.kt -// "Import member" "false" +// "Import" "false" // ACTION: Create local variable 'foobar' // ACTION: Create object 'foobar' // ACTION: Create parameter 'foobar' diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/annotationNoReceiver.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/annotationNoReceiver.kt index 2583f34ede4..e1a3233384b 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/annotationNoReceiver.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/annotationNoReceiver.kt @@ -3,7 +3,7 @@ // ACTION: Create local variable 'A' // ACTION: Create parameter 'A' // ACTION: Create property 'A' -// ACTION: Import member +// ACTION: Import // ACTION: Rename reference // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classNoReceiver.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classNoReceiver.kt index ebacdb61f37..f3514496c15 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classNoReceiver.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classNoReceiver.kt @@ -4,7 +4,7 @@ // ACTION: Create parameter 'A' // ACTION: Create property 'A' // ACTION: Rename reference -// ACTION: Import member +// ACTION: Import // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumEntryNoReceiver.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumEntryNoReceiver.kt index 5d8519641ea..a64b020e0ce 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumEntryNoReceiver.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumEntryNoReceiver.kt @@ -3,7 +3,7 @@ // ACTION: Create local variable 'A' // ACTION: Create parameter 'A' // ACTION: Create property 'A' -// ACTION: Import member +// ACTION: Import // ACTION: Rename reference // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumNoReceiver.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumNoReceiver.kt index e6b4d2b2ea9..e6abc56254a 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumNoReceiver.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/enumNoReceiver.kt @@ -3,7 +3,7 @@ // ACTION: Create local variable 'A' // ACTION: Create parameter 'A' // ACTION: Create property 'A' -// ACTION: Import member +// ACTION: Import // ACTION: Rename reference // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/traitNoReceiver.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/traitNoReceiver.kt index 57d7530feeb..2513c527773 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/traitNoReceiver.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/traitNoReceiver.kt @@ -3,7 +3,7 @@ // ACTION: Create local variable 'A' // ACTION: Create parameter 'A' // ACTION: Create property 'A' -// ACTION: Import member +// ACTION: Import // ACTION: Rename reference // ERROR: Unresolved reference: A package p diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java index 966137a857a..73cc1de3b35 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java @@ -343,8 +343,9 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer final String originalFileText = FileUtil.loadFile(mainFile, true); boolean withRuntime = InTextDirectivesUtils.isDirectiveDefined(originalFileText, "// WITH_RUNTIME"); + boolean fullJdk = InTextDirectivesUtils.isDirectiveDefined(originalFileText, "// FULL_JDK"); if (withRuntime) { - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()); + ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, fullJdk ? PluginTestCaseBase.fullJdk() : PluginTestCaseBase.mockJdk()); } try { @@ -440,7 +441,8 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer } finally { if (withRuntime) { - ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()); + ConfigLibraryUtil + .unConfigureKotlinRuntimeAndSdk(myModule, fullJdk ? PluginTestCaseBase.fullJdk() : PluginTestCaseBase.mockJdk()); } } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index e85443da402..b4c8cbc98e6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -390,6 +390,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes doTestWithExtraFile(fileName); } + @TestMetadata("memberWithTopLevelConflict.before.Main.kt") + public void testMemberWithTopLevelConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/memberWithTopLevelConflict.before.Main.kt"); + doTestWithExtraFile(fileName); + } + @TestMetadata("minusOperator.before.Main.kt") public void testMinusOperator() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/minusOperator.before.Main.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 1c842ac695c..c6e1dfb2100 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -722,12 +722,6 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } - @TestMetadata("enumEntriesImportAbsentJsRuntime.kt") - public void testEnumEntriesImportAbsentJsRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/enumEntriesImportAbsentJsRuntime.kt"); - doTest(fileName); - } - @TestMetadata("enumEntriesJsRuntime.kt") public void testEnumEntriesJsRuntime() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt");