[NI] Support AllCandidates mode for features in IDE
This commit is contained in:
+1
@@ -98,6 +98,7 @@ class KotlinToResolvedCallTransformer(
|
|||||||
|
|
||||||
return ktPrimitiveCompleter.completeResolvedCall(candidate) as ResolvedCall<D>
|
return ktPrimitiveCompleter.completeResolvedCall(candidate) as ResolvedCall<D>
|
||||||
}
|
}
|
||||||
|
CallResolutionResult.Type.ALL_CANDIDATES -> error("Cannot transform result for ALL_CANDIDATES mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.*
|
import org.jetbrains.kotlin.resolve.calls.results.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ManyCandidates
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
||||||
@@ -93,7 +93,8 @@ class PSICallResolver(
|
|||||||
val factoryProviderForInvoke = FactoryProviderForInvoke(context, scopeTower, kotlinCall)
|
val factoryProviderForInvoke = FactoryProviderForInvoke(context, scopeTower, kotlinCall)
|
||||||
|
|
||||||
val expectedType = calculateExpectedType(context)
|
val expectedType = calculateExpectedType(context)
|
||||||
var result = kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, kotlinCall, expectedType, factoryProviderForInvoke)
|
var result = kotlinCallResolver.resolveCall(
|
||||||
|
scopeTower, resolutionCallbacks, kotlinCall, expectedType, factoryProviderForInvoke, context.collectAllCandidates)
|
||||||
|
|
||||||
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
||||||
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) {
|
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) {
|
||||||
@@ -125,7 +126,8 @@ class PSICallResolver(
|
|||||||
it.knownTypeParametersResultingSubstitutor)
|
it.knownTypeParametersResultingSubstitutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = kotlinCallResolver.resolveGivenCandidates(scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates)
|
val result = kotlinCallResolver.resolveGivenCandidates(
|
||||||
|
scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates, context.collectAllCandidates)
|
||||||
return convertToOverloadResolutionResults(context, result, tracingStrategy)
|
return convertToOverloadResolutionResults(context, result, tracingStrategy)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,8 @@ class PSICallResolver(
|
|||||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[remOperatorName]!!
|
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[remOperatorName]!!
|
||||||
val callWithDeprecatedName = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, deprecatedName, tracingStrategy)
|
val callWithDeprecatedName = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, deprecatedName, tracingStrategy)
|
||||||
val refinedProviderForInvokeFactory = FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
|
val refinedProviderForInvokeFactory = FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
|
||||||
return kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType, refinedProviderForInvokeFactory)
|
return kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType,
|
||||||
|
refinedProviderForInvokeFactory, context.collectAllCandidates)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
|
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
|
||||||
@@ -173,6 +176,15 @@ class PSICallResolver(
|
|||||||
result: CallResolutionResult,
|
result: CallResolutionResult,
|
||||||
tracingStrategy: TracingStrategy
|
tracingStrategy: TracingStrategy
|
||||||
): OverloadResolutionResults<D> {
|
): OverloadResolutionResults<D> {
|
||||||
|
if (result.type == CallResolutionResult.Type.ALL_CANDIDATES) {
|
||||||
|
val resolvedCalls = result.allCandidates?.map {
|
||||||
|
val resultingSubstitutor = it.getSystem().asReadOnlyStorage().buildResultingSubstitutor()
|
||||||
|
kotlinToResolvedCallTransformer.transformToResolvedCall<D>(it.resolvedCall, false, resultingSubstitutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return AllCandidates(resolvedCalls ?: emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
val trace = context.trace
|
val trace = context.trace
|
||||||
|
|
||||||
result.diagnostics.firstIsInstanceOrNull<NoneCandidatesCallDiagnostic>()?.let {
|
result.diagnostics.firstIsInstanceOrNull<NoneCandidatesCallDiagnostic>()?.let {
|
||||||
@@ -559,8 +571,10 @@ class PSICallResolver(
|
|||||||
ktExpression, argumentName, lhsNewResult, name)
|
ktExpression, argumentName, lhsNewResult, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// valueArgument.getArgumentExpression()!! instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
val argumentExpression = valueArgument.getArgumentExpression() ?: return parseErrorArgument
|
||||||
val typeInfo = expressionTypingServices.getTypeInfo(valueArgument.getArgumentExpression()!!, context)
|
|
||||||
|
// argumentExpression instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
||||||
|
val typeInfo = expressionTypingServices.getTypeInfo(argumentExpression, context)
|
||||||
return createSimplePSICallArgument(context, valueArgument, typeInfo) ?: parseErrorArgument
|
return createSimplePSICallArgument(context, valueArgument, typeInfo) ?: parseErrorArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ class KotlinCallResolver(
|
|||||||
resolutionCallbacks: KotlinResolutionCallbacks,
|
resolutionCallbacks: KotlinResolutionCallbacks,
|
||||||
kotlinCall: KotlinCall,
|
kotlinCall: KotlinCall,
|
||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<KotlinResolutionCandidate>
|
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<KotlinResolutionCandidate>,
|
||||||
|
collectAllCandidates: Boolean
|
||||||
): CallResolutionResult {
|
): CallResolutionResult {
|
||||||
kotlinCall.checkCallInvariants()
|
kotlinCall.checkCallInvariants()
|
||||||
|
|
||||||
@@ -53,6 +54,11 @@ class KotlinCallResolver(
|
|||||||
KotlinCallKind.UNSUPPORTED -> throw UnsupportedOperationException()
|
KotlinCallKind.UNSUPPORTED -> throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (collectAllCandidates) {
|
||||||
|
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor)
|
||||||
|
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
|
||||||
|
}
|
||||||
|
|
||||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED)
|
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED)
|
||||||
|
|
||||||
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
|
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
|
||||||
@@ -63,12 +69,21 @@ class KotlinCallResolver(
|
|||||||
resolutionCallbacks: KotlinResolutionCallbacks,
|
resolutionCallbacks: KotlinResolutionCallbacks,
|
||||||
kotlinCall: KotlinCall,
|
kotlinCall: KotlinCall,
|
||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
givenCandidates: Collection<GivenCandidate>
|
givenCandidates: Collection<GivenCandidate>,
|
||||||
|
collectAllCandidates: Boolean
|
||||||
): CallResolutionResult {
|
): CallResolutionResult {
|
||||||
kotlinCall.checkCallInvariants()
|
kotlinCall.checkCallInvariants()
|
||||||
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall)
|
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall)
|
||||||
|
|
||||||
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
|
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
|
||||||
|
|
||||||
|
if (collectAllCandidates) {
|
||||||
|
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
|
||||||
|
TowerResolver.AllCandidatesCollector(),
|
||||||
|
useOrder = false)
|
||||||
|
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
|
||||||
|
|
||||||
|
}
|
||||||
val candidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
|
val candidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
|
||||||
TowerResolver.SuccessfulResultCollector(),
|
TowerResolver.SuccessfulResultCollector(),
|
||||||
useOrder = true)
|
useOrder = true)
|
||||||
|
|||||||
+23
-2
@@ -68,7 +68,25 @@ class KotlinCallCompleter(
|
|||||||
else {
|
else {
|
||||||
CallResolutionResult(CallResolutionResult.Type.PARTIAL, candidate.resolvedCall, diagnosticHolder.getDiagnostics(), constraintSystem.asReadOnlyStorage())
|
CallResolutionResult(CallResolutionResult.Type.PARTIAL, candidate.resolvedCall, diagnosticHolder.getDiagnostics(), constraintSystem.asReadOnlyStorage())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createAllCandidatesResult(
|
||||||
|
candidates: Collection<KotlinResolutionCandidate>,
|
||||||
|
expectedType: UnwrappedType?,
|
||||||
|
resolutionCallbacks: KotlinResolutionCallbacks
|
||||||
|
): CallResolutionResult {
|
||||||
|
val diagnosticsHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
||||||
|
for (candidate in candidates) {
|
||||||
|
candidate.prepareForCompletion(expectedType)
|
||||||
|
runCompletion(
|
||||||
|
candidate.resolvedCall,
|
||||||
|
ConstraintSystemCompletionMode.FULL,
|
||||||
|
diagnosticsHolder,
|
||||||
|
candidate.getSystem(),
|
||||||
|
resolutionCallbacks,
|
||||||
|
skipPostponedArguments = true)
|
||||||
|
}
|
||||||
|
return CallResolutionResult(CallResolutionResult.Type.ALL_CANDIDATES, null, emptyList(), ConstraintStorage.Empty, candidates)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runCompletion(
|
private fun runCompletion(
|
||||||
@@ -76,11 +94,14 @@ class KotlinCallCompleter(
|
|||||||
completionMode: ConstraintSystemCompletionMode,
|
completionMode: ConstraintSystemCompletionMode,
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
constraintSystem: NewConstraintSystem,
|
constraintSystem: NewConstraintSystem,
|
||||||
resolutionCallbacks: KotlinResolutionCallbacks
|
resolutionCallbacks: KotlinResolutionCallbacks,
|
||||||
|
skipPostponedArguments: Boolean = false
|
||||||
) {
|
) {
|
||||||
val returnType = resolvedCallAtom.freshReturnType ?: constraintSystem.builtIns.unitType
|
val returnType = resolvedCallAtom.freshReturnType ?: constraintSystem.builtIns.unitType
|
||||||
kotlinConstraintSystemCompleter.runCompletion(constraintSystem.asConstraintSystemCompleterContext(), completionMode, resolvedCallAtom, returnType) {
|
kotlinConstraintSystemCompleter.runCompletion(constraintSystem.asConstraintSystemCompleterContext(), completionMode, resolvedCallAtom, returnType) {
|
||||||
postponedArgumentsAnalyzer.analyze(constraintSystem.asPostponedArgumentsAnalyzerContext(), resolutionCallbacks, it)
|
if (!skipPostponedArguments) {
|
||||||
|
postponedArgumentsAnalyzer.analyze(constraintSystem.asPostponedArgumentsAnalyzerContext(), resolutionCallbacks, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constraintSystem.diagnostics.forEach(diagnosticsHolder::addDiagnostic)
|
constraintSystem.diagnostics.forEach(diagnosticsHolder::addDiagnostic)
|
||||||
|
|||||||
@@ -150,14 +150,16 @@ class CallResolutionResult(
|
|||||||
val type: Type,
|
val type: Type,
|
||||||
val resultCallAtom: ResolvedCallAtom?,
|
val resultCallAtom: ResolvedCallAtom?,
|
||||||
diagnostics: List<KotlinCallDiagnostic>,
|
diagnostics: List<KotlinCallDiagnostic>,
|
||||||
val constraintSystem: ConstraintStorage
|
val constraintSystem: ConstraintStorage,
|
||||||
|
val allCandidates: Collection<KotlinResolutionCandidate>? = null
|
||||||
) : ResolvedAtom() {
|
) : ResolvedAtom() {
|
||||||
override val atom: ResolutionAtom? get() = null
|
override val atom: ResolutionAtom? get() = null
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
COMPLETED, // resultSubstitutor possible create use constraintSystem
|
COMPLETED, // resultSubstitutor possible create use constraintSystem
|
||||||
PARTIAL,
|
PARTIAL,
|
||||||
ERROR // if resultCallAtom == null it means that there is errors NoneCandidates or ManyCandidates
|
ERROR, // if resultCallAtom == null it means that there is errors NoneCandidates or ManyCandidates
|
||||||
|
ALL_CANDIDATES // allCandidates != null
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
Reference in New Issue
Block a user