[NI] Refactor adding expected type constraint
Add comments, make computation needed for expected type more clear
This commit is contained in:
+44
-24
@@ -28,18 +28,22 @@ class KotlinCallCompleter(
|
|||||||
resolutionCallbacks: KotlinResolutionCallbacks
|
resolutionCallbacks: KotlinResolutionCallbacks
|
||||||
): CallResolutionResult {
|
): CallResolutionResult {
|
||||||
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
||||||
if (candidates.isEmpty()) {
|
when {
|
||||||
diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic(factory.kotlinCall))
|
candidates.isEmpty() -> diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic(factory.kotlinCall))
|
||||||
}
|
candidates.size > 1 -> diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates))
|
||||||
if (candidates.size > 1) {
|
|
||||||
diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val candidate = prepareCandidateForCompletion(factory, candidates, resolutionCallbacks)
|
val candidate = prepareCandidateForCompletion(factory, candidates, resolutionCallbacks)
|
||||||
val completionType = candidate.prepareForCompletion(expectedType, resolutionCallbacks)
|
val returnType = candidate.returnTypeWithSmartCastInfo(resolutionCallbacks)
|
||||||
|
|
||||||
|
candidate.addExpectedTypeConstraint(returnType, expectedType, resolutionCallbacks)
|
||||||
|
|
||||||
return if (resolutionCallbacks.inferenceSession.shouldRunCompletion(candidate))
|
return if (resolutionCallbacks.inferenceSession.shouldRunCompletion(candidate))
|
||||||
candidate.runCompletion(completionType, diagnosticHolder, resolutionCallbacks)
|
candidate.runCompletion(
|
||||||
|
candidate.computeCompletionMode(expectedType, returnType),
|
||||||
|
diagnosticHolder,
|
||||||
|
resolutionCallbacks
|
||||||
|
)
|
||||||
else
|
else
|
||||||
candidate.asCallResolutionResult(ConstraintSystemCompletionMode.PARTIAL, diagnosticHolder)
|
candidate.asCallResolutionResult(ConstraintSystemCompletionMode.PARTIAL, diagnosticHolder)
|
||||||
}
|
}
|
||||||
@@ -51,7 +55,10 @@ class KotlinCallCompleter(
|
|||||||
): CallResolutionResult {
|
): CallResolutionResult {
|
||||||
val diagnosticsHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
val diagnosticsHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
||||||
for (candidate in candidates) {
|
for (candidate in candidates) {
|
||||||
candidate.prepareForCompletion(expectedType, resolutionCallbacks)
|
candidate.addExpectedTypeConstraint(
|
||||||
|
candidate.returnTypeWithSmartCastInfo(resolutionCallbacks), expectedType, resolutionCallbacks
|
||||||
|
)
|
||||||
|
|
||||||
runCompletion(
|
runCompletion(
|
||||||
candidate.resolvedCall,
|
candidate.resolvedCall,
|
||||||
ConstraintSystemCompletionMode.FULL,
|
ConstraintSystemCompletionMode.FULL,
|
||||||
@@ -122,27 +129,40 @@ class KotlinCallCompleter(
|
|||||||
return candidate ?: factory.createErrorCandidate().forceResolution()
|
return candidate ?: factory.createErrorCandidate().forceResolution()
|
||||||
}
|
}
|
||||||
|
|
||||||
// true if we should complete this call
|
private fun KotlinResolutionCandidate.returnTypeWithSmartCastInfo(resolutionCallbacks: KotlinResolutionCallbacks): UnwrappedType? {
|
||||||
private fun KotlinResolutionCandidate.prepareForCompletion(
|
val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null
|
||||||
|
val returnTypeWithSmartCastInfo = computeReturnTypeWithSmartCastInfo(returnType, resolutionCallbacks)
|
||||||
|
return resolvedCall.substitutor.substituteKeepAnnotations(returnTypeWithSmartCastInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KotlinResolutionCandidate.addExpectedTypeConstraint(
|
||||||
|
returnType: UnwrappedType?,
|
||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
resolutionCallbacks: KotlinResolutionCallbacks
|
resolutionCallbacks: KotlinResolutionCallbacks
|
||||||
): ConstraintSystemCompletionMode {
|
) {
|
||||||
if (expectedType != null && TypeUtils.noExpectedType(expectedType)) return ConstraintSystemCompletionMode.FULL
|
if (returnType == null) return
|
||||||
|
if (expectedType == null || TypeUtils.noExpectedType(expectedType)) return
|
||||||
|
|
||||||
val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return ConstraintSystemCompletionMode.PARTIAL
|
// We don't add expected type constraint for constant expression like "1 + 1" because of type coercion for numbers:
|
||||||
val substitutedType: UnwrappedType
|
// val a: Long = 1 + 1, note that result type of "1 + 1" will be Int and adding constraint with Long will produce type mismatch
|
||||||
if (expectedType != null) {
|
if (!resolutionCallbacks.isCompileTimeConstant(resolvedCall, expectedType)) {
|
||||||
val returnTypeWithSmartCastInfo = computeReturnTypeWithSmartCastInfo(returnType, resolutionCallbacks)
|
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPosition(resolvedCall.atom))
|
||||||
substitutedType = resolvedCall.substitutor.substituteKeepAnnotations(returnTypeWithSmartCastInfo)
|
|
||||||
|
|
||||||
if (!resolutionCallbacks.isCompileTimeConstant(resolvedCall, expectedType)) {
|
|
||||||
csBuilder.addSubtypeConstraint(substitutedType, expectedType, ExpectedTypeConstraintPosition(resolvedCall.atom))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
substitutedType = resolvedCall.substitutor.substituteKeepAnnotations(returnType)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return if (expectedType != null || csBuilder.isProperType(substitutedType))
|
private fun KotlinResolutionCandidate.computeCompletionMode(
|
||||||
|
expectedType: UnwrappedType?,
|
||||||
|
currentReturnType: UnwrappedType?
|
||||||
|
): ConstraintSystemCompletionMode {
|
||||||
|
// Presence of expected type means that we trying to complete outermost call => completion mode should be full
|
||||||
|
if (expectedType != null) return ConstraintSystemCompletionMode.FULL
|
||||||
|
|
||||||
|
// This is questionable as null return type can be only for error call
|
||||||
|
if (currentReturnType == null) return ConstraintSystemCompletionMode.PARTIAL
|
||||||
|
|
||||||
|
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
|
||||||
|
// Otherwise, we shouldn't complete bar until we process call foo
|
||||||
|
return if (csBuilder.isProperType(currentReturnType))
|
||||||
ConstraintSystemCompletionMode.FULL
|
ConstraintSystemCompletionMode.FULL
|
||||||
else
|
else
|
||||||
ConstraintSystemCompletionMode.PARTIAL
|
ConstraintSystemCompletionMode.PARTIAL
|
||||||
|
|||||||
Reference in New Issue
Block a user