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) {
|
||||
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() {
|
||||
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(
|
||||
expression: KtSimpleNameExpression
|
||||
) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Import member" "true"
|
||||
// "Import" "true"
|
||||
package e
|
||||
|
||||
enum class ImportEnum {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Import member" "true"
|
||||
// "Import" "true"
|
||||
package e
|
||||
|
||||
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
|
||||
|
||||
enum class ImportEnum {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "Import member" "true"
|
||||
// "Import" "true"
|
||||
package e
|
||||
|
||||
import e.ImportClass.Companion.BLUE
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
// "Import member" "false"
|
||||
// "Import" "false"
|
||||
// ACTION: Create local variable 'foobar'
|
||||
// ACTION: Create object 'foobar'
|
||||
// ACTION: Create parameter 'foobar'
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user