Import all components and delegates accessors if possible

This commit is contained in:
Nikolay Krasko
2015-10-23 16:07:38 +03:00
parent 1517a099d0
commit 3c07bc3df7
10 changed files with 489 additions and 110 deletions
@@ -47,6 +47,8 @@ public fun FqName.tail(prefix: FqName): FqName {
}
}
public fun FqName.parentOrNull(): FqName? = if (this.isRoot) null else parent()
private enum class State {
BEGINNING,
MIDDLE,
@@ -17,7 +17,9 @@
package org.jetbrains.kotlin.idea.actions
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass
import com.intellij.codeInsight.daemon.impl.actions.AddImportAction
import com.intellij.codeInsight.hint.HintManager
import com.intellij.codeInsight.hint.QuestionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
@@ -27,6 +29,7 @@ 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.PsiElement
import com.intellij.psi.statistics.StatisticsManager
import com.intellij.psi.util.ProximityLocation
import com.intellij.psi.util.proximity.PsiProximityComparator
@@ -44,70 +47,94 @@ import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
fun createSingleImportAction(project: Project,
editor: Editor,
element: KtElement,
descriptors: Collection<DeclarationDescriptor>): KotlinAddImportAction {
val prioritizer = Prioritizer(element.getContainingJetFile())
val variants = descriptors
.groupBy { it.importableFqName!! }
.map {
val (fqName, sameFqNameDescriptors) = it
val priority = sameFqNameDescriptors.map { prioritizer.priority(it) }.min()!!
Prioritizer.VariantWithPriority(SingleImportVariant(fqName, sameFqNameDescriptors), priority)
}
.sortedBy { it.priority }
.map { it.variant }
return KotlinAddImportAction(project, editor, element, variants)
}
fun createGroupedImportsAction(project: Project,
editor: Editor,
element: KtElement,
autoImportDescription: String,
descriptors: Collection<DeclarationDescriptor>): KotlinAddImportAction {
val prioritizer = DescriptorGroupPrioritizer(element.getContainingJetFile())
val variants = descriptors
.groupBy { it.importableFqName!!.parentOrNull() ?: FqName.ROOT }
.map {
val samePackageDescriptors = it.value
val variant = if (samePackageDescriptors.size > 1) {
GroupedImportVariant(autoImportDescription, samePackageDescriptors)
}
else {
SingleImportVariant(samePackageDescriptors.first().importableFqName!!, samePackageDescriptors)
}
val priority = prioritizer.priority(samePackageDescriptors)
DescriptorGroupPrioritizer.VariantWithPriority(variant, priority)
}
.sortedBy {
it.priority
}
.map { it.variant }
return KotlinAddImportAction(project, editor, element, variants)
}
/**
* Automatically adds import directive to the file for resolving reference.
* Based on {@link AddImportAction}
*/
public class KotlinAddImportAction(
internal class KotlinAddImportAction(
private val project: Project,
private val editor: Editor,
private val element: KtExpression,
candidates: Collection<DeclarationDescriptor>
) : QuestionAction {
private val element: KtElement,
private val variants: List<AutoImportVariant>) : QuestionAction {
fun showHint(): Boolean {
if (variants.isEmpty()) return false
private val file = element.getContainingJetFile()
private val prioritizer = Prioritizer(file)
private inner class Variant(
val fqName: FqName,
val descriptors: Collection<DeclarationDescriptor>
) {
val priority = descriptors
.map { prioritizer.priority(fqName, it) }
.min()!!
val descriptorToImport: DeclarationDescriptor
get() {
return descriptors.singleOrNull()
?: descriptors.sortedBy { if (it is ClassDescriptor) 0 else 1 }.first()
}
val declarationToImport = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptorToImport)
}
private val variants = candidates
.groupBy { it.importableFqName!! }
.map { Variant(it.key, it.value) }
.sortedBy { it.priority }
public val highestPriorityFqName: FqName
get() = variants.first().fqName
override fun execute(): Boolean {
PsiDocumentManager.getInstance(project).commitAllDocuments()
if (!element.isValid()) return false
// TODO: Validate resolution variants. See AddImportAction.execute()
if (variants.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
addImport(variants.first())
}
else {
chooseCandidateAndImport()
}
val hintText = ShowAutoImportPass.getMessage(variants.size > 1, variants.first().hint)
HintManager.getInstance().showQuestionHint(editor, hintText, element.getTextOffset(), element.getTextRange()!!.getEndOffset(), this)
return true
}
private fun getImportSelectionPopup(): BaseListPopupStep<Variant> {
return object : BaseListPopupStep<Variant>(JetBundle.message("imports.chooser.title"), variants) {
override fun execute(): Boolean {
PsiDocumentManager.getInstance(project).commitAllDocuments()
if (!element.isValid) return false
if (variants.size == 1 || ApplicationManager.getApplication().isUnitTestMode) {
addImport(variants.first())
return true
}
JBPopupFactory.getInstance().createListPopup(getVariantSelectionPopup()).showInBestPositionFor(editor)
return true
}
private fun getVariantSelectionPopup(): BaseListPopupStep<AutoImportVariant> {
return object : BaseListPopupStep<AutoImportVariant>(JetBundle.message("imports.chooser.title"), variants) {
override fun isAutoSelectionEnabled() = false
override fun onChosen(selectedValue: Variant?, finalChoice: Boolean): PopupStep<String>? {
override fun onChosen(selectedValue: AutoImportVariant?, finalChoice: Boolean): PopupStep<String>? {
if (selectedValue == null || project.isDisposed) return null
if (finalChoice) {
@@ -115,7 +142,7 @@ public class KotlinAddImportAction(
return null
}
val toExclude = AddImportAction.getAllExcludableStrings(selectedValue.fqName.asString())
val toExclude = AddImportAction.getAllExcludableStrings(selectedValue.excludeFqNameCheck.asString())
return object : BaseListPopupStep<String>(null, toExclude) {
override fun getTextFor(value: String): String {
@@ -131,65 +158,116 @@ public class KotlinAddImportAction(
}
}
override fun hasSubstep(selectedValue: Variant?) = true
override fun getTextFor(value: Variant) = value.fqName.asString()
override fun getIconFor(value: Variant) = JetDescriptorIconProvider.getIcon(value.descriptorToImport, value.declarationToImport, 0)
override fun hasSubstep(selectedValue: AutoImportVariant?) = true
override fun getTextFor(value: AutoImportVariant) = value.hint
override fun getIconFor(value: AutoImportVariant) = value.icon(project)
}
}
private fun chooseCandidateAndImport() {
JBPopupFactory.getInstance().createListPopup(getImportSelectionPopup()).showInBestPositionFor(editor)
}
private fun addImport(selectedVariant: Variant) {
private fun addImport(variant: AutoImportVariant) {
PsiDocumentManager.getInstance(project).commitAllDocuments()
project.executeWriteCommand(QuickFixBundle.message("add.import")) {
if (!element.isValid()) return@executeWriteCommand
if (!element.isValid) return@executeWriteCommand
selectedVariant.declarationToImport?.let {
val location = ProximityLocation(file, ModuleUtilCore.findModuleForPsiElement(file))
val file = element.getContainingJetFile()
variant.declarationToImport(project)?.let {
val location = ProximityLocation(element, ModuleUtilCore.findModuleForPsiElement(element))
StatisticsManager.getInstance().incUseCount(PsiProximityComparator.STATISTICS_KEY, it, 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) {
if (element is KtSimpleNameExpression) {
element.mainReference.bindToFqName(descriptor.importableFqName!!, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING)
for (descriptor in variant.descriptorsToImport) {
// 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) {
if (element is KtSimpleNameExpression) {
element.mainReference.bindToFqName(descriptor.importableFqName!!, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING)
}
} else {
ImportInsertHelper.getInstance(project).importDescriptor(file, descriptor)
}
} else {
ImportInsertHelper.getInstance(project).importDescriptor(file, descriptor)
}
}
}
private class Prioritizer(private val file: KtFile) {
private val classifier = ImportableFqNameClassifier(file)
private val proximityComparator = PsiProximityComparator(file)
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)
override fun compareTo(other: Priority): Int {
if (isDeprecated != other.isDeprecated) {
return if (isDeprecated) +1 else -1
}
val c1 = classification.compareTo(other.classification)
if (c1 != 0) return c1
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(fqName, descriptor)
}
}
private class Prioritizer(private val file: KtFile, private val compareNames: Boolean = true) {
private val classifier = ImportableFqNameClassifier(file)
private val proximityComparator = PsiProximityComparator(file)
inner class Priority(private val descriptor: DeclarationDescriptor) : Comparable<Priority> {
private val isDeprecated = KotlinBuiltIns.isDeprecated(descriptor)
private val fqName = descriptor.importableFqName!!
private val classification = classifier.classify(fqName, false)
private val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(file.project, descriptor)
override fun compareTo(other: Priority): Int {
if (isDeprecated != other.isDeprecated) {
return if (isDeprecated) +1 else -1
}
val c1 = classification.compareTo(other.classification)
if (c1 != 0) return c1
val c2 = proximityComparator.compare(declaration, other.declaration)
if (c2 != 0) return c2
if (compareNames) {
return fqName.asString().compareTo(other.fqName.asString())
}
return 0
}
}
fun priority(descriptor: DeclarationDescriptor) = Priority(descriptor)
data class VariantWithPriority(val variant: AutoImportVariant, val priority: Priority)
}
private class DescriptorGroupPrioritizer(private val file: KtFile) {
private val prioritizer = Prioritizer(file, false)
inner class Priority(val descriptors: List<DeclarationDescriptor>) : Comparable<Priority> {
val ownDescriptorsPriority = descriptors.map { prioritizer.priority(it) }.max()!!
override fun compareTo(other: Priority): Int {
val c1 = ownDescriptorsPriority.compareTo(other.ownDescriptorsPriority)
if (c1 != 0) return c1
return other.descriptors.size - descriptors.size
}
}
fun priority(descriptors: List<DeclarationDescriptor>) = Priority(descriptors)
data class VariantWithPriority(val variant: AutoImportVariant, val priority: Priority)
}
internal interface AutoImportVariant {
val descriptorsToImport: Collection<DeclarationDescriptor>
val hint: String
val excludeFqNameCheck: FqName
fun icon(project: Project) = JetDescriptorIconProvider.getIcon(descriptorsToImport.first(), declarationToImport(project), 0)
fun declarationToImport(project: Project): PsiElement? =
DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptorsToImport.first())
}
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"
}
private class SingleImportVariant(
override val excludeFqNameCheck: FqName,
val descriptors: Collection<DeclarationDescriptor>
) : AutoImportVariant {
override val descriptorsToImport: Collection<DeclarationDescriptor> get() =
listOf(descriptors.singleOrNull() ?: descriptors.sortedBy { if (it is ClassDescriptor) 0 else 1 }.first())
override val hint: String get() = excludeFqNameCheck.asString()
}
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass
import com.intellij.codeInsight.hint.HintManager
import com.intellij.codeInsight.intention.HighPriorityAction
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInspection.HintAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.actions.KotlinAddImportAction
import org.jetbrains.kotlin.idea.actions.*
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope
@@ -80,12 +80,7 @@ abstract class AutoImportFixBase<T: KtExpression>(expression: T, val diagnostics
if (suggestionCount == 0) return false
val suggestions = computeSuggestions()
val action = KotlinAddImportAction(element.project, editor, element, suggestions)
val hintText = ShowAutoImportPass.getMessage(suggestions.size > 1, action.highestPriorityFqName.asString())
HintManager.getInstance().showQuestionHint(editor, hintText, element.textOffset, element.textRange.endOffset, action)
return true
return createAction(element.project, editor).showHint()
}
override fun getText() = JetBundle.message("import.fix")
@@ -97,8 +92,7 @@ abstract class AutoImportFixBase<T: KtExpression>(expression: T, val diagnostics
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
CommandProcessor.getInstance().runUndoTransparentAction {
val suggestions = computeSuggestions()
KotlinAddImportAction(project, editor!!, element, suggestions).execute()
createAction(project, editor!!).execute()
}
}
@@ -106,6 +100,10 @@ abstract class AutoImportFixBase<T: KtExpression>(expression: T, val diagnostics
private fun isOutdated() = modificationCountOnCreate != PsiModificationTracker.SERVICE.getInstance(element.getProject()).getModificationCount()
protected open fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
return createSingleImportAction(project, editor, element, computeSuggestions())
}
fun computeSuggestions(): Collection<DeclarationDescriptor> {
if (!element.isValid()) return listOf()
if (element.getContainingFile() !is KtFile) return emptyList()
@@ -291,12 +289,25 @@ class MissingDelegateAccessorsAutoImportFix(element: KtExpression, diagnostics:
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.DELEGATE(element)
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
if (diagnostics.size > 1) {
return createGroupedImportsAction(project, editor, element, "Delegate accessors", computeSuggestions())
}
return super.createAction(project, editor)
}
override fun getSupportedErrors() = ERRORS
companion object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtExpression>? {
assert(diagnostic.factory == Errors.DELEGATE_SPECIAL_FUNCTION_MISSING)
return MissingDelegateAccessorsAutoImportFix(diagnostic.psiElement as KtExpression, listOf(diagnostic))
return (diagnostic.psiElement as? KtExpression)?.let { MissingDelegateAccessorsAutoImportFix(it, listOf(diagnostic)) }
}
override fun doCreateActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> {
val element = sameTypeDiagnostics.first().psiElement
return (element as? KtExpression)?.let { MissingDelegateAccessorsAutoImportFix(it, sameTypeDiagnostics) }.singletonOrEmptyList()
}
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
@@ -309,12 +320,25 @@ class MissingComponentsAutoImportFix(element: KtExpression, diagnostics: Collect
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element)
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
if (diagnostics.size > 1) {
return createGroupedImportsAction(project, editor, element, "Component functions", computeSuggestions())
}
return super.createAction(project, editor)
}
override fun getSupportedErrors() = ERRORS
companion object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtExpression>? {
assert(diagnostic.factory == Errors.COMPONENT_FUNCTION_MISSING)
return MissingComponentsAutoImportFix(diagnostic.psiElement as KtExpression, listOf(diagnostic))
return (diagnostic.psiElement as? KtExpression)?.let { MissingComponentsAutoImportFix(it, listOf(diagnostic)) }
}
override fun doCreateActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> {
val element = sameTypeDiagnostics.first().psiElement
return (element as? KtExpression)?.let { MissingComponentsAutoImportFix(it, sameTypeDiagnostics) }.singletonOrEmptyList()
}
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
@@ -24,7 +24,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.actions.KotlinAddImportAction
import org.jetbrains.kotlin.idea.actions.createSingleImportAction
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.targetDescriptors
import org.jetbrains.kotlin.idea.imports.importableFqName
@@ -96,7 +96,7 @@ public class KotlinReferenceImporter : ReferenceImporter {
var result = false
CommandProcessor.getInstance().runUndoTransparentAction {
result = KotlinAddImportAction(project, editor, this, suggestions).execute()
result = createSingleImportAction(project, editor, this, suggestions).execute()
}
return result
}
@@ -0,0 +1,42 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Missing 'getValue(testing.BigTest, kotlin.reflect.KProperty<*>)' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
// ERROR: Missing 'setValue(testing.BigTest, kotlin.reflect.KProperty<*>, [ERROR : Type from delegate])' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
package testing
import some.DelegateImpl
class BigTest {
var a by <caret>DelegateImpl<Int>()
}
// FILE: second.kt
package some
class DelegateImpl<T> {
val value: T = null!!
}
public fun <T> DelegateImpl<T>.getValue(thisRef: Any?, property: PropertyMetadata): T = value
public fun <T> DelegateImpl<T>.setValue(thisRef: Any, propertyMetadata: PropertyMetadata, t: T) {}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Missing 'getValue(testing.BigTest, kotlin.reflect.KProperty<*>)' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
// ERROR: Missing 'setValue(testing.BigTest, kotlin.reflect.KProperty<*>, [ERROR : Type from delegate])' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
package testing
import some.DelegateImpl
import some.getValue
import some.setValue
class BigTest {
var a by <caret>DelegateImpl<Int>()
}
@@ -0,0 +1,44 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
// FILE: second.kt
// "Import" "true"
package some
public class Some
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
import some.component1
import some.component2
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
@@ -0,0 +1,53 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
// FILE: second.kt
package some
public class Some
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: second.kt
package other
import some.Some
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
import some.component1
import some.component2
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
@@ -0,0 +1,52 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
// FILE: second.kt
package some
public class Some
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: second.kt
package other
import some.Some
operator fun Some.component1() = 1
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
package testing
import some.Some
import some.component1
import some.component2
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
@@ -0,0 +1,54 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type aaa.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type aaa.Some must have a 'component2()' function
package testing
import aaa.Some
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
// FILE: second.kt
package aaa
public class Some
@Deprecated("Use componenents from other")
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: second.kt
package other
import aaa.Some
operator fun Some.component1() = 1
operator fun Some.component2() = 3
//-----------------------
// FILE: first.after.kt
// "Import" "true"
// ERROR: Multi-declaration initializer of type aaa.Some must have a 'component1()' function
// ERROR: Multi-declaration initializer of type aaa.Some must have a 'component2()' function
package testing
import aaa.Some
import other.component1
import other.component2
fun testing() {
val (a, b) = <caret>Some()
}
//-----------------------
@@ -83,6 +83,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
doTestWithExtraFile(fileName);
}
@TestMetadata("delegateExtensionBoth.test")
public void testDelegateExtensionBoth() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/delegateExtensionBoth.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("delegateExtensionGet.test")
public void testDelegateExtensionGet() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/delegateExtensionGet.test");
@@ -215,6 +221,30 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
doTestWithExtraFile(fileName);
}
@TestMetadata("multiDeclarationExtensionAllComponents.test")
public void testMultiDeclarationExtensionAllComponents() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionAllComponents.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("multiDeclarationExtensionAllComponentsMany.test")
public void testMultiDeclarationExtensionAllComponentsMany() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionAllComponentsMany.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("multiDeclarationExtensionAllComponentsPrefereFull.test")
public void testMultiDeclarationExtensionAllComponentsPrefereFull() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionAllComponentsPrefereFull.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("multiDeclarationExtensionAllComponentsPrefereNotDeprecated.test")
public void testMultiDeclarationExtensionAllComponentsPrefereNotDeprecated() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionAllComponentsPrefereNotDeprecated.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("multiDeclarationExtensionComponent1.test")
public void testMultiDeclarationExtensionComponent1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionComponent1.test");