Fix priority for "add import" action wrt DeprecatedSinceKotlin

This commit is contained in:
Mikhail Zarechenskiy
2020-06-25 11:05:56 +03:00
parent beca7fca30
commit 6efa7a51c6
5 changed files with 129 additions and 11 deletions
@@ -67,7 +67,7 @@ abstract class DeclarationLookupObjectImpl(
}
// This function is kind of a hack to avoid using DeprecationResolver as it's hard to preserve same resolutionFacade for descriptor
private fun isDeprecatedAtCallSite(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings?): Boolean {
fun isDeprecatedAtCallSite(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings?): Boolean {
val isDeprecatedAtDeclarationSite = KotlinBuiltIns.isDeprecated(descriptor)
if (languageVersionSettings == null) return isDeprecatedAtDeclarationSite
@@ -33,7 +33,7 @@ import com.intellij.psi.statistics.StatisticsManager
import com.intellij.psi.util.proximity.PsiProximityComparator
import com.intellij.ui.popup.list.ListPopupImpl
import com.intellij.ui.popup.list.PopupListElementRenderer
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
@@ -42,8 +42,10 @@ import org.jetbrains.kotlin.idea.KotlinDescriptorIconProvider
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.completion.KotlinStatisticsInfo
import org.jetbrains.kotlin.idea.completion.isDeprecatedAtCallSite
import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
@@ -69,7 +71,7 @@ internal fun createSingleImportAction(
val prioritizer = Prioritizer(element.containingKtFile)
val variants = fqNames.mapNotNull { fqName ->
val sameFqNameDescriptors = file.resolveImportReference(fqName)
val priority = sameFqNameDescriptors.map { prioritizer.priority(it) }.min() ?: return@mapNotNull null
val priority = sameFqNameDescriptors.map { prioritizer.priority(it, file.languageVersionSettings) }.min() ?: return@mapNotNull null
Prioritizer.VariantWithPriority(SingleImportVariant(fqName, sameFqNameDescriptors), priority)
}.sortedBy { it.priority }.map { it.variant }
@@ -89,7 +91,8 @@ internal fun createSingleImportActionForConstructor(
.filterIsInstance<ClassDescriptor>()
.flatMap { it.constructors }
val priority = sameFqNameDescriptors.asSequence().map { prioritizer.priority(it) }.min() ?: return@mapNotNull null
val priority =
sameFqNameDescriptors.asSequence().map { prioritizer.priority(it, file.languageVersionSettings) }.min() ?: return@mapNotNull null
Prioritizer.VariantWithPriority(SingleImportVariant(fqName, sameFqNameDescriptors), priority)
}.sortedBy { it.priority }.map { it.variant }
return KotlinAddImportAction(project, editor, element, variants)
@@ -116,7 +119,7 @@ internal fun createGroupedImportsAction(
SingleImportVariant(samePackageFqNames.first(), descriptors)
}
val priority = prioritizer.priority(descriptors)
val priority = prioritizer.priority(descriptors, file.languageVersionSettings)
DescriptorGroupPrioritizer.VariantWithPriority(variant, priority)
}
.sortedBy {
@@ -272,8 +275,8 @@ private class Prioritizer(private val file: KtFile, private val compareNames: Bo
private val classifier = ImportableFqNameClassifier(file)
private val proximityComparator = PsiProximityComparator(file)
inner class Priority(descriptor: DeclarationDescriptor) : Comparable<Priority> {
private val isDeprecated = KotlinBuiltIns.isDeprecated(descriptor)
inner class Priority(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings) : Comparable<Priority> {
private val isDeprecated = isDeprecatedAtCallSite(descriptor, languageVersionSettings)
private val fqName = descriptor.importableFqName!!
private val classification = classifier.classify(fqName, false)
private val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
@@ -297,7 +300,8 @@ private class Prioritizer(private val file: KtFile, private val compareNames: Bo
}
}
fun priority(descriptor: DeclarationDescriptor) = Priority(descriptor)
fun priority(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings) =
Priority(descriptor, languageVersionSettings)
data class VariantWithPriority(val variant: AutoImportVariant, val priority: Priority)
}
@@ -305,8 +309,11 @@ private class Prioritizer(private val file: KtFile, private val compareNames: Bo
private class DescriptorGroupPrioritizer(file: KtFile) {
private val prioritizer = Prioritizer(file, false)
inner class Priority(val descriptors: List<DeclarationDescriptor>) : Comparable<Priority> {
val ownDescriptorsPriority = descriptors.asSequence().map { prioritizer.priority(it) }.max()!!
inner class Priority(
val descriptors: List<DeclarationDescriptor>,
languageVersionSettings: LanguageVersionSettings
) : Comparable<Priority> {
val ownDescriptorsPriority = descriptors.asSequence().map { prioritizer.priority(it, languageVersionSettings) }.max()!!
override fun compareTo(other: Priority): Int {
val c1 = ownDescriptorsPriority.compareTo(other.ownDescriptorsPriority)
@@ -316,7 +323,8 @@ private class DescriptorGroupPrioritizer(file: KtFile) {
}
}
fun priority(descriptors: List<DeclarationDescriptor>) = Priority(descriptors)
fun priority(descriptors: List<DeclarationDescriptor>, languageVersionSettings: LanguageVersionSettings) =
Priority(descriptors, languageVersionSettings)
data class VariantWithPriority(val variant: AutoImportVariant, val priority: Priority)
}
@@ -0,0 +1,50 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Destructuring declaration initializer of type Some must have a 'component1()' function
package testing
import aaa.Some
fun testing() {
val (a) = <caret>Some()
}
//-----------------------
// FILE: second.kt
package aaa
public class Some
@Deprecated("Bad, use from package other")
@DeprecatedSinceKotlin(warningSince = "1.0")
operator fun Some.component1() = 1
//-----------------------
// FILE: other_second.kt
package other
import aaa.Some
operator fun Some.component1() = 1
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Destructuring declaration initializer of type Some must have a 'component1()' function
package testing
import aaa.Some
import other.component1
fun testing() {
val (a) = <caret>Some()
}
//-----------------------
@@ -0,0 +1,50 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Destructuring declaration initializer of type Some must have a 'component1()' function
package testing
import aaa.Some
fun testing() {
val (a) = <caret>Some()
}
//-----------------------
// FILE: second.kt
package aaa
public class Some
@Deprecated("Good")
@DeprecatedSinceKotlin(warningSince = "999.999")
operator fun Some.component1() = 1
//-----------------------
// FILE: other_second.kt
package other
import aaa.Some
operator fun Some.component1() = 1
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Destructuring declaration initializer of type Some must have a 'component1()' function
package testing
import aaa.Some
import aaa.component1
fun testing() {
val (a) = <caret>Some()
}
//-----------------------
@@ -641,6 +641,16 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
runTest("idea/testData/quickfix/autoImports/extensionFunctionImportImplicitReceiver.before.Main.kt");
}
@TestMetadata("extensionPreferDeprecatedSinceApplicable.test")
public void testExtensionPreferDeprecatedSinceApplicable() throws Exception {
runTest("idea/testData/quickfix/autoImports/extensionPreferDeprecatedSinceApplicable.test");
}
@TestMetadata("extensionPreferDeprecatedSinceNotApplicable.test")
public void testExtensionPreferDeprecatedSinceNotApplicable() throws Exception {
runTest("idea/testData/quickfix/autoImports/extensionPreferDeprecatedSinceNotApplicable.test");
}
@TestMetadata("extensionPropertyImport.before.Main.kt")
public void testExtensionPropertyImport() throws Exception {
runTest("idea/testData/quickfix/autoImports/extensionPropertyImport.before.Main.kt");