KT-15744 Intention to import sleep wrongly suggests Thread.sleep
#KT-15744 fixed
This commit is contained in:
@@ -258,7 +258,67 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T, f
|
|||||||
internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
||||||
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
|
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
|
||||||
|
|
||||||
override val importNames = element?.mainReference?.resolvesByNames ?: emptyList()
|
private fun importNamesForMembers(): Collection<Name> {
|
||||||
|
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<Name> = ((element?.mainReference?.resolvesByNames ?: emptyList()) + importNamesForMembers()).distinct()
|
||||||
|
|
||||||
|
private fun collectMemberCandidates(
|
||||||
|
name: String,
|
||||||
|
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||||
|
indicesHelper: KotlinIndicesHelper
|
||||||
|
): List<DeclarationDescriptor> {
|
||||||
|
|
||||||
|
val element = element ?: return emptyList()
|
||||||
|
if (element.isImportDirectiveExpression() || isSelectorInQualified(element)) return emptyList()
|
||||||
|
|
||||||
|
val result = ArrayList<DeclarationDescriptor>()
|
||||||
|
|
||||||
|
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<DeclarationDescriptor> {
|
||||||
|
return super.fillCandidates(name, callTypeAndReceiver, bindingContext, indicesHelper) + collectMemberCandidates(name, callTypeAndReceiver, indicesHelper)
|
||||||
|
}
|
||||||
|
|
||||||
companion object MyFactory : Factory() {
|
companion object MyFactory : Factory() {
|
||||||
override fun createAction(diagnostic: Diagnostic) =
|
override fun createAction(diagnostic: Diagnostic) =
|
||||||
@@ -417,68 +477,6 @@ internal class ComponentsImportFix(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
|
||||||
override fun getText() = "Import member"
|
|
||||||
|
|
||||||
override fun fillCandidates(
|
|
||||||
name: String,
|
|
||||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
|
||||||
bindingContext: BindingContext,
|
|
||||||
indicesHelper: KotlinIndicesHelper
|
|
||||||
): List<DeclarationDescriptor> {
|
|
||||||
val element = element ?: return emptyList()
|
|
||||||
if (element.isImportDirectiveExpression() || isSelectorInQualified(element)) return emptyList()
|
|
||||||
|
|
||||||
val result = ArrayList<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
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<Name> = 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(
|
internal class ImportForMismatchingArgumentsFix(
|
||||||
expression: KtSimpleNameExpression
|
expression: KtSimpleNameExpression
|
||||||
) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
DEPRECATED_BINARY_MOD.registerFactory(removeModifierFactory)
|
DEPRECATED_BINARY_MOD.registerFactory(removeModifierFactory)
|
||||||
DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
|
DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
|
||||||
|
|
||||||
UNRESOLVED_REFERENCE.registerFactory(ImportMemberFix)
|
|
||||||
UNRESOLVED_REFERENCE.registerFactory(ImportFix)
|
UNRESOLVED_REFERENCE.registerFactory(ImportFix)
|
||||||
UNRESOLVED_REFERENCE.registerFactory(ImportConstructorReferenceFix)
|
UNRESOLVED_REFERENCE.registerFactory(ImportConstructorReferenceFix)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
package e
|
package e
|
||||||
|
|
||||||
enum class ImportEnum {
|
enum class ImportEnum {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
package e
|
package e
|
||||||
|
|
||||||
enum class ImportEnum {
|
enum class ImportEnum {
|
||||||
|
|||||||
@@ -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 = B<caret>LUE
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
package e
|
package e
|
||||||
|
|
||||||
enum class ImportEnum {
|
enum class ImportEnum {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
package e
|
package e
|
||||||
|
|
||||||
import e.ImportClass.Companion.BLUE
|
import e.ImportClass.Companion.BLUE
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// FILE: main.before.kt
|
// FILE: main.before.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
@@ -20,7 +20,7 @@ object Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: main.after.kt
|
// FILE: main.after.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// FILE: first.before.kt
|
// FILE: first.before.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
@@ -19,7 +19,7 @@ public class Bar {
|
|||||||
// FILE: first.after.kt
|
// FILE: first.after.kt
|
||||||
import foo.Bar.foobar
|
import foo.Bar.foobar
|
||||||
|
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// FILE: first.before.kt
|
// FILE: first.before.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
@@ -22,7 +22,7 @@ public class Bar {
|
|||||||
// FILE: first.after.kt
|
// FILE: first.after.kt
|
||||||
import foo.Bar.foobar
|
import foo.Bar.foobar
|
||||||
|
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// FILE: main.before.kt
|
// FILE: main.before.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
@@ -19,7 +19,7 @@ object Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: main.after.kt
|
// FILE: main.after.kt
|
||||||
// "Import member" "true"
|
// "Import" "true"
|
||||||
// ERROR: Unresolved reference: foobar
|
// ERROR: Unresolved reference: foobar
|
||||||
|
|
||||||
//KT-9009
|
//KT-9009
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import p1.sleep
|
||||||
|
|
||||||
|
// "Import" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
// ERROR: Unresolved reference: sleep
|
||||||
|
|
||||||
|
|
||||||
|
fun usage() {
|
||||||
|
sleep<caret>()
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package p1
|
||||||
|
|
||||||
|
fun sleep() {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// "Import" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
// ERROR: Unresolved reference: sleep
|
||||||
|
|
||||||
|
|
||||||
|
fun usage() {
|
||||||
|
sleep<caret>()
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// FILE: main.before.kt
|
// FILE: main.before.kt
|
||||||
// "Import member" "false"
|
// "Import" "false"
|
||||||
// ACTION: Create local variable 'foobar'
|
// ACTION: Create local variable 'foobar'
|
||||||
// ACTION: Create object 'foobar'
|
// ACTION: Create object 'foobar'
|
||||||
// ACTION: Create parameter 'foobar'
|
// ACTION: Create parameter 'foobar'
|
||||||
|
|||||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// ACTION: Create local variable 'A'
|
// ACTION: Create local variable 'A'
|
||||||
// ACTION: Create parameter 'A'
|
// ACTION: Create parameter 'A'
|
||||||
// ACTION: Create property 'A'
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Import member
|
// ACTION: Import
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
package p
|
package p
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
// ACTION: Create parameter 'A'
|
// ACTION: Create parameter 'A'
|
||||||
// ACTION: Create property 'A'
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ACTION: Import member
|
// ACTION: Import
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
package p
|
package p
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// ACTION: Create local variable 'A'
|
// ACTION: Create local variable 'A'
|
||||||
// ACTION: Create parameter 'A'
|
// ACTION: Create parameter 'A'
|
||||||
// ACTION: Create property 'A'
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Import member
|
// ACTION: Import
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
package p
|
package p
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// ACTION: Create local variable 'A'
|
// ACTION: Create local variable 'A'
|
||||||
// ACTION: Create parameter 'A'
|
// ACTION: Create parameter 'A'
|
||||||
// ACTION: Create property 'A'
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Import member
|
// ACTION: Import
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
package p
|
package p
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// ACTION: Create local variable 'A'
|
// ACTION: Create local variable 'A'
|
||||||
// ACTION: Create parameter 'A'
|
// ACTION: Create parameter 'A'
|
||||||
// ACTION: Create property 'A'
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Import member
|
// ACTION: Import
|
||||||
// ACTION: Rename reference
|
// ACTION: Rename reference
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
package p
|
package p
|
||||||
|
|||||||
@@ -343,8 +343,9 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer
|
|||||||
final String originalFileText = FileUtil.loadFile(mainFile, true);
|
final String originalFileText = FileUtil.loadFile(mainFile, true);
|
||||||
|
|
||||||
boolean withRuntime = InTextDirectivesUtils.isDirectiveDefined(originalFileText, "// WITH_RUNTIME");
|
boolean withRuntime = InTextDirectivesUtils.isDirectiveDefined(originalFileText, "// WITH_RUNTIME");
|
||||||
|
boolean fullJdk = InTextDirectivesUtils.isDirectiveDefined(originalFileText, "// FULL_JDK");
|
||||||
if (withRuntime) {
|
if (withRuntime) {
|
||||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk());
|
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, fullJdk ? PluginTestCaseBase.fullJdk() : PluginTestCaseBase.mockJdk());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -440,7 +441,8 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (withRuntime) {
|
if (withRuntime) {
|
||||||
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk());
|
ConfigLibraryUtil
|
||||||
|
.unConfigureKotlinRuntimeAndSdk(myModule, fullJdk ? PluginTestCaseBase.fullJdk() : PluginTestCaseBase.mockJdk());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,6 +390,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
|||||||
doTestWithExtraFile(fileName);
|
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")
|
@TestMetadata("minusOperator.before.Main.kt")
|
||||||
public void testMinusOperator() throws Exception {
|
public void testMinusOperator() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/minusOperator.before.Main.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/minusOperator.before.Main.kt");
|
||||||
|
|||||||
@@ -722,12 +722,6 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("enumEntriesJsRuntime.kt")
|
||||||
public void testEnumEntriesJsRuntime() throws Exception {
|
public void testEnumEntriesJsRuntime() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/enumEntriesJsRuntime.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user