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.smartcasts.DataFlowInfo;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.*;
|
import org.jetbrains.kotlin.resolve.calls.tasks.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
|
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.calls.util.CallMaker;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||||
@@ -78,6 +79,7 @@ public class CallResolver {
|
|||||||
private ArgumentTypeResolver argumentTypeResolver;
|
private ArgumentTypeResolver argumentTypeResolver;
|
||||||
private GenericCandidateResolver genericCandidateResolver;
|
private GenericCandidateResolver genericCandidateResolver;
|
||||||
private CallCompleter callCompleter;
|
private CallCompleter callCompleter;
|
||||||
|
private NewResolveOldInference newCallResolver;
|
||||||
private final TaskPrioritizer taskPrioritizer;
|
private final TaskPrioritizer taskPrioritizer;
|
||||||
private final ResolutionResultsHandler resolutionResultsHandler;
|
private final ResolutionResultsHandler resolutionResultsHandler;
|
||||||
@NotNull private KotlinBuiltIns builtIns;
|
@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 callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
|
||||||
private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
|
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(
|
public CallResolver(
|
||||||
@NotNull TaskPrioritizer taskPrioritizer,
|
@NotNull TaskPrioritizer taskPrioritizer,
|
||||||
@NotNull ResolutionResultsHandler resolutionResultsHandler,
|
@NotNull ResolutionResultsHandler resolutionResultsHandler,
|
||||||
@@ -131,6 +135,12 @@ public class CallResolver {
|
|||||||
this.callCompleter = callCompleter;
|
this.callCompleter = callCompleter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// component dependency cycle
|
||||||
|
@Inject
|
||||||
|
public void setCallCompleter(@NotNull NewResolveOldInference newCallResolver) {
|
||||||
|
this.newCallResolver = newCallResolver;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
|
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
|
||||||
KtExpression calleeExpression = context.call.getCalleeExpression();
|
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);
|
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.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
|
|
||||||
public interface VariableAsFunctionResolvedCall {
|
public interface VariableAsFunctionResolvedCall {
|
||||||
public val functionCall: ResolvedCall<FunctionDescriptor>
|
public val functionCall: ResolvedCall<FunctionDescriptor>
|
||||||
@@ -42,6 +43,9 @@ class VariableAsFunctionResolvedCallImpl(
|
|||||||
|
|
||||||
override fun getTrace(): DelegatingBindingTrace {
|
override fun getTrace(): DelegatingBindingTrace {
|
||||||
//functionCall.trace is temporary trace above variableCall.trace and is committed already
|
//functionCall.trace is temporary trace above variableCall.trace and is committed already
|
||||||
|
if (CallResolver.useNewResolve) {
|
||||||
|
return functionCall.trace
|
||||||
|
}
|
||||||
return variableCall.getTrace()
|
return variableCall.getTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -184,7 +184,7 @@ public class ResolutionResultsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||||
@NotNull Set<MutableResolvedCall<D>> candidates,
|
@NotNull Set<MutableResolvedCall<D>> candidates,
|
||||||
boolean discriminateGenerics,
|
boolean discriminateGenerics,
|
||||||
@NotNull CheckArgumentTypesMode checkArgumentsMode
|
@NotNull CheckArgumentTypesMode checkArgumentsMode
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class TaskPrioritizer(
|
|||||||
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
taskPrioritizerContext: TaskPrioritizerContext<D, F>
|
||||||
) {
|
) {
|
||||||
if (qualifier is ClassQualifier) {
|
if (qualifier is ClassQualifier) {
|
||||||
val companionObject = qualifier.companionObjectReceiver ?: return
|
val companionObject = qualifier.classValueReceiver ?: return
|
||||||
val classifierDescriptor = qualifier.classifier
|
val classifierDescriptor = qualifier.classifier
|
||||||
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
|
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
|
||||||
when {
|
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(
|
class ClassQualifier(
|
||||||
referenceExpression: KtSimpleNameExpression,
|
referenceExpression: KtSimpleNameExpression,
|
||||||
override val classifier: ClassDescriptor,
|
override val classifier: ClassDescriptor,
|
||||||
val companionObjectReceiver: ReceiverValue?
|
val classValueReceiver: ReceiverValue?
|
||||||
) : ClassifierQualifier(referenceExpression) {
|
) : ClassifierQualifier(referenceExpression) {
|
||||||
|
|
||||||
override val scope: MemberScope get() {
|
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);
|
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")
|
@TestMetadata("initializerScopeOfExtensionProperty.kt")
|
||||||
public void testInitializerScopeOfExtensionProperty() throws Exception {
|
public void testInitializerScopeOfExtensionProperty() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/initializerScopeOfExtensionProperty.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/scopes/initializerScopeOfExtensionProperty.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user