KT-9950 IntelliJ IDEA does not suggest importing extension methods which have the same name as an instance method

#KT-9950 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-10-05 19:03:05 +03:00
parent 49ac6b99f6
commit 5734f2ba9b
21 changed files with 794 additions and 55 deletions
@@ -34,9 +34,20 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
@NotNull LexicalScope scope,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull KotlinType expectedType
) {
return newContext(trace, scope, dataFlowInfo, expectedType, ContextDependency.INDEPENDENT);
}
@NotNull
public static ExpressionTypingContext newContext(
@NotNull BindingTrace trace,
@NotNull LexicalScope scope,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull KotlinType expectedType,
@NotNull ContextDependency contextDependency
) {
return newContext(trace, scope, dataFlowInfo, expectedType,
ContextDependency.INDEPENDENT, new ResolutionResultsCacheImpl(),
contextDependency, new ResolutionResultsCacheImpl(),
StatementFilter.NONE, false);
}
@@ -30,8 +30,6 @@ import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
@@ -93,7 +91,7 @@ public class ExpressionTypingServices {
@NotNull BindingTrace trace,
boolean isStatement
) {
return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, isStatement, expression);
return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, isStatement, expression, ContextDependency.INDEPENDENT);
}
@NotNull
@@ -104,10 +102,11 @@ public class ExpressionTypingServices {
@NotNull DataFlowInfo dataFlowInfo,
@NotNull BindingTrace trace,
boolean isStatement,
@NotNull final KtExpression contextExpression
@NotNull final KtExpression contextExpression,
@NotNull ContextDependency contextDependency
) {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, scope, dataFlowInfo, expectedType
trace, scope, dataFlowInfo, expectedType, contextDependency
);
if (contextExpression != expression) {
context = context.replaceExpressionContextProvider(new Function1<KtExpression, KtExpression>() {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.KotlinType
@@ -36,11 +37,12 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
trace: BindingTrace = BindingTraceContext(),
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
isStatement: Boolean = false
isStatement: Boolean = false,
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
): KotlinTypeInfo {
PreliminaryDeclarationVisitor.createForExpression(this, trace)
return contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement, contextExpression)
.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement, contextExpression, contextDependency)
}
@JvmOverloads fun KtExpression.analyzeInContext(
@@ -49,9 +51,10 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
trace: BindingTrace = BindingTraceContext(),
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
isStatement: Boolean = false
isStatement: Boolean = false,
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
): BindingContext {
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement)
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement, contextDependency)
return trace.bindingContext
}
@@ -25,18 +25,23 @@ import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.packageDependencies.DependencyValidationManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.actions.KotlinAddImportAction
import org.jetbrains.kotlin.idea.actions.createGroupedImportsAction
import org.jetbrains.kotlin.idea.actions.createSingleImportAction
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope
@@ -46,12 +51,25 @@ import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiUtil.getConventionName
import org.jetbrains.kotlin.psi.KtPsiUtil.isSelectorInQualified
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
import org.jetbrains.kotlin.resolve.scopes.utils.addImportingScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.CachedValueProperty
@@ -123,22 +141,18 @@ internal abstract class ImportFixBase<T : KtExpression>(expression: T) :
}
}
private fun computeSuggestionsForName(name: Name, callTypeAndReceiver: CallTypeAndReceiver<*, *>):
Collection<DeclarationDescriptor> {
private fun computeSuggestionsForName(name: Name, callTypeAndReceiver: CallTypeAndReceiver<*, *>): Collection<DeclarationDescriptor> {
val nameStr = name.asString()
if (nameStr.isEmpty()) return emptyList()
val file = element.containingFile as KtFile
val file = element.getContainingKtFile()
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
if (!checkErrorStillPresent(bindingContext)) return emptyList()
val searchScope = getResolveScope(file)
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
val diagnostics = bindingContext.diagnostics.forElement(element)
if (!diagnostics.any { it.factory in getSupportedErrors() }) return emptyList()
val resolutionFacade = element.getResolutionFacade()
val resolutionFacade = file.getResolutionFacade()
fun isVisible(descriptor: DeclarationDescriptor): Boolean {
if (descriptor is DeclarationDescriptorWithVisibility) {
@@ -166,6 +180,14 @@ internal abstract class ImportFixBase<T : KtExpression>(expression: T) :
result
}
private fun checkErrorStillPresent(bindingContext: BindingContext): Boolean {
return elementsToCheckDiagnostics()
.flatMap { bindingContext.diagnostics.forElement(it) }
.any { diagnostic -> diagnostic.factory in getSupportedErrors() }
}
protected open fun elementsToCheckDiagnostics(): Collection<PsiElement> = listOf(element)
abstract fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
@@ -196,7 +218,7 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T) :
val expression = element
if (expression is KtSimpleNameExpression) {
if (!expression.isImportDirectiveExpression() && !KtPsiUtil.isSelectorInQualified(expression)) {
if (!expression.isImportDirectiveExpression() && !isSelectorInQualified(expression)) {
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
if (ProjectStructureUtil.isJsKotlinModule(expression.getContainingKtFile())) {
@@ -221,31 +243,7 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T) :
internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFixBase<KtSimpleNameExpression>(expression) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override val importNames: Collection<Name> = run {
if (element.getIdentifier() == null) {
val conventionName = KtPsiUtil.getConventionName(element)
if (conventionName != null) {
if (element is KtOperationReferenceExpression) {
val elementType = element.firstChild.node.elementType
if (elementType in OperatorConventions.ASSIGNMENT_OPERATIONS) {
val counterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[elementType]
val counterpartName = OperatorConventions.BINARY_OPERATION_NAMES[counterpart]
if (counterpartName != null) {
return@run listOf(conventionName, counterpartName)
}
}
}
return@run conventionName.singletonOrEmptyList()
}
}
else if (Name.isValidIdentifier(element.getReferencedName())) {
return@run Name.identifier(element.getReferencedName()).singletonOrEmptyList()
}
emptyList<Name>()
}
override val importNames = element.extractImportNames()
override fun getSupportedErrors() = ERRORS
@@ -259,6 +257,31 @@ internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFix
}
}
private fun KtSimpleNameExpression.extractImportNames(): Collection<Name> {
if (getIdentifier() == null) {
val conventionName = getConventionName(this)
if (conventionName != null) {
if (this is KtOperationReferenceExpression) {
val elementType = firstChild.node.elementType
if (elementType in OperatorConventions.ASSIGNMENT_OPERATIONS) {
val counterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[elementType]
val counterpartName = OperatorConventions.BINARY_OPERATION_NAMES[counterpart]
if (counterpartName != null) {
return listOf(conventionName, counterpartName)
}
}
}
return conventionName.singletonOrEmptyList()
}
}
else if (Name.isValidIdentifier(getReferencedName())) {
return Name.identifier(getReferencedName()).singletonOrEmptyList()
}
return emptyList()
}
internal class InvokeImportFix(expression: KtExpression) : OrdinaryImportFixBase<KtExpression>(expression) {
override val importNames = OperatorNameConventions.INVOKE.singletonList()
@@ -275,8 +298,12 @@ internal class InvokeImportFix(expression: KtExpression) : OrdinaryImportFixBase
}
}
internal open class ArrayAccessorImportFix(element: KtArrayAccessExpression, override val importNames: Collection<Name>, private val showHint: Boolean) :
OrdinaryImportFixBase<KtArrayAccessExpression>(element) {
internal open class ArrayAccessorImportFix(
element: KtArrayAccessExpression,
override val importNames: Collection<Name>,
private val showHint: Boolean
) : OrdinaryImportFixBase<KtArrayAccessExpression>(element) {
override fun getCallTypeAndReceiver() =
CallTypeAndReceiver.OPERATOR(element.arrayExpression!!)
@@ -310,8 +337,11 @@ internal open class ArrayAccessorImportFix(element: KtArrayAccessExpression, ove
}
internal class DelegateAccessorsImportFix(
element: KtExpression, override val importNames: Collection<Name>, private val solveSeveralProblems: Boolean) :
OrdinaryImportFixBase<KtExpression>(element) {
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
) : OrdinaryImportFixBase<KtExpression>(element) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.DELEGATE(element)
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
@@ -351,8 +381,12 @@ internal class DelegateAccessorsImportFix(
}
}
internal class ComponentsImportFix(element: KtExpression, override val importNames: Collection<Name>, private val solveSeveralProblems: Boolean) :
OrdinaryImportFixBase<KtExpression>(element) {
internal class ComponentsImportFix(
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
) : OrdinaryImportFixBase<KtExpression>(element) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element)
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
@@ -397,15 +431,14 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val result = ArrayList<DeclarationDescriptor>()
val expression = element
if (!expression.isImportDirectiveExpression() && !KtPsiUtil.isSelectorInQualified(expression)) {
if (!element.isImportDirectiveExpression() && !isSelectorInQualified(element)) {
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
indicesHelper.getKotlinCallablesByName(name)
.filter { it.canBeReferencedViaImport() && !isTopLevelDeclaration(it) }
.filterTo(result, filterByCallType)
if (!ProjectStructureUtil.isJsKotlinModule(expression.getContainingKtFile())) {
if (!ProjectStructureUtil.isJsKotlinModule(element.getContainingKtFile())) {
indicesHelper.getJvmCallablesByName(name)
.filter { it.canBeReferencedViaImport() }
.filterTo(result, filterByCallType)
@@ -436,7 +469,90 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
private val ERRORS: Collection<DiagnosticFactory<*>> by lazy { QuickFixes.getInstance().getDiagnostics(this) }
}
}
internal class ImportForMismatchingArgumentsFix(expression: KtSimpleNameExpression) : ImportFixBase<KtSimpleNameExpression>(expression) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override val importNames = element.extractImportNames()
override fun getSupportedErrors() = ERRORS
override fun elementsToCheckDiagnostics(): Collection<PsiElement> {
val callExpression = element.parent as? KtCallExpression ?: return emptyList()
return callExpression.valueArguments +
callExpression.valueArguments.mapNotNull { it.getArgumentExpression() } +
callExpression.valueArguments.mapNotNull { it.getArgumentName()?.referenceExpression } +
callExpression.valueArgumentList.singletonOrEmptyList()
}
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
if (!Name.isValidIdentifier(name)) return emptyList()
val identifier = Name.identifier(name)
val call = element.getParentCall(bindingContext) ?: return emptyList()
val callElement = call.callElement as? KtExpression ?: return emptyList()
if (callElement.anyDescendantOfType<PsiErrorElement>()) return emptyList() // incomplete call
val elementToAnalyze = callElement.getQualifiedExpressionForSelectorOrThis()
val file = element.getContainingKtFile()
val resolutionFacade = file.getResolutionFacade()
val resolutionScope = elementToAnalyze.getResolutionScope(bindingContext, resolutionFacade)
fun filterFunction(descriptor: FunctionDescriptor): Boolean {
if (!callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor)) return false
if (descriptor in resolutionScope.collectFunctions(identifier, NoLookupLocation.FROM_IDE)) return false // already imported
// check that this function matches all arguments
val resolutionScopeWithAddedImport = resolutionScope.addImportingScope(ExplicitImportsScope(listOf(descriptor)))
val dataFlowInfo = bindingContext.getDataFlowInfo(elementToAnalyze)
val newBindingContext = elementToAnalyze.analyzeInContext(
resolutionScopeWithAddedImport,
dataFlowInfo = dataFlowInfo,
contextDependency = ContextDependency.DEPENDENT // to not check complete inference
)
return newBindingContext.diagnostics.none { it.severity == Severity.ERROR }
}
val result = ArrayList<FunctionDescriptor>()
fun processDescriptor(descriptor: CallableDescriptor) {
if (descriptor is FunctionDescriptor && filterFunction(descriptor)) {
result.add(descriptor)
}
}
indicesHelper
.getCallableTopLevelExtensions(callTypeAndReceiver, element, bindingContext) { it == name }
.forEach(::processDescriptor)
if (!isSelectorInQualified(element)) {
indicesHelper
.getTopLevelCallablesByName(name)
.forEach(::processDescriptor)
}
return result
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): ImportForMismatchingArgumentsFix? {
//TODO: not only KtCallExpression
val callExpression = diagnostic.psiElement.getStrictParentOfType<KtCallExpression>() ?: return null
val nameExpression = callExpression.calleeExpression as? KtNameReferenceExpression ?: return null
return ImportForMismatchingArgumentsFix(nameExpression)
}
override fun isApplicableForCodeFragment() = true
private val ERRORS: Collection<DiagnosticFactory<*>> by lazy { QuickFixes.getInstance().getDiagnostics(this) }
}
}
object ImportForMissingOperatorFactory : KotlinSingleIntentionActionFactory() {
@@ -134,6 +134,12 @@ class QuickFixRegistrar : QuickFixContributor {
UNRESOLVED_REFERENCE.registerFactory(ImportMemberFix)
UNRESOLVED_REFERENCE.registerFactory(ImportFix)
TOO_MANY_ARGUMENTS.registerFactory(ImportForMismatchingArgumentsFix)
NO_VALUE_FOR_PARAMETER.registerFactory(ImportForMismatchingArgumentsFix)
TYPE_MISMATCH.registerFactory(ImportForMismatchingArgumentsFix)
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(ImportForMismatchingArgumentsFix)
NAMED_PARAMETER_NOT_FOUND.registerFactory(ImportForMismatchingArgumentsFix)
UNRESOLVED_REFERENCE.registerFactory(AddTestLibQuickFix)
UNRESOLVED_REFERENCE_WRONG_RECEIVER.registerFactory(ImportFix)
@@ -0,0 +1,26 @@
// FILE: first.before.kt
// "Import" "false"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
// ACTION: Add parameter to function 'foo'
// ACTION: Convert to expression body
// ACTION: Create extension function 'X.foo'
// ACTION: Create member function 'X.foo'
package main
class X {
fun foo() {
}
fun f() {
this.foo(<caret>1)
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: String) {
}
@@ -0,0 +1,40 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: The integer literal does not conform to the expected type String
package main
class X {
fun foo(p: String) {
}
fun f() {
foo(<caret>1)
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: The integer literal does not conform to the expected type String
package main
import other.foo
class X {
fun foo(p: String) {
}
fun f() {
foo(<caret>1)
}
}
@@ -0,0 +1,41 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: No value passed for parameter p
// ERROR: Type mismatch: inferred type is Unit but String was expected
package main
class X {
fun foo(p: Int) {
}
fun f(): String {
return foo(<caret>)
}
}
// FILE: second.kt
package other
import main.X
fun <T> X.foo(): T = TODO()
// FILE: first.after.kt
// "Import" "true"
// ERROR: No value passed for parameter p
// ERROR: Type mismatch: inferred type is Unit but String was expected
package main
import other.foo
class X {
fun foo(p: Int) {
}
fun f(): String {
return foo(<caret>)
}
}
@@ -0,0 +1,40 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
class X {
fun foo() {
}
}
fun f(x: X) {
x.foo(<caret>1)
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
import other.foo
class X {
fun foo() {
}
}
fun f(x: X) {
x.foo(<caret>1)
}
@@ -0,0 +1,40 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
class X {
fun foo() {
}
fun f() {
foo(<caret>1)
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
import other.foo
class X {
fun foo() {
}
fun f() {
foo(<caret>1)
}
}
@@ -0,0 +1,27 @@
// FILE: first.before.kt
// "Import" "false"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
// ACTION: Add parameter to function 'foo'
// ACTION: Convert to expression body
// ACTION: Create extension function 'X.foo'
// ACTION: Create member function 'X.foo'
package main
class X {
fun foo() {
}
}
fun f(x: X) {
x.foo(<caret>1)
}
// FILE: second.kt
package other
import main.X
fun String.foo(p: Int) {
}
@@ -0,0 +1,46 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
// ERROR: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: <br>public operator fun String?.plus(other: Any?): String defined in kotlin
// ERROR: Unresolved reference: XXX
// ERROR: Unresolved reference: xxx
package main
class X : XXX {
fun foo() {
}
fun f() {
foo(<caret>1) + xxx()
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
// ERROR: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: <br>public operator fun String?.plus(other: Any?): String defined in kotlin
// ERROR: Unresolved reference: XXX
// ERROR: Unresolved reference: xxx
package main
import other.foo
class X : XXX {
fun foo() {
}
fun f() {
foo(<caret>1) + xxx()
}
}
@@ -0,0 +1,39 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Type mismatch: inferred type is () -> Unit but Int was expected
package main
class X {
fun foo(p: Int) {
}
fun f() {
foo {<caret>}
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(filter: (String) -> Boolean){}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Type mismatch: inferred type is () -> Unit but Int was expected
package main
import other.foo
class X {
fun foo(p: Int) {
}
fun f() {
foo {<caret>}
}
}
@@ -0,0 +1,39 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Cannot find a parameter with this name: p2
package main
class X {
fun foo() {
}
fun f(p: Int) {
foo(<caret>p2 = 0)
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p1: Int = 1, p2: Int = 2, p3: Int = 3){}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Cannot find a parameter with this name: p2
package main
import other.foo
class X {
fun foo() {
}
fun f(p: Int) {
foo(<caret>p2 = 0)
}
}
@@ -0,0 +1,26 @@
// FILE: first.before.kt
// "Import" "false"
// ERROR: Type mismatch: inferred type is Int but String was expected
// ACTION: Add 'toString()' call
// ACTION: Change parameter 'p' type of function 'main.X.foo' to 'Int'
// ACTION: Convert to expression body
// ACTION: Create function 'foo'
package main
class X {
fun foo(p: String) {
}
fun f(p: Int) {
foo(<caret>p, )
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
@@ -0,0 +1,44 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
class X {
fun foo() {
}
fun f(p: Any) {
if (p is String) {
foo(<caret>p)
}
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: String) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
import other.foo
class X {
fun foo() {
}
fun f(p: Any) {
if (p is String) {
foo(<caret>p)
}
}
}
@@ -0,0 +1,38 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
class X {
fun foo() {
}
fun f() {
foo(<caret>1)
}
}
// FILE: second.kt
package other
fun foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
package main
import other.foo
class X {
fun foo() {
}
fun f() {
foo(<caret>1)
}
}
@@ -0,0 +1,24 @@
// FILE: first.before.kt
// "Import" "false"
// ERROR: Too many arguments for public final fun foo(): Unit defined in main.X
// ACTION: Add parameter to function 'foo'
// ACTION: Convert to expression body
// ACTION: Create extension function 'X.foo'
// ACTION: Create member function 'X.foo'
package main
class X {
fun foo() {
}
fun f() {
this.foo(<caret>1)
}
}
// FILE: second.kt
package other
fun foo(p: Int) {
}
@@ -0,0 +1,40 @@
// FILE: first.before.kt
// "Import" "true"
// ERROR: Type mismatch: inferred type is Int but String was expected
package main
class X {
fun foo(p: String) {
}
fun f(p: Int) {
foo(<caret>p)
}
}
// FILE: second.kt
package other
import main.X
fun X.foo(p: Int) {
}
// FILE: first.after.kt
// "Import" "true"
// ERROR: Type mismatch: inferred type is Int but String was expected
package main
import other.foo
class X {
fun foo(p: String) {
}
fun f(p: Int) {
foo(<caret>p)
}
}
@@ -580,6 +580,99 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/withSmartCastQualifier.before.Main.kt");
doTestWithExtraFile(fileName);
}
@TestMetadata("idea/testData/quickfix/autoImports/mismatchingArgs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MismatchingArgs extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInMismatchingArgs() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/autoImports/mismatchingArgs"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), true);
}
@TestMetadata("checkArgumentTypes.test")
public void testCheckArgumentTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/checkArgumentTypes.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("constantExpectedTypeMismatch.test")
public void testConstantExpectedTypeMismatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/constantExpectedTypeMismatch.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("expectedTypeRequired.test")
public void testExpectedTypeRequired() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/expectedTypeRequired.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("extensionExplicitReceiver.test")
public void testExtensionExplicitReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/extensionExplicitReceiver.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("extensionImplicitReceiver.test")
public void testExtensionImplicitReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/extensionImplicitReceiver.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("extensionWrongReceiver.test")
public void testExtensionWrongReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/extensionWrongReceiver.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("ignoreErrorsOutsideCall.test")
public void testIgnoreErrorsOutsideCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/ignoreErrorsOutsideCall.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("lambdaArgument.test")
public void testLambdaArgument() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/lambdaArgument.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("namedArgument.test")
public void testNamedArgument() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/namedArgument.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("notForIncompleteCall.test")
public void testNotForIncompleteCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/notForIncompleteCall.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("smartCast.test")
public void testSmartCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/smartCast.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("topLevelFun.test")
public void testTopLevelFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/topLevelFun.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("topLevelFun_notWithReceiver.test")
public void testTopLevelFun_notWithReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/topLevelFun_notWithReceiver.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("typeMismatch.test")
public void testTypeMismatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/mismatchingArgs/typeMismatch.test");
doTestWithExtraFile(fileName);
}
}
}
@TestMetadata("idea/testData/quickfix/changeSignature")
@@ -771,6 +771,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/unresolvedReferenceInCall.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/canBeParameter")