Create new Tower Resolve
This commit is contained in:
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolveOldInference;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||
@@ -78,6 +79,7 @@ public class CallResolver {
|
||||
private ArgumentTypeResolver argumentTypeResolver;
|
||||
private GenericCandidateResolver genericCandidateResolver;
|
||||
private CallCompleter callCompleter;
|
||||
private NewResolveOldInference newCallResolver;
|
||||
private final TaskPrioritizer taskPrioritizer;
|
||||
private final ResolutionResultsHandler resolutionResultsHandler;
|
||||
@NotNull private KotlinBuiltIns builtIns;
|
||||
@@ -85,6 +87,8 @@ public class CallResolver {
|
||||
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
|
||||
private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
|
||||
|
||||
public static boolean useNewResolve = System.getProperty("kotlin.internal.new_resolve") != null;
|
||||
|
||||
public CallResolver(
|
||||
@NotNull TaskPrioritizer taskPrioritizer,
|
||||
@NotNull ResolutionResultsHandler resolutionResultsHandler,
|
||||
@@ -131,6 +135,12 @@ public class CallResolver {
|
||||
this.callCompleter = callCompleter;
|
||||
}
|
||||
|
||||
// component dependency cycle
|
||||
@Inject
|
||||
public void setCallCompleter(@NotNull NewResolveOldInference newCallResolver) {
|
||||
this.newCallResolver = newCallResolver;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
|
||||
KtExpression calleeExpression = context.call.getCalleeExpression();
|
||||
@@ -592,6 +602,12 @@ public class CallResolver {
|
||||
}
|
||||
}
|
||||
|
||||
if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES && useNewResolve) {
|
||||
assert contextForMigration.name != null;
|
||||
return (OverloadResolutionResultsImpl<F>)
|
||||
newCallResolver.runResolve(context, contextForMigration.name, contextForMigration.resolveKind, tracing);
|
||||
}
|
||||
|
||||
return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing);
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
|
||||
public interface VariableAsFunctionResolvedCall {
|
||||
public val functionCall: ResolvedCall<FunctionDescriptor>
|
||||
@@ -42,6 +43,9 @@ class VariableAsFunctionResolvedCallImpl(
|
||||
|
||||
override fun getTrace(): DelegatingBindingTrace {
|
||||
//functionCall.trace is temporary trace above variableCall.trace and is committed already
|
||||
if (CallResolver.useNewResolve) {
|
||||
return functionCall.trace
|
||||
}
|
||||
return variableCall.getTrace()
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ public class ResolutionResultsHandler {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||
@NotNull Set<MutableResolvedCall<D>> candidates,
|
||||
boolean discriminateGenerics,
|
||||
@NotNull CheckArgumentTypesMode checkArgumentsMode
|
||||
|
||||
@@ -99,7 +99,7 @@ public class TaskPrioritizer(
|
||||
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
||||
) {
|
||||
if (qualifier is ClassQualifier) {
|
||||
val companionObject = qualifier.companionObjectReceiver ?: return
|
||||
val companionObject = qualifier.classValueReceiver ?: return
|
||||
val classifierDescriptor = qualifier.classifier
|
||||
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
|
||||
when {
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
|
||||
internal abstract class AbstractInvokeTowerProcessor<C>(
|
||||
protected val functionContext: TowerContext<C>,
|
||||
private val variableProcessor: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
// todo optimize it
|
||||
private val previousActions = ArrayList<ScopeTowerProcessor<C>.() -> Unit>()
|
||||
private val candidateGroups: MutableList<Collection<C>> = ArrayList()
|
||||
|
||||
private val invokeProcessors: MutableList<Collection<VariableInvokeProcessor>> = ArrayList()
|
||||
|
||||
|
||||
private inner class VariableInvokeProcessor(
|
||||
val variableCandidate: C,
|
||||
val invokeProcessor: ScopeTowerProcessor<C> = createInvokeProcessor(variableCandidate)
|
||||
): ScopeTowerProcessor<C> by invokeProcessor {
|
||||
override fun getCandidatesGroups(): List<Collection<C>>
|
||||
= invokeProcessor.getCandidatesGroups().map { candidateGroup ->
|
||||
candidateGroup.map { functionContext.transformCandidate(variableCandidate, it) }
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C>
|
||||
|
||||
private fun findVariablesAndCreateNewInvokeCandidates() {
|
||||
for (variableCandidates in variableProcessor.getCandidatesGroups()) {
|
||||
val successfulVariables = variableCandidates.filter {
|
||||
functionContext.getStatus(it).resultingApplicability.isSuccess
|
||||
}
|
||||
|
||||
if (successfulVariables.isNotEmpty()) {
|
||||
val processors = successfulVariables.map { VariableInvokeProcessor(it) }
|
||||
invokeProcessors.add(processors)
|
||||
|
||||
for (previousAction in previousActions) {
|
||||
processors.forEach(previousAction)
|
||||
candidateGroups.addAll(processors.collectCandidateGroups())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Collection<VariableInvokeProcessor>.collectCandidateGroups(): List<Collection<C>> {
|
||||
return when (size) {
|
||||
0 -> emptyList()
|
||||
1 -> single().getCandidatesGroups()
|
||||
// overload on variables see KT-10093 Resolve depends on the order of declaration for variable with implicit invoke
|
||||
|
||||
else -> listOf(this.flatMap { it.getCandidatesGroups().flatten() })
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceed(action: ScopeTowerProcessor<C>.() -> Unit) {
|
||||
candidateGroups.clear()
|
||||
previousActions.add(action)
|
||||
|
||||
for (processorsGroup in invokeProcessors) {
|
||||
processorsGroup.forEach(action)
|
||||
candidateGroups.addAll(processorsGroup.collectCandidateGroups())
|
||||
}
|
||||
|
||||
variableProcessor.action()
|
||||
findVariablesAndCreateNewInvokeCandidates()
|
||||
}
|
||||
|
||||
init { proceed { /* do nothing */ } }
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) = proceed { this.processTowerLevel(level) }
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
= proceed { this.processImplicitReceiver(implicitReceiver) }
|
||||
|
||||
override fun getCandidatesGroups(): List<Collection<C>> = SmartList(candidateGroups)
|
||||
}
|
||||
|
||||
// todo KT-9522 Allow invoke convention for synthetic property
|
||||
internal class InvokeTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
private val explicitReceiver: Receiver?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver)
|
||||
) {
|
||||
|
||||
// todo filter by operator
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
|
||||
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
|
||||
}
|
||||
}
|
||||
|
||||
internal class InvokeExtensionTowerProcessor<C>(
|
||||
functionContext: TowerContext<C>,
|
||||
private val explicitReceiver: ReceiverValue?
|
||||
) : AbstractInvokeTowerProcessor<C>(
|
||||
functionContext,
|
||||
createVariableProcessor(functionContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null)
|
||||
) {
|
||||
|
||||
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
|
||||
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
|
||||
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
|
||||
?: return KnownResultProcessor(emptyList())
|
||||
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
private class InvokeExtensionScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver<FunctionDescriptor>,
|
||||
val explicitReceiver: ReceiverValue?
|
||||
) : AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates: Collection<C> = resolve(explicitReceiver)
|
||||
|
||||
private fun resolve(extensionReceiver: ReceiverValue?): Collection<C> {
|
||||
if (extensionReceiver == null) return emptyList()
|
||||
|
||||
// todo
|
||||
val explicitReceiverKind = if (explicitReceiver != null) ExplicitReceiverKind.BOTH_RECEIVERS else ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
|
||||
val candidate = context.createCandidate(invokeCandidateDescriptor, explicitReceiverKind, extensionReceiver)
|
||||
return listOf(candidate)
|
||||
}
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
// todo optimize
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
if (explicitReceiver == null) {
|
||||
candidates = resolve(implicitReceiver)
|
||||
}
|
||||
else {
|
||||
candidates = emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo debug info
|
||||
private fun ScopeTower.getExtensionInvokeCandidateDescriptor(
|
||||
extensionFunctionReceiver: ReceiverValue
|
||||
): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
|
||||
if (!KotlinBuiltIns.isExactExtensionFunctionType(extensionFunctionReceiver.type)) return null
|
||||
|
||||
return ReceiverScopeTowerLevel(this, extensionFunctionReceiver).getFunctions(OperatorNameConventions.INVOKE).single().let {
|
||||
assert(it.diagnostics.isEmpty())
|
||||
val synthesizedInvoke = createSynthesizedInvokes(listOf(it.descriptor)).single()
|
||||
|
||||
// here we don't add SynthesizedDescriptor diagnostic because it should has priority as member
|
||||
CandidateWithBoundDispatchReceiverImpl(extensionFunctionReceiver, synthesizedInvoke, listOf())
|
||||
}
|
||||
}
|
||||
|
||||
// case 1.(foo())() or (foo())()
|
||||
internal fun <C> createCallTowerProcessorForExplicitInvoke(
|
||||
contextForInvoke: TowerContext<C>,
|
||||
expressionForInvoke: ReceiverValue,
|
||||
explicitReceiver: ReceiverValue?
|
||||
): ScopeTowerProcessor<C> {
|
||||
val invokeExtensionDescriptor = contextForInvoke.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke)
|
||||
if (explicitReceiver != null) {
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
// case 1.(foo())(), where foo() isn't extension function
|
||||
return KnownResultProcessor(emptyList())
|
||||
}
|
||||
else {
|
||||
return InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = explicitReceiver)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val usualInvoke = ExplicitReceiverScopeTowerProcessor(contextForInvoke, expressionForInvoke, ScopeTowerLevel::getFunctions) // todo operator
|
||||
|
||||
if (invokeExtensionDescriptor == null) {
|
||||
return usualInvoke
|
||||
}
|
||||
else {
|
||||
return CompositeScopeTowerProcessor(
|
||||
usualInvoke,
|
||||
InvokeExtensionScopeTowerProcessor(contextForInvoke, invokeExtensionDescriptor, explicitReceiver = null)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||
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.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.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
class NewResolveOldInference(
|
||||
val candidateResolver: CandidateResolver,
|
||||
val towerResolver: TowerResolver,
|
||||
val resolutionResultsHandler: ResolutionResultsHandler
|
||||
) {
|
||||
|
||||
fun runResolve(
|
||||
context: BasicCallResolutionContext,
|
||||
name: Name,
|
||||
kind: CallResolver.ResolveKind,
|
||||
tracing: TracingStrategy
|
||||
): OverloadResolutionResultsImpl<*> {
|
||||
val explicitReceiver = context.call.explicitReceiver.check { it.exists() }
|
||||
|
||||
val scopeTower = ScopeTowerImpl(context, explicitReceiver, context.call.createLookupLocation())
|
||||
|
||||
val baseContext = Context(scopeTower, name, context, tracing)
|
||||
|
||||
val processor =
|
||||
when (kind) {
|
||||
CallResolver.ResolveKind.VARIABLE -> createVariableProcessor(baseContext, explicitReceiver)
|
||||
CallResolver.ResolveKind.FUNCTION -> createFunctionTowerProcessor(baseContext, explicitReceiver)
|
||||
CallResolver.ResolveKind.CALLABLE_REFERENCE -> CompositeScopeTowerProcessor(
|
||||
createFunctionTowerProcessor(baseContext, explicitReceiver),
|
||||
createVariableProcessor(baseContext, explicitReceiver)
|
||||
)
|
||||
CallResolver.ResolveKind.INVOKE -> {
|
||||
// todo
|
||||
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
|
||||
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
|
||||
}
|
||||
createCollectorWithReceiverValueOrEmpty(explicitReceiver) {
|
||||
createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it)
|
||||
}
|
||||
}
|
||||
CallResolver.ResolveKind.GIVEN_CANDIDATES -> {
|
||||
throw UnsupportedOperationException("Kind $kind unsupported yet")
|
||||
}
|
||||
}
|
||||
|
||||
val candidates = towerResolver.runResolve(baseContext, processor, useOrder = kind != CallResolver.ResolveKind.CALLABLE_REFERENCE)
|
||||
return convertToOverloadResults(candidates, tracing, context)
|
||||
}
|
||||
|
||||
private fun createCollectorWithReceiverValueOrEmpty(
|
||||
explicitReceiver: Receiver?,
|
||||
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
|
||||
): ScopeTowerProcessor<Candidate> {
|
||||
return if (explicitReceiver is Qualifier) {
|
||||
(explicitReceiver as? ClassQualifier)?.classValueReceiver?.let(create)
|
||||
?: KnownResultProcessor<Candidate>(listOf())
|
||||
}
|
||||
else {
|
||||
create(explicitReceiver as ReceiverValue?)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun createFunctionTowerProcessor(baseContext: Context, explicitReceiver: Receiver?): CompositeScopeTowerProcessor<Candidate> {
|
||||
// a.foo() -- simple function call
|
||||
val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver)
|
||||
|
||||
// a.foo() -- property a.foo + foo.invoke()
|
||||
val invokeProcessor = InvokeTowerProcessor(baseContext, explicitReceiver)
|
||||
|
||||
// a.foo() -- property foo is extension function with receiver a -- a.invoke()
|
||||
val invokeExtensionProcessor = createCollectorWithReceiverValueOrEmpty(explicitReceiver) { InvokeExtensionTowerProcessor(baseContext, it) }
|
||||
|
||||
return CompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor)
|
||||
}
|
||||
|
||||
|
||||
private fun convertToOverloadResults(
|
||||
candidates: Collection<Candidate>,
|
||||
tracing: TracingStrategy,
|
||||
basicCallContext: BasicCallResolutionContext
|
||||
): OverloadResolutionResultsImpl<*> {
|
||||
val resolvedCalls = candidates.mapNotNull {
|
||||
val (status, resolvedCall) = it
|
||||
if (resolvedCall is VariableAsFunctionResolvedCallImpl) {
|
||||
// todo hacks
|
||||
tracing.bindReference(resolvedCall.variableCall.trace, resolvedCall.variableCall)
|
||||
tracing.bindResolvedCall(resolvedCall.variableCall.trace, resolvedCall)
|
||||
|
||||
resolvedCall.variableCall.trace.addOwnDataTo(resolvedCall.functionCall.trace)
|
||||
|
||||
resolvedCall.functionCall.tracingStrategy.bindReference(resolvedCall.functionCall.trace, resolvedCall.functionCall)
|
||||
// resolvedCall.hackInvokeTracing.bindResolvedCall(resolvedCall.functionCall.trace, resolvedCall)
|
||||
} else {
|
||||
tracing.bindReference(resolvedCall.trace, resolvedCall)
|
||||
tracing.bindResolvedCall(resolvedCall.trace, resolvedCall)
|
||||
}
|
||||
|
||||
if (resolvedCall.status.possibleTransformToSuccess()) {
|
||||
for (error in status.diagnostics) {
|
||||
if (error is UnsupportedInnerClassCall) {
|
||||
resolvedCall.trace.report(Errors.UNSUPPORTED.on(resolvedCall.call.callElement, error.message))
|
||||
}
|
||||
else if (error is NestedClassViaInstanceReference) {
|
||||
tracing.nestedClassAccessViaInstanceReference(resolvedCall.trace, error.classDescriptor, resolvedCall.explicitReceiverKind)
|
||||
}
|
||||
else if (error is ErrorDescriptorDiagnostic) {
|
||||
// todo
|
||||
// return@map null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolvedCall
|
||||
}
|
||||
|
||||
return resolutionResultsHandler.computeResultAndReportErrors<CallableDescriptor>(basicCallContext, tracing, resolvedCalls as List<MutableResolvedCall<CallableDescriptor>>)
|
||||
}
|
||||
|
||||
private data class Candidate(val candidateStatus: ResolutionCandidateStatus, val resolvedCall: MutableResolvedCall<*>)
|
||||
|
||||
private inner class Context(
|
||||
override val scopeTower: ScopeTower,
|
||||
override val name: Name,
|
||||
private val basicCallContext: BasicCallResolutionContext,
|
||||
private val tracing: TracingStrategy
|
||||
) : TowerContext<Candidate> {
|
||||
|
||||
override fun createCandidate(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
extensionReceiver: ReceiverValue?
|
||||
): Candidate {
|
||||
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
|
||||
val candidateCall = ResolvedCallImpl(
|
||||
basicCallContext.call, towerCandidate.descriptor,
|
||||
towerCandidate.dispatchReceiver ?: ReceiverValue.NO_RECEIVER, extensionReceiver ?: ReceiverValue.NO_RECEIVER,
|
||||
explicitReceiverKind, null, candidateTrace, tracing,
|
||||
basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments
|
||||
)
|
||||
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
|
||||
candidateCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
|
||||
ReceiverValue.NO_RECEIVER, CandidateResolveMode.FULLY // todo
|
||||
)
|
||||
candidateResolver.performResolutionForCandidateCall(callCandidateResolutionContext, basicCallContext.checkArguments) // todo
|
||||
|
||||
val diagnostics = (towerCandidate.diagnostics + createPreviousResolveError(candidateCall.status)).filterNotNull() // todo
|
||||
return Candidate(ResolutionCandidateStatus(diagnostics), candidateCall)
|
||||
}
|
||||
|
||||
override fun getStatus(candidate: Candidate): ResolutionCandidateStatus = candidate.candidateStatus
|
||||
|
||||
override fun transformCandidate(variable: Candidate, invoke: Candidate): Candidate {
|
||||
val resolvedCallImpl = VariableAsFunctionResolvedCallImpl(
|
||||
invoke.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
|
||||
variable.resolvedCall as MutableResolvedCall<VariableDescriptor>
|
||||
)
|
||||
assert(variable.candidateStatus.resultingApplicability.isSuccess) {
|
||||
"Variable call must be success: $variable"
|
||||
}
|
||||
|
||||
return Candidate(ResolutionCandidateStatus(variable.candidateStatus.diagnostics + invoke.candidateStatus.diagnostics), resolvedCallImpl)
|
||||
}
|
||||
|
||||
override fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<Candidate> {
|
||||
val basicCallResolutionContext = basicCallContext.replaceCall(CallTransformer.stripCallArguments(basicCallContext.call))
|
||||
return Context(scopeTower, name, basicCallResolutionContext, tracing)
|
||||
}
|
||||
|
||||
override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<Candidate>> {
|
||||
assert(variable.resolvedCall.status.isSuccess)
|
||||
val calleeExpression = variable.resolvedCall.call.calleeExpression
|
||||
val variableDescriptor = variable.resolvedCall.resultingDescriptor
|
||||
assert(variable.resolvedCall.status.isSuccess && calleeExpression != null && variableDescriptor is VariableDescriptor) {
|
||||
"Unexpected varialbe candidate: $variable"
|
||||
}
|
||||
val variableReceiver = ExpressionReceiver.create(calleeExpression!!,
|
||||
(variableDescriptor as VariableDescriptor).type,
|
||||
basicCallContext.trace.bindingContext)
|
||||
|
||||
// todo hack
|
||||
val functionCall = CallTransformer.CallForImplicitInvoke(
|
||||
basicCallContext.call.explicitReceiver.check { useExplicitReceiver } ?: ReceiverValue.NO_RECEIVER,
|
||||
variableReceiver, basicCallContext.call)
|
||||
val tracingForInvoke = TracingStrategyForInvoke(calleeExpression, functionCall, variableReceiver.type)
|
||||
val basicCallResolutionContext = basicCallContext.replaceBindingTrace(variable.resolvedCall.trace)
|
||||
.replaceContextDependency(ContextDependency.DEPENDENT) // todo
|
||||
val newContext = Context(scopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke)
|
||||
|
||||
return variableReceiver to newContext
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
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.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface ScopeTower {
|
||||
/**
|
||||
* Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first
|
||||
* Doesn't include receivers with error types
|
||||
*/
|
||||
val implicitReceivers: List<ReceiverValue>
|
||||
|
||||
val lexicalScope: LexicalScope
|
||||
|
||||
val location: LookupLocation
|
||||
|
||||
val dataFlowInfo: DataFlowDecorator
|
||||
|
||||
// The closest (the most local) levels goes first
|
||||
val levels: Sequence<ScopeTowerLevel>
|
||||
}
|
||||
|
||||
interface DataFlowDecorator {
|
||||
fun getDataFlowValue(receiver: ReceiverValue): DataFlowValue
|
||||
|
||||
fun isStableReceiver(receiver: ReceiverValue): Boolean
|
||||
|
||||
// doesn't include receiver.type
|
||||
fun getSmartCastTypes(receiver: ReceiverValue): Set<KotlinType>
|
||||
}
|
||||
|
||||
interface ScopeTowerLevel {
|
||||
fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>>
|
||||
|
||||
fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>
|
||||
}
|
||||
|
||||
interface CandidateWithBoundDispatchReceiver<out D : CallableDescriptor> {
|
||||
val descriptor: D
|
||||
|
||||
val diagnostics: List<ResolutionDiagnostic>
|
||||
|
||||
val dispatchReceiver: ReceiverValue?
|
||||
}
|
||||
|
||||
class ResolutionCandidateStatus(val diagnostics: List<ResolutionDiagnostic>) {
|
||||
val resultingApplicability: ResolutionCandidateApplicability = diagnostics.asSequence().map { it.candidateLevel }.max()
|
||||
?: ResolutionCandidateApplicability.RESOLVED
|
||||
}
|
||||
|
||||
enum class ResolutionCandidateApplicability {
|
||||
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
|
||||
RESOLVED_SYNTHESIZED,
|
||||
CONVENTION_ERROR, // missing infix, operator etc
|
||||
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
|
||||
RUNTIME_ERROR, // problems with visibility
|
||||
IMPOSSIBLE_TO_GENERATE, // access to outer class from nested
|
||||
INAPPLICABLE // arguments not matched
|
||||
// todo wrong receiver
|
||||
}
|
||||
|
||||
abstract class ResolutionDiagnostic(val candidateLevel: ResolutionCandidateApplicability)
|
||||
|
||||
// todo error for this access from nested class
|
||||
class VisibilityError(val invisibleMember: DeclarationDescriptorWithVisibility): ResolutionDiagnostic(ResolutionCandidateApplicability.RUNTIME_ERROR)
|
||||
class NestedClassViaInstanceReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
|
||||
class InnerClassViaStaticReference(val classDescriptor: ClassDescriptor): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
|
||||
class UnsupportedInnerClassCall(val message: String): ResolutionDiagnostic(ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE)
|
||||
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
|
||||
|
||||
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE)
|
||||
object SynthesizedDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
|
||||
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
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.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.containsError
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
|
||||
internal class CandidateWithBoundDispatchReceiverImpl<D : CallableDescriptor>(
|
||||
override val dispatchReceiver: ReceiverValue?,
|
||||
override val descriptor: D,
|
||||
override val diagnostics: List<ResolutionDiagnostic>
|
||||
) : CandidateWithBoundDispatchReceiver<D>
|
||||
|
||||
internal class ScopeTowerImpl(
|
||||
resolutionContext: ResolutionContext<*>,
|
||||
private val explicitReceiver: Receiver?,
|
||||
override val location: LookupLocation
|
||||
): ScopeTower {
|
||||
override val dataFlowInfo: DataFlowDecorator = DataFlowDecoratorImpl(resolutionContext)
|
||||
override val lexicalScope: LexicalScope = resolutionContext.scope
|
||||
|
||||
override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy().
|
||||
mapNotNull { it.value.check { !it.type.containsError() } }
|
||||
|
||||
override val levels: Sequence<ScopeTowerLevel> = createPrototypeLevels().asSequence().map { it.asTowerLevel(this) }
|
||||
|
||||
// we shouldn't calculate this before we entrance to some importing scope
|
||||
private val receiversForSyntheticExtensions: Collection<KotlinType> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
if (explicitReceiver != null) {
|
||||
if (explicitReceiver is ReceiverValue) {
|
||||
return@lazy dataFlowInfo.getAllPossibleTypes(explicitReceiver)
|
||||
}
|
||||
|
||||
if (explicitReceiver is ClassQualifier) {
|
||||
explicitReceiver.classValueReceiver?.let {
|
||||
return@lazy dataFlowInfo.getAllPossibleTypes(it)
|
||||
}
|
||||
}
|
||||
|
||||
// explicit receiver is package or class without companion object
|
||||
emptyList()
|
||||
}
|
||||
else {
|
||||
implicitReceivers.flatMap { dataFlowInfo.getAllPossibleTypes(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class LevelFactory {
|
||||
abstract fun asTowerLevel(resolveTower: ScopeTower): ScopeTowerLevel
|
||||
|
||||
class Scope(val lexicalScope: LexicalScope): LevelFactory() {
|
||||
override fun asTowerLevel(resolveTower: ScopeTower) = ScopeBasedTowerLevel(resolveTower, lexicalScope)
|
||||
}
|
||||
|
||||
class Receiver(val implicitReceiver: ReceiverParameterDescriptor): LevelFactory() {
|
||||
override fun asTowerLevel(resolveTower: ScopeTower) = ReceiverScopeTowerLevel(resolveTower, implicitReceiver.value)
|
||||
}
|
||||
|
||||
class ImportingScopeFactory(val importingScope: ImportingScope, val lazyReceiversForSyntheticExtensions: () -> Collection<KotlinType>): LevelFactory() {
|
||||
override fun asTowerLevel(resolveTower: ScopeTower) = ImportingScopeBasedTowerLevel(resolveTower, importingScope, lazyReceiversForSyntheticExtensions())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPrototypeLevels(): List<LevelFactory> {
|
||||
val result = ArrayList<LevelFactory>()
|
||||
|
||||
// locals win
|
||||
lexicalScope.parentsWithSelf.
|
||||
filterIsInstance<LexicalScope>().
|
||||
filter { it.kind.withLocalDescriptors }.
|
||||
mapTo(result) { LevelFactory.Scope(it) }
|
||||
|
||||
lexicalScope.parentsWithSelf.forEach { scope ->
|
||||
if (scope is LexicalScope) {
|
||||
if (!scope.kind.withLocalDescriptors) result.add(LevelFactory.Scope(scope))
|
||||
|
||||
scope.implicitReceiver?.let { result.add(LevelFactory.Receiver(it)) }
|
||||
}
|
||||
else {
|
||||
result.add(LevelFactory.ImportingScopeFactory(scope as ImportingScope, { receiversForSyntheticExtensions }))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DataFlowDecoratorImpl(private val resolutionContext: ResolutionContext<*>): DataFlowDecorator {
|
||||
private val dataFlowInfo = resolutionContext.dataFlowInfo
|
||||
private val cache = HashMap<ReceiverValue, SmartCastInfo>()
|
||||
|
||||
private fun getSmartCastInfo(receiver: ReceiverValue): SmartCastInfo
|
||||
= cache.getOrPut(receiver) {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, resolutionContext)
|
||||
SmartCastInfo(dataFlowValue, dataFlowInfo.getPossibleTypes(dataFlowValue))
|
||||
}
|
||||
|
||||
override fun getDataFlowValue(receiver: ReceiverValue): DataFlowValue = getSmartCastInfo(receiver).dataFlowValue
|
||||
|
||||
override fun isStableReceiver(receiver: ReceiverValue): Boolean = getSmartCastInfo(receiver).dataFlowValue.isPredictable
|
||||
|
||||
override fun getSmartCastTypes(receiver: ReceiverValue): Set<KotlinType> = getSmartCastInfo(receiver).possibleTypes
|
||||
|
||||
private data class SmartCastInfo(val dataFlowValue: DataFlowValue, val possibleTypes: Set<KotlinType>)
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
|
||||
internal class KnownResultProcessor<C>(
|
||||
result: Collection<C>
|
||||
): ScopeTowerProcessor<C> {
|
||||
var candidates = result
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun getCandidatesGroups() = listOfNotNull(candidates.check { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
internal class CompositeScopeTowerProcessor<C>(
|
||||
vararg val processors: ScopeTowerProcessor<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) = processors.forEach { it.processTowerLevel(level) }
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
= processors.forEach { it.processImplicitReceiver(implicitReceiver) }
|
||||
|
||||
override fun getCandidatesGroups(): List<Collection<C>> = processors.flatMap { it.getCandidatesGroups() }
|
||||
}
|
||||
|
||||
internal abstract class AbstractScopeTowerProcessor<C>(
|
||||
val context: TowerContext<C>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
protected val name: Name get() = context.name
|
||||
|
||||
protected abstract var candidates: Collection<C>
|
||||
|
||||
override fun getCandidatesGroups() = listOfNotNull(candidates.check { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val explicitReceiver: ReceiverValue,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates = resolveAsMember()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
candidates = resolveAsExtension(level)
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
// no candidates, because we already have receiver
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
private fun resolveAsMember(): Collection<C> {
|
||||
val members = ReceiverScopeTowerLevel(context.scopeTower, explicitReceiver).collectCandidates(name).filter { !it.requiresExtensionReceiver }
|
||||
return members.map { context.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) }
|
||||
}
|
||||
|
||||
private fun resolveAsExtension(level: ScopeTowerLevel): Collection<C> {
|
||||
val extensions = level.collectCandidates(name).filter { it.requiresExtensionReceiver }
|
||||
return extensions.map { context.createCandidate(it, ExplicitReceiverKind.EXTENSION_RECEIVER, extensionReceiver = explicitReceiver) }
|
||||
}
|
||||
}
|
||||
|
||||
private class QualifierScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val qualifier: QualifierReceiver,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
): AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates = resolve()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
// no candidates, because we done all already
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
// no candidates, because we done all already
|
||||
candidates = emptyList()
|
||||
}
|
||||
|
||||
private fun resolve(): Collection<C> {
|
||||
val staticMembers = QualifierScopeTowerLevel(context.scopeTower, qualifier).collectCandidates(name)
|
||||
.filter { !it.requiresExtensionReceiver }
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
|
||||
return staticMembers
|
||||
}
|
||||
}
|
||||
|
||||
private class NoExplicitReceiverScopeTowerProcessor<C>(
|
||||
context: TowerContext<C>,
|
||||
val collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
) : AbstractScopeTowerProcessor<C>(context) {
|
||||
override var candidates: Collection<C> = emptyList()
|
||||
|
||||
private var descriptorsRequestImplicitReceiver = emptyList<CandidateWithBoundDispatchReceiver<*>>()
|
||||
|
||||
override fun processTowerLevel(level: ScopeTowerLevel) {
|
||||
val descriptors = level.collectCandidates(name)
|
||||
|
||||
descriptorsRequestImplicitReceiver = descriptors.filter { it.requiresExtensionReceiver }
|
||||
|
||||
candidates = descriptors.filter { !it.requiresExtensionReceiver }
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = null) }
|
||||
}
|
||||
|
||||
override fun processImplicitReceiver(implicitReceiver: ReceiverValue) {
|
||||
candidates = descriptorsRequestImplicitReceiver
|
||||
.map { context.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, extensionReceiver = implicitReceiver) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun <C> createSimpleProcessor(
|
||||
context: TowerContext<C>,
|
||||
explicitReceiver: Receiver?,
|
||||
collectCandidates: ScopeTowerLevel.(Name) -> Collection<CandidateWithBoundDispatchReceiver<*>>
|
||||
) : ScopeTowerProcessor<C> {
|
||||
if (explicitReceiver is ReceiverValue) {
|
||||
return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates)
|
||||
}
|
||||
else if (explicitReceiver is QualifierReceiver) {
|
||||
val qualifierProcessor = QualifierScopeTowerProcessor(context, explicitReceiver, collectCandidates)
|
||||
|
||||
// todo enum entry, object.
|
||||
val classValue = (explicitReceiver as? ClassQualifier)?.classValueReceiver ?: return qualifierProcessor
|
||||
return CompositeScopeTowerProcessor(
|
||||
qualifierProcessor,
|
||||
ExplicitReceiverScopeTowerProcessor(context, classValue, collectCandidates)
|
||||
)
|
||||
}
|
||||
else {
|
||||
assert(explicitReceiver == null) {
|
||||
"Illegal explicit receiver: $explicitReceiver(${explicitReceiver!!.javaClass.simpleName})"
|
||||
}
|
||||
return NoExplicitReceiverScopeTowerProcessor(context, collectCandidates)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <C> createVariableProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
|
||||
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables)
|
||||
|
||||
internal fun <C> createFunctionProcessor(context: TowerContext<C>, explicitReceiver: Receiver?)
|
||||
= createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions)
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
|
||||
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.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
internal abstract class AbstractScopeTowerLevel(
|
||||
protected val scopeTower: ScopeTower
|
||||
): ScopeTowerLevel {
|
||||
protected val location: LookupLocation get() = scopeTower.location
|
||||
|
||||
protected fun <D : CallableDescriptor> createCandidateDescriptor(
|
||||
descriptor: D,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
specialError: ResolutionDiagnostic? = null,
|
||||
dispatchReceiverSmartCastType: KotlinType? = null
|
||||
): CandidateWithBoundDispatchReceiver<D> {
|
||||
val diagnostics = SmartList<ResolutionDiagnostic>()
|
||||
diagnostics.addIfNotNull(specialError)
|
||||
|
||||
if (ErrorUtils.isError(descriptor)) diagnostics.add(ErrorDescriptorDiagnostic)
|
||||
if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic)
|
||||
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
|
||||
|
||||
Visibilities.findInvisibleMember(
|
||||
dispatchReceiver ?: ReceiverValue.NO_RECEIVER, descriptor,
|
||||
scopeTower.lexicalScope.ownerDescriptor
|
||||
)?.let { diagnostics.add(VisibilityError(it)) }
|
||||
|
||||
return CandidateWithBoundDispatchReceiverImpl(dispatchReceiver, descriptor, diagnostics)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// todo create error for constructors call and for implicit receiver
|
||||
// todo KT-9538 Unresolved inner class via subclass reference
|
||||
// todo Future plan: move constructors and fake variables for objects to class member scope.
|
||||
internal abstract class ConstructorsAndFakeVariableHackLevelScope(scopeTower: ScopeTower) : AbstractScopeTowerLevel(scopeTower) {
|
||||
|
||||
protected fun createConstructors(
|
||||
classifier: ClassifierDescriptor?,
|
||||
dispatchReceiver: ReceiverValue?,
|
||||
dispatchReceiverSmartCastType: KotlinType? = null,
|
||||
checkClass: (ClassDescriptor) -> ResolutionDiagnostic? = { null }
|
||||
): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
|
||||
val classDescriptor = getClassWithConstructors(classifier) ?: return emptyList()
|
||||
|
||||
val specialError = checkClass(classDescriptor)
|
||||
return classDescriptor.constructors.map {
|
||||
|
||||
val dispatchReceiverHack = if (dispatchReceiver == null && it.dispatchReceiverParameter != null) {
|
||||
it.dispatchReceiverParameter?.value // todo this is hack for Scope Level
|
||||
}
|
||||
else if (dispatchReceiver != null && it.dispatchReceiverParameter == null) { // should be reported error
|
||||
null
|
||||
}
|
||||
else {
|
||||
dispatchReceiver
|
||||
}
|
||||
|
||||
createCandidateDescriptor(it, dispatchReceiverHack, specialError, dispatchReceiverSmartCastType)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun createVariableDescriptor(
|
||||
classifier: ClassifierDescriptor?,
|
||||
dispatchReceiverSmartCastType: KotlinType? = null,
|
||||
checkClass: (ClassDescriptor) -> ResolutionDiagnostic? = { null }
|
||||
): CandidateWithBoundDispatchReceiver<VariableDescriptor>? {
|
||||
val fakeVariable = getFakeDescriptorForObject(classifier) ?: return null
|
||||
return createCandidateDescriptor(fakeVariable, null, checkClass(fakeVariable.classDescriptor), dispatchReceiverSmartCastType)
|
||||
}
|
||||
|
||||
|
||||
private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? {
|
||||
if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier)
|
||||
// Constructors of singletons shouldn't be callable from the code
|
||||
|| classifier.kind.isSingleton) {
|
||||
return null
|
||||
}
|
||||
else {
|
||||
return classifier
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? {
|
||||
if (classifier !is ClassDescriptor || !classifier.hasClassValueDescriptor) return null // todo
|
||||
|
||||
return FakeCallableDescriptorForObject(classifier)
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReceiverScopeTowerLevel(
|
||||
scopeTower: ScopeTower,
|
||||
val dispatchReceiver: ReceiverValue
|
||||
): ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
|
||||
private val memberScope = dispatchReceiver.type.memberScope
|
||||
|
||||
private fun <D: CallableDescriptor> collectMembers(
|
||||
members: ResolutionScope.() -> Collection<D>,
|
||||
additionalDescriptors: ResolutionScope.(smartCastType: KotlinType?) -> Collection<CandidateWithBoundDispatchReceiver<D>> // todo
|
||||
): Collection<CandidateWithBoundDispatchReceiver<D>> {
|
||||
val result = ArrayList<CandidateWithBoundDispatchReceiver<D>>(0)
|
||||
memberScope.members().mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver)
|
||||
}
|
||||
result.addAll(memberScope.additionalDescriptors(null))
|
||||
|
||||
val smartCastPossibleTypes = scopeTower.dataFlowInfo.getSmartCastTypes(dispatchReceiver)
|
||||
val unstableError = if (scopeTower.dataFlowInfo.isStableReceiver(dispatchReceiver)) null else UnstableSmartCastDiagnostic
|
||||
|
||||
for (possibleType in smartCastPossibleTypes) {
|
||||
possibleType.memberScope.members().mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver, unstableError, dispatchReceiverSmartCastType = possibleType)
|
||||
}
|
||||
|
||||
possibleType.memberScope.additionalDescriptors(possibleType).mapTo(result) {
|
||||
it.addDiagnostic(unstableError)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// todo add static methods & fields with error
|
||||
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
|
||||
return collectMembers({ getContributedVariables(name, location) }) {
|
||||
smartCastType ->
|
||||
listOfNotNull(createVariableDescriptor(getContributedClassifier(name, location), smartCastType){ NestedClassViaInstanceReference(it) } )
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
|
||||
return collectMembers({ getContributedFunctions(name, location) }) {
|
||||
smartCastType ->
|
||||
createConstructors(getContributedClassifier(name, location), dispatchReceiver, smartCastType) {
|
||||
if (it.isInner) null else NestedClassViaInstanceReference(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, qualifier: QualifierReceiver) : ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
|
||||
private val qualifierScope = qualifier.getNestedClassesAndPackageMembersScope()
|
||||
|
||||
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
|
||||
val result = ArrayList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>(0)
|
||||
qualifierScope.getContributedVariables(name, location).mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
result.addIfNotNull(createVariableDescriptor(qualifierScope.getContributedClassifier(name, location)))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
|
||||
val functions = qualifierScope.getContributedFunctions(name, location).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
val constructors = createConstructors(qualifierScope.getContributedClassifier(name, location), dispatchReceiver = null) {
|
||||
if (it.isInner) InnerClassViaStaticReference(it) else null
|
||||
}
|
||||
return functions + constructors
|
||||
}
|
||||
}
|
||||
|
||||
internal open class ScopeBasedTowerLevel protected constructor(
|
||||
scopeTower: ScopeTower,
|
||||
private val resolutionScope: ResolutionScope
|
||||
) : ConstructorsAndFakeVariableHackLevelScope(scopeTower) {
|
||||
|
||||
internal constructor(scopeTower: ScopeTower, lexicalScope: LexicalScope): this(scopeTower, lexicalScope as ResolutionScope)
|
||||
|
||||
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
|
||||
val result = ArrayList<CandidateWithBoundDispatchReceiver<VariableDescriptor>>(0)
|
||||
resolutionScope.getContributedVariables(name, location).mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
result.addIfNotNull(createVariableDescriptor(resolutionScope.getContributedClassifier(name, location)))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
|
||||
val result = ArrayList<CandidateWithBoundDispatchReceiver<FunctionDescriptor>>(0)
|
||||
resolutionScope.getContributedFunctions(name, location).mapTo(result) {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
|
||||
// todo report errors for constructors if there is no match receiver
|
||||
result.addAll(createConstructors(resolutionScope.getContributedClassifier(name, location), dispatchReceiver = null) {
|
||||
if (!it.isInner) return@createConstructors null
|
||||
|
||||
// todo add constructors functions to member class member scope
|
||||
// KT-3335 Creating imported super class' inner class fails in codegen
|
||||
UnsupportedInnerClassCall("Constructor call for inner class from subclass unsupported")
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
internal class ImportingScopeBasedTowerLevel(
|
||||
scopeTower: ScopeTower,
|
||||
private val importingScope: ImportingScope,
|
||||
private val receiversForSyntheticExtensions: Collection<KotlinType>
|
||||
): ScopeBasedTowerLevel(scopeTower, importingScope) {
|
||||
|
||||
override fun getVariables(name: Name): Collection<CandidateWithBoundDispatchReceiver<VariableDescriptor>> {
|
||||
val synthetic = importingScope.getContributedSyntheticExtensionProperties(receiversForSyntheticExtensions, name, location).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
return super.getVariables(name) + synthetic
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<CandidateWithBoundDispatchReceiver<FunctionDescriptor>> {
|
||||
val synthetic = importingScope.getContributedSyntheticExtensionFunctions(receiversForSyntheticExtensions, name, location).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
return super.getFunctions(name) + synthetic
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
interface TowerContext<C> {
|
||||
val name: Name
|
||||
val scopeTower: ScopeTower
|
||||
|
||||
fun createCandidate(
|
||||
towerCandidate: CandidateWithBoundDispatchReceiver<*>,
|
||||
explicitReceiverKind: ExplicitReceiverKind,
|
||||
extensionReceiver: ReceiverValue?
|
||||
): C
|
||||
|
||||
fun getStatus(candidate: C): ResolutionCandidateStatus
|
||||
|
||||
fun transformCandidate(variable: C, invoke: C): C
|
||||
|
||||
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<C>
|
||||
|
||||
// foo() -> ReceiverValue(foo), context for invoke
|
||||
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>
|
||||
}
|
||||
|
||||
internal interface ScopeTowerProcessor<C> {
|
||||
|
||||
fun processTowerLevel(level: ScopeTowerLevel)
|
||||
fun processImplicitReceiver(implicitReceiver: ReceiverValue)
|
||||
|
||||
// Candidates with matched receivers (dispatch receiver was already matched in ScopeTowerLevel)
|
||||
// Candidates in one groups have same priority, first group has highest priority.
|
||||
fun getCandidatesGroups(): List<Collection<C>>
|
||||
}
|
||||
|
||||
class TowerResolver {
|
||||
internal fun <C> runResolve(
|
||||
context: TowerContext<C>,
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
useOrder: Boolean = true
|
||||
): Collection<C> {
|
||||
|
||||
val resultCollector = ResultCollector<C> { context.getStatus(it) }
|
||||
|
||||
fun collectCandidates(action: ScopeTowerProcessor<C>.() -> Unit): Collection<C>? {
|
||||
processor.action()
|
||||
val candidatesGroups = if (useOrder) {
|
||||
processor.getCandidatesGroups()
|
||||
}
|
||||
else {
|
||||
listOf(processor.getCandidatesGroups().flatMap { it })
|
||||
}
|
||||
|
||||
for (candidatesGroup in candidatesGroups) {
|
||||
resultCollector.pushCandidates(candidatesGroup)
|
||||
resultCollector.getResolved()?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// possible there is explicit member
|
||||
collectCandidates { /* do nothing */ }?.let { return it }
|
||||
|
||||
for (level in context.scopeTower.levels) {
|
||||
collectCandidates { processTowerLevel(level) }?.let { return it }
|
||||
|
||||
for (implicitReceiver in context.scopeTower.implicitReceivers) {
|
||||
collectCandidates { processImplicitReceiver(implicitReceiver) }?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
return resultCollector.getFinalCandidates()
|
||||
}
|
||||
|
||||
|
||||
//todo collect all candidates
|
||||
internal class ResultCollector<C>(private val getStatus: (C) -> ResolutionCandidateStatus) {
|
||||
private var currentCandidates: Collection<C> = emptyList()
|
||||
private var currentLevel: ResolutionCandidateApplicability? = null
|
||||
|
||||
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
|
||||
|
||||
fun getSyntheticResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
|
||||
|
||||
fun getErrors() = currentCandidates.check {
|
||||
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
|
||||
}
|
||||
|
||||
fun getFinalCandidates() = getResolved() ?: getSyntheticResolved() ?: getErrors() ?: emptyList()
|
||||
|
||||
fun pushCandidates(candidates: Collection<C>) {
|
||||
if (candidates.isEmpty()) return
|
||||
val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!!
|
||||
if (currentLevel == null || currentLevel!! > minimalLevel) {
|
||||
currentLevel = minimalLevel
|
||||
currentCandidates = candidates.filter { getStatus(it).resultingApplicability == minimalLevel }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
|
||||
internal fun <D : CallableDescriptor> CandidateWithBoundDispatchReceiver<D>.addDiagnostic(error: ResolutionDiagnostic?): CandidateWithBoundDispatchReceiver<D> {
|
||||
if (error == null) return this
|
||||
return CandidateWithBoundDispatchReceiverImpl(dispatchReceiver, descriptor, diagnostics + error)
|
||||
}
|
||||
|
||||
@Deprecated("Temporary error")
|
||||
internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel)
|
||||
|
||||
@Deprecated("Temporary error")
|
||||
internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResolutionError? {
|
||||
val level = when (status) {
|
||||
ResolutionStatus.SUCCESS, ResolutionStatus.INCOMPLETE_TYPE_INFERENCE -> return null
|
||||
ResolutionStatus.UNSAFE_CALL_ERROR -> ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR
|
||||
else -> ResolutionCandidateApplicability.INAPPLICABLE
|
||||
}
|
||||
return PreviousResolutionError(level)
|
||||
}
|
||||
|
||||
internal val ResolutionCandidateApplicability.isSuccess: Boolean
|
||||
get() = this == ResolutionCandidateApplicability.RESOLVED || this == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
|
||||
|
||||
internal val CallableDescriptor.isSynthesized: Boolean // todo dynamics calls
|
||||
get() = (this is CallableMemberDescriptor && isOrOverridesSynthesized(this))
|
||||
|| hasLowPriorityInOverloadResolution()
|
||||
|
||||
internal val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean
|
||||
get() = descriptor.extensionReceiverParameter != null
|
||||
|
||||
internal fun DataFlowDecorator.getAllPossibleTypes(receiver: ReceiverValue) = getSmartCastTypes(receiver) + receiver.type
|
||||
@@ -91,7 +91,7 @@ class ClassifierQualifierWithEmptyScope(
|
||||
class ClassQualifier(
|
||||
referenceExpression: KtSimpleNameExpression,
|
||||
override val classifier: ClassDescriptor,
|
||||
val companionObjectReceiver: ReceiverValue?
|
||||
val classValueReceiver: ReceiverValue?
|
||||
) : ClassifierQualifier(referenceExpression) {
|
||||
|
||||
override val scope: MemberScope get() {
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class A(val foo: Int)
|
||||
|
||||
fun A.test(foo: String) {
|
||||
val <!UNUSED_VARIABLE!>a<!>: String = foo
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun A.test(/*0*/ foo: kotlin.String): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A(/*0*/ foo: kotlin.Int)
|
||||
public final val foo: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -13533,6 +13533,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implicitReceiverMemberVsParameter.kt")
|
||||
public void testImplicitReceiverMemberVsParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/implicitReceiverMemberVsParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initializerScopeOfExtensionProperty.kt")
|
||||
public void testInitializerScopeOfExtensionProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/initializerScopeOfExtensionProperty.kt");
|
||||
|
||||
Reference in New Issue
Block a user