Fix import quickfix if import has import alias
#KT-30669 Fixed #KT-7380 Fixed #KT-30663 Fixed
This commit is contained in:
@@ -174,6 +174,10 @@ open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) :
|
||||
fun findImportByAlias(name: String): KtImportDirective? =
|
||||
importDirectives.firstOrNull { name == it.aliasName }
|
||||
|
||||
fun findAliasByFqName(fqName: FqName): KtImportAlias? = importDirectives.firstOrNull {
|
||||
fqName == it.importedFqName
|
||||
}?.alias
|
||||
|
||||
@Deprecated("") // getPackageFqName should be used instead
|
||||
override fun getPackageName(): String {
|
||||
return packageFqName.asString()
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -195,7 +196,8 @@ class KotlinAddImportAction internal constructor(
|
||||
}
|
||||
|
||||
private fun addImport(variant: AutoImportVariant) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
val psiDocumentManager = PsiDocumentManager.getInstance(project)
|
||||
psiDocumentManager.commitAllDocuments()
|
||||
|
||||
project.executeWriteCommand(QuickFixBundle.message("add.import")) {
|
||||
if (!element.isValid) return@executeWriteCommand
|
||||
@@ -207,15 +209,27 @@ class KotlinAddImportAction internal constructor(
|
||||
StatisticsManager.getInstance().incUseCount(PsiProximityComparator.STATISTICS_KEY, it, location)
|
||||
}
|
||||
|
||||
for (descriptor in variant.descriptorsToImport) {
|
||||
variant.descriptorsToImport.forEach { descriptor ->
|
||||
// for class or package we use ShortenReferences because we not necessary insert an import but may want to
|
||||
// insert partly qualified name
|
||||
if (descriptor is ClassDescriptor || descriptor is PackageViewDescriptor) {
|
||||
|
||||
val importAlias = descriptor.importableFqName?.let { file.findAliasByFqName(it) }
|
||||
if (importAlias != null || descriptor is ClassDescriptor || descriptor is PackageViewDescriptor) {
|
||||
if (element is KtSimpleNameExpression) {
|
||||
element.mainReference.bindToFqName(
|
||||
descriptor.importableFqName!!,
|
||||
KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING
|
||||
)
|
||||
if (importAlias != null) {
|
||||
importAlias.nameIdentifier?.copy()?.let { element.getIdentifier()?.replace(it) }
|
||||
val resultDescriptor = element.resolveMainReferenceToDescriptors().firstOrNull()
|
||||
if (resultDescriptor == descriptor) {
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
|
||||
descriptor.importableFqName?.let {
|
||||
element.mainReference.bindToFqName(
|
||||
it,
|
||||
KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImportInsertHelper.getInstance(project).importDescriptor(file, descriptor)
|
||||
@@ -289,8 +303,10 @@ internal interface AutoImportVariant {
|
||||
DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptorsToImport.first())
|
||||
}
|
||||
|
||||
private class GroupedImportVariant(val autoImportDescription: String, val descriptors: Collection<DeclarationDescriptor>) :
|
||||
AutoImportVariant {
|
||||
private class GroupedImportVariant(
|
||||
val autoImportDescription: String,
|
||||
val descriptors: Collection<DeclarationDescriptor>
|
||||
) : AutoImportVariant {
|
||||
override val excludeFqNameCheck: FqName = descriptors.first().importableFqName!!.parent()
|
||||
override val descriptorsToImport: Collection<DeclarationDescriptor> get() = descriptors
|
||||
override val hint: String get() = "$autoImportDescription from $excludeFqNameCheck"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: ImportedClass
|
||||
|
||||
import editor.completion.apx.ImportedClass as Class2
|
||||
fun context() {
|
||||
val c: Class2
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
package editor.completion.apx
|
||||
class ImportedClass
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: ImportedClass
|
||||
|
||||
import editor.completion.apx.ImportedClass as Class2
|
||||
fun context() {
|
||||
val c: <caret>ImportedClass
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: ImportedClass
|
||||
|
||||
import editor.completion.apx.ImportedClass as Class2
|
||||
fun context() {
|
||||
class Class2
|
||||
val c: editor.completion.apx.ImportedClass
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
package editor.completion.apx
|
||||
class ImportedClass
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: ImportedClass
|
||||
|
||||
import editor.completion.apx.ImportedClass as Class2
|
||||
fun context() {
|
||||
class Class2
|
||||
val c: <caret>ImportedClass
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedFunA
|
||||
|
||||
import editor.completion.apx.importedFunA as funA
|
||||
fun context() {
|
||||
val funA = 42
|
||||
funA()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
package editor.completion.apx
|
||||
fun importedFunA() {}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedFunA
|
||||
|
||||
import editor.completion.apx.importedFunA as funA
|
||||
fun context() {
|
||||
val funA = 42
|
||||
<caret>importedFunA()
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedFunA
|
||||
|
||||
import editor.completion.apx.importedFunA as funA
|
||||
fun context() {
|
||||
fun funA() {}
|
||||
editor.completion.apx.importedFunA()
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
package editor.completion.apx
|
||||
fun importedFunA() {}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedFunA
|
||||
|
||||
import editor.completion.apx.importedFunA as funA
|
||||
fun context() {
|
||||
fun funA() {}
|
||||
<caret>importedFunA()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Import" "true"
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.let as let1
|
||||
|
||||
fun main() {
|
||||
1.<caret>let {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Import" "true"
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.let as let1
|
||||
|
||||
fun main() {
|
||||
1.let1 {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedValA
|
||||
|
||||
import editor.completion.apx.importedValA as valA
|
||||
fun context() {
|
||||
valA()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
package editor.completion.apx
|
||||
val importedValA = ""
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: importedValA
|
||||
|
||||
import editor.completion.apx.importedValA as valA
|
||||
fun context() {
|
||||
<caret>importedValA()
|
||||
}
|
||||
+25
@@ -595,6 +595,31 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
runTest("idea/testData/quickfix/autoImports/functionImport.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasClassAlreadyExists.before.Main.kt")
|
||||
public void testImportAliasClassAlreadyExists() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasClassAlreadyExists.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasClassAlreadyExistsCollision.before.Main.kt")
|
||||
public void testImportAliasClassAlreadyExistsCollision() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasClassAlreadyExistsCollision.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasFunctionAlreadyExists.before.Main.kt")
|
||||
public void testImportAliasFunctionAlreadyExists() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasFunctionAlreadyExists.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasFunctionAlreadyExistsCollision.before.Main.kt")
|
||||
public void testImportAliasFunctionAlreadyExistsCollision() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasFunctionAlreadyExistsCollision.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasPropertyAlreadyExists.before.Main.kt")
|
||||
public void testImportAliasPropertyAlreadyExists() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasPropertyAlreadyExists.before.Main.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importInFirstPartInQualifiedExpression.before.Main.kt")
|
||||
public void testImportInFirstPartInQualifiedExpression() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importInFirstPartInQualifiedExpression.before.Main.kt");
|
||||
|
||||
@@ -1670,6 +1670,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
runTest("idea/testData/quickfix/autoImports/excludedFromImport.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("importAliasLetAlreadyExists.kt")
|
||||
public void testImportAliasLetAlreadyExists() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/importAliasLetAlreadyExists.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inPrimaryConstructor.kt")
|
||||
public void testInPrimaryConstructor() throws Exception {
|
||||
runTest("idea/testData/quickfix/autoImports/inPrimaryConstructor.kt");
|
||||
|
||||
Reference in New Issue
Block a user