Auto-imports for index functions, += like operators, invoke, delegates and components
#KT-9482 Fixed #KT-9397 Fixed #KT-8060 Fixed
This commit is contained in:
committed by
Nikolay Krasko
parent
0f85d770dd
commit
2f26480e6b
@@ -53,6 +53,8 @@ public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: D
|
||||
|
||||
object TYPE : CallType<KtExpression?>(DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK))
|
||||
|
||||
object DELEGATE : CallType<KtExpression?>(DescriptorKindFilter.FUNCTIONS)
|
||||
|
||||
object ANNOTATION : CallType<KtExpression?>(DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK) exclude NonAnnotationClassifierExclude)
|
||||
|
||||
private object NonInfixExclude : DescriptorKindExclude() {
|
||||
@@ -103,6 +105,7 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
||||
class IMPORT_DIRECTIVE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.IMPORT_DIRECTIVE>(CallType.IMPORT_DIRECTIVE, receiver)
|
||||
class PACKAGE_DIRECTIVE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.PACKAGE_DIRECTIVE>(CallType.PACKAGE_DIRECTIVE, receiver)
|
||||
class TYPE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.TYPE>(CallType.TYPE, receiver)
|
||||
class DELEGATE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.DELEGATE>(CallType.DELEGATE, receiver)
|
||||
class ANNOTATION(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.ANNOTATION>(CallType.ANNOTATION, receiver)
|
||||
|
||||
companion object {
|
||||
@@ -193,10 +196,12 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
|
||||
|
||||
is CallTypeAndReceiver.DOT -> receiverExpression = receiver
|
||||
is CallTypeAndReceiver.SAFE -> receiverExpression = receiver
|
||||
is CallTypeAndReceiver.INFIX -> receiverExpression = receiver
|
||||
is CallTypeAndReceiver.OPERATOR -> receiverExpression = receiver
|
||||
is CallTypeAndReceiver.DELEGATE -> receiverExpression = receiver
|
||||
|
||||
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
|
||||
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
||||
|
||||
@@ -44,6 +44,7 @@ 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.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
@@ -54,7 +55,7 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
public class KotlinAddImportAction(
|
||||
private val project: Project,
|
||||
private val editor: Editor,
|
||||
private val element: KtSimpleNameExpression,
|
||||
private val element: KtExpression,
|
||||
candidates: Collection<DeclarationDescriptor>
|
||||
) : QuestionAction {
|
||||
|
||||
@@ -156,9 +157,10 @@ public class KotlinAddImportAction(
|
||||
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) {
|
||||
element.mainReference.bindToFqName(descriptor.importableFqName!!, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING)
|
||||
}
|
||||
else {
|
||||
if (element is KtSimpleNameExpression) {
|
||||
element.mainReference.bindToFqName(descriptor.importableFqName!!, KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING)
|
||||
}
|
||||
} else {
|
||||
ImportInsertHelper.getInstance(project).importDescriptor(file, descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import org.jetbrains.kotlin.idea.actions.KotlinAddImportAction
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -42,16 +44,19 @@ import org.jetbrains.kotlin.idea.core.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.core.isVisible
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.CachedValueProperty
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Check possibility and perform fix for unresolved references.
|
||||
*/
|
||||
public abstract class AutoImportFixBase(
|
||||
abstract class AutoImportFixBase public constructor(
|
||||
expression: KtExpression,
|
||||
val diagnostics: Collection<Diagnostic> = emptyList()) : KotlinQuickFixAction<KtExpression>(expression), HighPriorityAction, HintAction {
|
||||
|
||||
@@ -189,8 +194,8 @@ public abstract class AutoImportFixBase(
|
||||
}
|
||||
}
|
||||
|
||||
public class AutoImportFix(expression: KtSimpleNameExpression, diagnostic: Diagnostic? = null) : AutoImportFixBase(expression, diagnostic) {
|
||||
override fun getTypeAndReceiver(): CallTypeAndReceiver<*, *> = CallTypeAndReceiver.detect(element as KtSimpleNameExpression)
|
||||
class AutoImportFix(expression: KtSimpleNameExpression, diagnostic: Diagnostic? = null) : AutoImportFixBase(expression, diagnostic) {
|
||||
override fun getTypeAndReceiver(): CallTypeAndReceiver<*, *> = CallTypeAndReceiver.detect(element as JetSimpleNameExpression)
|
||||
override fun getImportNames(diagnostics: Collection<Diagnostic>, element: KtExpression): Collection<String> {
|
||||
element as KtSimpleNameExpression
|
||||
|
||||
@@ -198,7 +203,14 @@ public class AutoImportFix(expression: KtSimpleNameExpression, diagnostic: Diagn
|
||||
val conventionName = KtPsiUtil.getConventionName(element)
|
||||
if (conventionName != null) {
|
||||
if (element is KtOperationReferenceExpression) {
|
||||
return listOf(conventionName.asString())
|
||||
val elementType = element.firstChild.node.elementType
|
||||
if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(elementType)) {
|
||||
val conterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(elementType)
|
||||
val counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(conterpart)
|
||||
if (counterpartName != null) {
|
||||
return listOf(conventionName.asString(), counterpartName.asString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return listOf(conventionName.asString())
|
||||
@@ -228,4 +240,99 @@ public class AutoImportFix(expression: KtSimpleNameExpression, diagnostic: Diagn
|
||||
|
||||
private val ERRORS: Collection<DiagnosticFactory<*>> by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
|
||||
}
|
||||
}
|
||||
|
||||
class MissingInvokeAutoImportFix(expression: KtExpression, diagnostic: Diagnostic) : AutoImportFixBase(expression, diagnostic) {
|
||||
override fun getImportNames(diagnostics: Collection<Diagnostic>, element: KtExpression) = setOf("invoke")
|
||||
|
||||
override fun getTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element as KtExpression)
|
||||
|
||||
override fun getSupportedErrors() = ERRORS
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtExpression>? {
|
||||
val element = diagnostic.psiElement
|
||||
if (element is KtExpression) {
|
||||
return MissingInvokeAutoImportFix(element, diagnostic)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
|
||||
}
|
||||
}
|
||||
|
||||
class MissingArrayAccessorAutoImportFix(element: KtArrayAccessExpression, diagnostic: Diagnostic) : AutoImportFixBase(element, diagnostic) {
|
||||
override fun getImportNames(diagnostics: Collection<Diagnostic>, element: KtExpression): Set<String> {
|
||||
val s = if ((element.parent as? KtBinaryExpression)?.operationToken == KtTokens.EQ) "set" else "get"
|
||||
return setOf(s)
|
||||
}
|
||||
|
||||
override fun getTypeAndReceiver() =
|
||||
CallTypeAndReceiver.OPERATOR((element as KtArrayAccessExpression).arrayExpression!!)
|
||||
|
||||
override fun getSupportedErrors() = ERRORS
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<KtExpression>? {
|
||||
val element = diagnostic.psiElement
|
||||
if (element is KtArrayAccessExpression && element.arrayExpression != null) {
|
||||
return MissingArrayAccessorAutoImportFix(element, diagnostic)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
|
||||
}
|
||||
}
|
||||
|
||||
class MissingDelegateAccessorsAutoImportFix(element: KtExpression, diagnostics: Collection<Diagnostic>) : AutoImportFixBase(element, diagnostics) {
|
||||
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
|
||||
return KotlinAddImportAction(project, editor, element, suggestions)
|
||||
}
|
||||
|
||||
override fun getImportNames(diagnostics: Collection<Diagnostic>, element: KtExpression): Set<String> {
|
||||
return diagnostics.mapTo(LinkedHashSet()) { if (it.toString().contains("setValue")) "setValue" else "getValue" }
|
||||
}
|
||||
|
||||
override fun getTypeAndReceiver() = CallTypeAndReceiver.DELEGATE(element as KtExpression)
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
|
||||
}
|
||||
}
|
||||
|
||||
class MissingComponentsAutoImportFix(element: KtExpression, diagnostics: Collection<Diagnostic>) : AutoImportFixBase(element, diagnostics) {
|
||||
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
|
||||
return KotlinAddImportAction(project, editor, element, suggestions)
|
||||
}
|
||||
|
||||
override fun getImportNames(diagnostics: Collection<Diagnostic>, element: KtExpression): List<String> {
|
||||
return diagnostics.map {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(it as DiagnosticWithParameters2<*, Name, *>).a.identifier
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element as KtExpression)
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
private val ERRORS by lazy(LazyThreadSafetyMode.PUBLICATION) { QuickFixes.getInstance().getDiagnostics(this) }
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,14 @@ public class QuickFixRegistrar : QuickFixContributor {
|
||||
UNRESOLVED_REFERENCE.registerFactory(AutoImportFix)
|
||||
UNRESOLVED_REFERENCE_WRONG_RECEIVER.registerFactory(AutoImportFix)
|
||||
|
||||
FUNCTION_EXPECTED.registerFactory(MissingInvokeAutoImportFix)
|
||||
|
||||
DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(MissingDelegateAccessorsAutoImportFix)
|
||||
COMPONENT_FUNCTION_MISSING.registerFactory(MissingComponentsAutoImportFix)
|
||||
|
||||
NO_GET_METHOD.registerFactory(MissingArrayAccessorAutoImportFix)
|
||||
NO_SET_METHOD.registerFactory(MissingArrayAccessorAutoImportFix)
|
||||
|
||||
val removeImportFixFactory = RemovePsiElementSimpleFix.createRemoveImportFactory()
|
||||
CONFLICTING_IMPORT.registerFactory(removeImportFixFactory)
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Missing 'getValue(testing.BigTest, kotlin.PropertyMetadata)' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
|
||||
|
||||
package testing
|
||||
|
||||
import some.DelegateImpl
|
||||
|
||||
class BigTest {
|
||||
val 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
|
||||
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Missing 'getValue(testing.BigTest, kotlin.PropertyMetadata)' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
|
||||
|
||||
package testing
|
||||
|
||||
import some.DelegateImpl
|
||||
import some.getValue
|
||||
|
||||
class BigTest {
|
||||
val a by <caret>DelegateImpl<Int>()
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Missing 'setValue(testing.BigTest, kotlin.PropertyMetadata, kotlin.Int)' method on delegate of type 'some.DelegateImpl<kotlin.Int>'
|
||||
|
||||
package testing
|
||||
|
||||
import some.DelegateImpl
|
||||
import some.getValue
|
||||
|
||||
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 'setValue(testing.BigTest, kotlin.PropertyMetadata, kotlin.Int)' 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: Unresolved reference: foo()["str"]
|
||||
// ERROR: No get method providing array access
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.get(s: String) {}
|
||||
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: foo()["str"]
|
||||
// ERROR: No get method providing array access
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.get
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "false"
|
||||
// ERROR: Unresolved reference: foo()["str"]
|
||||
// ERROR: No get method providing array access
|
||||
// ACTION: Create extension function 'get'
|
||||
// ACTION: Create member function 'get'
|
||||
// ACTION: Replace overloaded operator with function call
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
fun Some.get(s: String) {}
|
||||
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: foo()["str"]
|
||||
// ERROR: No get method providing array access
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.get
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: foo()["other"]
|
||||
// ERROR: No set method providing array access
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["other"] = 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.set(s: String) {}
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Unresolved reference: foo()["other"]
|
||||
// ERROR: No set method providing array access
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.set
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["other"] = 1
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "false"
|
||||
// ERROR: Unresolved reference: foo()["str"]
|
||||
// ERROR: No set method providing array access
|
||||
// ACTION: Create extension function 'set'
|
||||
// ACTION: Create member function 'set'
|
||||
// ACTION: Replace overloaded operator with function call
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"] = 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.get(s: String) {}
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// Empty File
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "false"
|
||||
// ERROR: Unresolved reference: foo()["str"]
|
||||
// ERROR: No get method providing array access
|
||||
// ACTION: Create extension function 'get'
|
||||
// ACTION: Create member function 'get'
|
||||
// ACTION: Replace overloaded operator with function call
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun foo(): Some = Some()
|
||||
|
||||
fun testing() {
|
||||
foo()<caret>["str"]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.set(s: String) {}
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// Empty File
|
||||
@@ -0,0 +1,41 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun testing() {
|
||||
<caret>Some()("str")
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.invoke(s: String) {}
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.invoke
|
||||
|
||||
fun testing() {
|
||||
<caret>Some()("str")
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "false"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
// ACTION: Create extension function 'invoke'
|
||||
// ACTION: Create member function 'invoke'
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun testing() {
|
||||
<caret>Some()("str")
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
fun Some.invoke(s: String) {}
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Expression 'Some()' of type 'some.Some' cannot be invoked as a function. The function invoke() is not found
|
||||
// ACTION: Create extension function 'invoke'
|
||||
// ACTION: Create member function 'invoke'
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.invoke
|
||||
|
||||
fun testing() {
|
||||
<caret>Some()("str")
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.component2
|
||||
|
||||
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: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.component1
|
||||
import some.component2
|
||||
|
||||
fun testing() {
|
||||
val (a, b) = <caret>Some()
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: Multi-declaration initializer of type some.Some must have a 'component2()' function
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.component1
|
||||
|
||||
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: first.after.kt
|
||||
// "Import" "true"
|
||||
// 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()
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "false"
|
||||
// ERROR: Multi-declaration initializer of type some.Some must have a 'component1()' function
|
||||
// ACTION: Create extension function 'component1'
|
||||
// ACTION: Create member function 'component1'
|
||||
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.component2
|
||||
|
||||
fun testing() {
|
||||
val (a, b) = <caret>Some()
|
||||
}
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
fun Some.component1() = 1
|
||||
operator fun Some.component2() = 3
|
||||
//-----------------------
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// -- Empty file --
|
||||
@@ -0,0 +1,39 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.plus(i: Int) : Some = this
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.plus
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.plusAssign(i: Int) {}
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.plusAssign
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// FILE: first.before.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: second.kt
|
||||
package some
|
||||
|
||||
public class Some
|
||||
|
||||
operator fun Some.plusAssign(i: Int) {}
|
||||
|
||||
// FILE: second.kt
|
||||
// Lexicography is before "some"
|
||||
package aaa
|
||||
|
||||
import some.Some
|
||||
|
||||
operator fun Some.plus(i: Int) : Some = this
|
||||
|
||||
|
||||
// FILE: first.after.kt
|
||||
// "Import" "true"
|
||||
// ERROR: <html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul><li><b>public</b> operator <b>fun</b> kotlin.String?.plus(other: kotlin.Any?): kotlin.String <i>defined in</i> kotlin</li></ul></html>
|
||||
|
||||
package testing
|
||||
|
||||
import some.Some
|
||||
import some.plusAssign
|
||||
|
||||
fun testing() {
|
||||
var s = Some()
|
||||
s <caret>+= 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,6 +83,18 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegateExtensionGet.test")
|
||||
public void testDelegateExtensionGet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/delegateExtensionGet.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegateExtensionSet.test")
|
||||
public void testDelegateExtensionSet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/delegateExtensionSet.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("divOperator.before.Main.kt")
|
||||
public void testDivOperator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/divOperator.before.Main.kt");
|
||||
@@ -143,6 +155,36 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("indexCallExtensionGet.test")
|
||||
public void testIndexCallExtensionGet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/indexCallExtensionGet.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("indexCallExtensionGetNoOperator.test")
|
||||
public void testIndexCallExtensionGetNoOperator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/indexCallExtensionGetNoOperator.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("indexCallExtensionSet.test")
|
||||
public void testIndexCallExtensionSet() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/indexCallExtensionSet.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("indexCallNoImportWhenGetNeededButSetAvailable.test")
|
||||
public void testIndexCallNoImportWhenGetNeededButSetAvailable() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/indexCallNoImportWhenGetNeededButSetAvailable.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("indexCallNoImportWhenSetNeededButGetAvailable.test")
|
||||
public void testIndexCallNoImportWhenSetNeededButGetAvailable() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/indexCallNoImportWhenSetNeededButGetAvailable.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("infixCall.before.Main.kt")
|
||||
public void testInfixCall() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/infixCall.before.Main.kt");
|
||||
@@ -155,12 +197,42 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("invokeExtension.test")
|
||||
public void testInvokeExtension() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/invokeExtension.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("invokeExtensionNoOperator.test")
|
||||
public void testInvokeExtensionNoOperator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/invokeExtensionNoOperator.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("minusOperator.before.Main.kt")
|
||||
public void testMinusOperator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/minusOperator.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multiDeclarationExtensionComponent1.test")
|
||||
public void testMultiDeclarationExtensionComponent1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionComponent1.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multiDeclarationExtensionComponent2.test")
|
||||
public void testMultiDeclarationExtensionComponent2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionComponent2.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multiDeclarationExtensionComponentNoOperator.test")
|
||||
public void testMultiDeclarationExtensionComponentNoOperator() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/multiDeclarationExtensionComponentNoOperator.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClass.before.Main.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/nestedClass.before.Main.kt");
|
||||
@@ -239,6 +311,24 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("operatorAssignPlus.test")
|
||||
public void testOperatorAssignPlus() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/operatorAssignPlus.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("operatorAssignPlusAssign.test")
|
||||
public void testOperatorAssignPlusAssign() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/operatorAssignPlusAssign.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("operatorAssignPlusTwoVariantsDifferentPackages.test")
|
||||
public void testOperatorAssignPlusTwoVariantsDifferentPackages() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/operatorAssignPlusTwoVariantsDifferentPackages.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("packageClass.before.Main.kt")
|
||||
public void testPackageClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/packageClass.before.Main.kt");
|
||||
|
||||
Reference in New Issue
Block a user