Better sorting of variants in add import popup
This commit is contained in:
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.completion
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionLocation
|
||||
import com.intellij.codeInsight.completion.CompletionStatistician
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.psi.statistics.StatisticsInfo
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
|
||||
public class KotlinCompletionStatistician : CompletionStatistician() {
|
||||
override fun serialize(element: LookupElement, location: CompletionLocation): StatisticsInfo? {
|
||||
val o = (element.`object` as? DeclarationLookupObject) ?: return null
|
||||
|
||||
if (o.descriptor != null) {
|
||||
val container = o.descriptor!!.containingDeclaration
|
||||
val containerFqName = when (container) {
|
||||
is ClassDescriptor -> container.importableFqName?.asString()
|
||||
is PackageFragmentDescriptor -> container.fqName.asString()
|
||||
is ModuleDescriptor -> ""
|
||||
else -> null
|
||||
} ?: return StatisticsInfo.EMPTY
|
||||
val signature = DescriptorRenderer.COMPACT.render(o.descriptor!!) //TODO: more compact presentation
|
||||
return StatisticsInfo(containerFqName, signature)
|
||||
}
|
||||
else {
|
||||
val fqName = o.importableFqName ?: return StatisticsInfo.EMPTY
|
||||
return StatisticsInfo(fqName.parent().asString(), fqName.shortName().identifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.completion
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionLocation
|
||||
import com.intellij.codeInsight.completion.CompletionStatistician
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.statistics.StatisticsInfo
|
||||
import com.intellij.psi.util.ProximityLocation
|
||||
import com.intellij.psi.util.proximity.ProximityStatistician
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
|
||||
class KotlinCompletionStatistician : CompletionStatistician() {
|
||||
override fun serialize(element: LookupElement, location: CompletionLocation): StatisticsInfo? {
|
||||
val o = (element.`object` as? DeclarationLookupObject) ?: return null
|
||||
|
||||
if (o.descriptor != null) {
|
||||
return KotlinStatisticsInfo.forDescriptor(o.descriptor!!)
|
||||
}
|
||||
else {
|
||||
val fqName = o.importableFqName ?: return StatisticsInfo.EMPTY
|
||||
return StatisticsInfo("", fqName.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinProximityStatistician : ProximityStatistician() {
|
||||
override fun serialize(element: PsiElement, location: ProximityLocation): StatisticsInfo? {
|
||||
if (element !is JetDeclaration) return null
|
||||
val descriptor = element.resolveToDescriptor()
|
||||
return KotlinStatisticsInfo.forDescriptor(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
object KotlinStatisticsInfo {
|
||||
fun forDescriptor(descriptor: DeclarationDescriptor): StatisticsInfo {
|
||||
val container = descriptor.containingDeclaration
|
||||
val containerFqName = when (container) {
|
||||
is ClassDescriptor -> container.importableFqName?.asString()
|
||||
is PackageFragmentDescriptor -> container.fqName.asString()
|
||||
is ModuleDescriptor -> ""
|
||||
else -> null
|
||||
} ?: return StatisticsInfo.EMPTY
|
||||
val signature = DescriptorRenderer.COMPACT.render(descriptor) //TODO: more compact presentation
|
||||
return StatisticsInfo("", "$containerFqName###$signature")
|
||||
}
|
||||
}
|
||||
@@ -320,8 +320,6 @@
|
||||
<completion.contributor language="jet"
|
||||
implementationClass="org.jetbrains.kotlin.idea.completion.KDocCompletionContributor"/>
|
||||
|
||||
<statistician key="completion" implementationClass="org.jetbrains.kotlin.idea.completion.KotlinCompletionStatistician"/>
|
||||
|
||||
<completion.confidence language="jet" implementationClass="com.intellij.codeInsight.completion.UnfocusedNameIdentifier"/>
|
||||
<completion.confidence language="jet"
|
||||
implementationClass="org.jetbrains.kotlin.idea.completion.confidence.UnfocusedPossibleFunctionParameter"/>
|
||||
@@ -330,6 +328,9 @@
|
||||
<lookup.charFilter implementation="org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter"/>
|
||||
<lookup.actionProvider implementation="org.jetbrains.kotlin.idea.completion.KotlinExcludeFromCompletionLookupActionProvider"/>
|
||||
|
||||
<statistician key="completion" implementationClass="org.jetbrains.kotlin.idea.completion.KotlinCompletionStatistician"/>
|
||||
<statistician key="proximity" implementationClass="org.jetbrains.kotlin.idea.completion.KotlinProximityStatistician"/>
|
||||
|
||||
<psi.referenceContributor language="jet" implementation="org.jetbrains.kotlin.idea.references.JetReferenceContributor"/>
|
||||
|
||||
<renamePsiElementProcessor id="KotlinClass"
|
||||
|
||||
@@ -27,6 +27,10 @@ import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.statistics.StatisticsManager
|
||||
import com.intellij.psi.util.ProximityLocation
|
||||
import com.intellij.psi.util.proximity.PsiProximityComparator
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
@@ -38,7 +42,6 @@ import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
@@ -56,7 +59,8 @@ public class KotlinAddImportAction(
|
||||
candidates: Collection<DeclarationDescriptor>
|
||||
) : QuestionAction {
|
||||
|
||||
private val prioritizer = Prioritizer(element.getContainingJetFile())
|
||||
private val file = element.getContainingJetFile()
|
||||
private val prioritizer = Prioritizer(file)
|
||||
|
||||
private inner class Variant(
|
||||
val fqName: FqName,
|
||||
@@ -145,7 +149,9 @@ public class KotlinAddImportAction(
|
||||
project.executeWriteCommand(QuickFixBundle.message("add.import")) {
|
||||
if (!element.isValid()) return@executeWriteCommand
|
||||
|
||||
val file = element.getContainingFile() as JetFile
|
||||
val location = ProximityLocation(file, ModuleUtilCore.findModuleForPsiElement(file))
|
||||
StatisticsManager.getInstance().incUseCount(PsiProximityComparator.STATISTICS_KEY, selectedVariant.declarationToImport, location)
|
||||
|
||||
val descriptor = selectedVariant.descriptorToImport
|
||||
// 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) {
|
||||
@@ -159,36 +165,28 @@ public class KotlinAddImportAction(
|
||||
|
||||
private class Prioritizer(private val file: JetFile) {
|
||||
private val classifier = ImportableFqNameClassifier(file)
|
||||
private val currentModule = ModuleUtilCore.findModuleForPsiElement(file)
|
||||
private val proximityComparator = PsiProximityComparator(file)
|
||||
|
||||
private enum class Location {
|
||||
currentModule,
|
||||
project,
|
||||
libraries,
|
||||
unknown
|
||||
}
|
||||
private inner class Priority(private val fqName: FqName, private val descriptor: DeclarationDescriptor) : Comparable<Priority> {
|
||||
private val isDeprecated = KotlinBuiltIns.isDeprecated(descriptor)
|
||||
private val classification = classifier.classify(fqName, false)
|
||||
private val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
|
||||
|
||||
private class Priority(private val priority1: ImportableFqNameClassifier.Classification, private val priority2: Location) : Comparable<Priority> {
|
||||
override fun compareTo(other: Priority): Int {
|
||||
val c1 = priority1.compareTo(other.priority1)
|
||||
if (isDeprecated != other.isDeprecated) {
|
||||
return if (isDeprecated) +1 else -1
|
||||
}
|
||||
|
||||
val c1 = classification.compareTo(other.classification)
|
||||
if (c1 != 0) return c1
|
||||
return priority2.compareTo(other.priority2)
|
||||
|
||||
val c2 = proximityComparator.compare(declaration, other.declaration)
|
||||
if (c2 != 0) return c2
|
||||
|
||||
return fqName.asString().compareTo(other.fqName.asString())
|
||||
}
|
||||
}
|
||||
|
||||
fun priority(fqName: FqName, descriptor: DeclarationDescriptor): Priority {
|
||||
val classification = classifier.classify(fqName, false)
|
||||
val location = location(descriptor)
|
||||
return Priority(classification, location)
|
||||
}
|
||||
|
||||
private fun location(descriptor: DeclarationDescriptor): Location {
|
||||
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor) ?: return Location.unknown
|
||||
return when {
|
||||
ModuleUtilCore.findModuleForPsiElement(declaration) == currentModule -> Location.currentModule
|
||||
ProjectRootsUtil.isInProjectSource(declaration) -> Location.project
|
||||
else -> Location.libraries
|
||||
}
|
||||
}
|
||||
fun priority(fqName: FqName, descriptor: DeclarationDescriptor) = Priority(fqName, descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
import java.util.*
|
||||
import dependency.*
|
||||
import dependency.Date
|
||||
import java.util.Date
|
||||
|
||||
fun foo(d: Date<caret>) {
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Please specify constructor invocation; classifier 'HTMLStyleElement' does not have a companion object
|
||||
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
<caret>HTMLStyleElement
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// "Import" "true"
|
||||
// ERROR: Please specify constructor invocation; classifier 'HTMLStyleElement' does not have a companion object
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.js.dom.html.HTMLStyleElement
|
||||
|
||||
fun foo() {
|
||||
HTMLStyleElement
|
||||
}
|
||||
@@ -53,9 +53,9 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/autoImports"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("ambiguousNamePreferFromProject.before.Main.kt")
|
||||
public void testAmbiguousNamePreferFromProject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.before.Main.kt");
|
||||
@TestMetadata("ambiguousNamePreferFromJdk.before.Main.kt")
|
||||
public void testAmbiguousNamePreferFromJdk() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
|
||||
@@ -361,12 +361,6 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("libraryClassJsRuntime.kt")
|
||||
public void testLibraryClassJsRuntime() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("libraryPropertyJsRuntime.kt")
|
||||
public void testLibraryPropertyJsRuntime() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/libraryPropertyJsRuntime.kt");
|
||||
|
||||
Reference in New Issue
Block a user