Base dynamic support in new resolve
This commit is contained in:
+18
-6
@@ -35,10 +35,13 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
@@ -46,7 +49,8 @@ import org.jetbrains.kotlin.utils.sure
|
||||
class NewResolveOldInference(
|
||||
val candidateResolver: CandidateResolver,
|
||||
val towerResolver: TowerResolver,
|
||||
val resolutionResultsHandler: ResolutionResultsHandler
|
||||
val resolutionResultsHandler: ResolutionResultsHandler,
|
||||
val dynamicCallableDescriptors: DynamicCallableDescriptors
|
||||
) {
|
||||
|
||||
fun runResolve(
|
||||
@@ -57,7 +61,8 @@ class NewResolveOldInference(
|
||||
): OverloadResolutionResultsImpl<*> {
|
||||
val explicitReceiver = context.call.explicitReceiver.check { it.exists() }
|
||||
|
||||
val scopeTower = ScopeTowerImpl(context, explicitReceiver, context.call.createLookupLocation())
|
||||
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
|
||||
val scopeTower = ScopeTowerImpl(context, dynamicScope, explicitReceiver, context.call.createLookupLocation())
|
||||
|
||||
val baseContext = Context(scopeTower, name, context, tracing)
|
||||
|
||||
@@ -74,7 +79,7 @@ class NewResolveOldInference(
|
||||
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
|
||||
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
|
||||
}
|
||||
createCollectorWithReceiverValueOrEmpty(explicitReceiver) {
|
||||
createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
|
||||
createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it)
|
||||
}
|
||||
}
|
||||
@@ -87,7 +92,7 @@ class NewResolveOldInference(
|
||||
return convertToOverloadResults(candidates, tracing, context)
|
||||
}
|
||||
|
||||
private fun createCollectorWithReceiverValueOrEmpty(
|
||||
private fun createProcessorWithReceiverValueOrEmpty(
|
||||
explicitReceiver: Receiver?,
|
||||
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
|
||||
): ScopeTowerProcessor<Candidate> {
|
||||
@@ -100,7 +105,6 @@ class NewResolveOldInference(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun createFunctionTowerProcessor(baseContext: Context, explicitReceiver: Receiver?): CompositeScopeTowerProcessor<Candidate> {
|
||||
// a.foo() -- simple function call
|
||||
val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver)
|
||||
@@ -109,7 +113,7 @@ class NewResolveOldInference(
|
||||
val invokeProcessor = InvokeTowerProcessor(baseContext, explicitReceiver)
|
||||
|
||||
// a.foo() -- property foo is extension function with receiver a -- a.invoke()
|
||||
val invokeExtensionProcessor = createCollectorWithReceiverValueOrEmpty(explicitReceiver) { InvokeExtensionTowerProcessor(baseContext, it) }
|
||||
val invokeExtensionProcessor = createProcessorWithReceiverValueOrEmpty(explicitReceiver) { InvokeExtensionTowerProcessor(baseContext, it) }
|
||||
|
||||
return CompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor)
|
||||
}
|
||||
@@ -178,6 +182,14 @@ class NewResolveOldInference(
|
||||
explicitReceiverKind, null, candidateTrace, tracing,
|
||||
basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments
|
||||
)
|
||||
|
||||
// see spec-docs/dynamic-types.md
|
||||
if (extensionReceiver != null && extensionReceiver.type.isDynamic()
|
||||
&& !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) {
|
||||
candidateCall.addStatus(ResolutionStatus.RECEIVER_PRESENCE_ERROR)
|
||||
return Candidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
|
||||
}
|
||||
|
||||
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
|
||||
candidateCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
|
||||
ReceiverValue.NO_RECEIVER, CandidateResolveMode.FULLY // todo
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -33,6 +34,8 @@ interface ScopeTower {
|
||||
|
||||
val lexicalScope: LexicalScope
|
||||
|
||||
val dynamicScope: MemberScope
|
||||
|
||||
val location: LookupLocation
|
||||
|
||||
val dataFlowInfo: DataFlowDecorator
|
||||
@@ -91,6 +94,8 @@ class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): Resolutio
|
||||
|
||||
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE)
|
||||
object SynthesizedDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
|
||||
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
|
||||
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
|
||||
object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -43,6 +44,7 @@ internal class CandidateWithBoundDispatchReceiverImpl<D : CallableDescriptor>(
|
||||
|
||||
internal class ScopeTowerImpl(
|
||||
resolutionContext: ResolutionContext<*>,
|
||||
override val dynamicScope: MemberScope,
|
||||
private val explicitReceiver: Receiver?,
|
||||
override val location: LookupLocation
|
||||
): ScopeTower {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
@@ -147,6 +148,12 @@ internal class ReceiverScopeTowerLevel(
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatchReceiver.type.isDynamic()) {
|
||||
scopeTower.dynamicScope.members().mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user