diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionStatistician.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionStatistician.kt
deleted file mode 100644
index cb4438c92e8..00000000000
--- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionStatistician.kt
+++ /dev/null
@@ -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)
- }
- }
-}
\ No newline at end of file
diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt
new file mode 100644
index 00000000000..1b369d34848
--- /dev/null
+++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Statisticians.kt
@@ -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")
+ }
+}
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 8a9a1426bf8..101b768faad 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -320,8 +320,6 @@
-
-
@@ -330,6 +328,9 @@
+
+
+
) : 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 {
+ 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 {
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)
}
}
diff --git a/idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.after.kt b/idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.after.kt
similarity index 84%
rename from idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.after.kt
rename to idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.after.kt
index f6586d4bcd9..a23aba8fc78 100644
--- a/idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.after.kt
+++ b/idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.after.kt
@@ -3,7 +3,7 @@
import java.util.*
import dependency.*
-import dependency.Date
+import java.util.Date
fun foo(d: Date) {
}
diff --git a/idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.before.Dependency.kt b/idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.before.Dependency.kt
similarity index 100%
rename from idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.before.Dependency.kt
rename to idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.before.Dependency.kt
diff --git a/idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.before.Main.kt b/idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.before.Main.kt
similarity index 100%
rename from idea/testData/quickfix/autoImports/ambiguousNamePreferFromProject.before.Main.kt
rename to idea/testData/quickfix/autoImports/ambiguousNamePreferFromJdk.before.Main.kt
diff --git a/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt b/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt
deleted file mode 100644
index d085e1a51a4..00000000000
--- a/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-// "Import" "true"
-// ERROR: Please specify constructor invocation; classifier 'HTMLStyleElement' does not have a companion object
-
-package test
-
-fun foo() {
- HTMLStyleElement
-}
diff --git a/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt.after b/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt.after
deleted file mode 100644
index 165319aee97..00000000000
--- a/idea/testData/quickfix/autoImports/libraryClassJsRuntime.kt.after
+++ /dev/null
@@ -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
-}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java
index fecee50e22d..fc8542a1afd 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java
@@ -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);
}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
index 72f636dbf1d..e59f81e3eb8 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java
@@ -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");