Smart completion to work when some of previous arguments have errors (+ fixed testAfterEmptyArgument broken by previous changes)
This commit is contained in:
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
|||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunctionDescriptor
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.noErrorsInValueArguments
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||||
@@ -250,7 +249,7 @@ class ExpectedInfos(
|
|||||||
if (status == ResolutionStatus.RECEIVER_TYPE_ERROR || status == ResolutionStatus.RECEIVER_PRESENCE_ERROR) continue
|
if (status == ResolutionStatus.RECEIVER_TYPE_ERROR || status == ResolutionStatus.RECEIVER_PRESENCE_ERROR) continue
|
||||||
|
|
||||||
// check that all arguments before the current one matched
|
// check that all arguments before the current one matched
|
||||||
if (!candidate.noErrorsInValueArguments()) continue
|
if (!candidate.allArgumentsMatched()) continue
|
||||||
|
|
||||||
var descriptor = candidate.getResultingDescriptor()
|
var descriptor = candidate.getResultingDescriptor()
|
||||||
if (descriptor.valueParameters.isEmpty()) continue
|
if (descriptor.valueParameters.isEmpty()) continue
|
||||||
@@ -352,6 +351,12 @@ class ExpectedInfos(
|
|||||||
return expectedInfos
|
return expectedInfos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> ResolvedCall<D>.allArgumentsMatched()
|
||||||
|
= call.valueArguments.none { argument -> getArgumentMapping(argument).isError() && !argument.hasError() /* ignore arguments that has error type */ }
|
||||||
|
|
||||||
|
private fun ValueArgument.hasError()
|
||||||
|
= getArgumentExpression()?.let { bindingContext.getType(it) }?.isError ?: true
|
||||||
|
|
||||||
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
||||||
val usedParameterNames = (argumentToParameter.values().map { it.getName() } + listOf(argumentName)).toSet()
|
val usedParameterNames = (argumentToParameter.values().map { it.getName() } + listOf(argumentName)).toSet()
|
||||||
val notUsedParameters = descriptor.getValueParameters().filter { it.getName() !in usedParameterNames }
|
val notUsedParameters = descriptor.getValueParameters().filter { it.getName() !in usedParameterNames }
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
class A
|
||||||
|
class B
|
||||||
|
class C
|
||||||
|
class D
|
||||||
|
class E
|
||||||
|
|
||||||
|
fun foo(s: String, a: A){}
|
||||||
|
fun foo(p: Int, b: B, c: C){}
|
||||||
|
fun foo(s: String, d: D, e: E, a: A){}
|
||||||
|
|
||||||
|
fun f(pa: A, pb: B, pc: C, pd: D, pe: E) {
|
||||||
|
foo(xxx, pb, <caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: pc
|
||||||
|
// ABSENT: pa, pb, pd, pe
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
class A
|
||||||
|
class B
|
||||||
|
class C
|
||||||
|
class D
|
||||||
|
class E
|
||||||
|
|
||||||
|
fun foo(a: A){}
|
||||||
|
fun foo(b: B, c: C){}
|
||||||
|
fun foo(d: D, e: E, a: A){}
|
||||||
|
|
||||||
|
fun f(pa: A, pb: B, pc: C, pd: D, pe: E) {
|
||||||
|
foo(pa, <caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: pc, pe
|
||||||
|
// ABSENT: pa, pb, pd
|
||||||
+6
@@ -413,6 +413,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreviousArgError.kt")
|
||||||
|
public void testPreviousArgError() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/PreviousArgError.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("QualifiedOverloadedMethodCallArgument1.kt")
|
@TestMetadata("QualifiedOverloadedMethodCallArgument1.kt")
|
||||||
public void testQualifiedOverloadedMethodCallArgument1() throws Exception {
|
public void testQualifiedOverloadedMethodCallArgument1() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/QualifiedOverloadedMethodCallArgument1.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/QualifiedOverloadedMethodCallArgument1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user