Revert "[FE 1.0] Get rid of NewResolutionOldInference"

This reverts commit 34a05105ef.
This commit is contained in:
Mikhail Glukhikh
2022-09-12 11:24:33 +02:00
committed by Space
parent e36091b926
commit b12dffa593
7 changed files with 732 additions and 95 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallKind;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInferenceKt;
import org.jetbrains.kotlin.resolve.calls.util.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession;
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.tasks.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference;
import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
@@ -115,7 +117,9 @@ public class CallResolver {
assert calleeExpression instanceof KtSimpleNameExpression;
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) calleeExpression;
Name referencedName = nameExpression.getReferencedNameAsName();
return computeTasksAndResolveCall(context, referencedName, nameExpression, KotlinCallKind.VARIABLE);
return computeTasksAndResolveCall(
context, referencedName, nameExpression,
NewResolutionOldInference.ResolutionKind.Variable.INSTANCE);
}
@NotNull
@@ -124,8 +128,8 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context
) {
return computeTasksAndResolveCall(
context, nameExpression.getReferencedNameAsName(), nameExpression, KotlinCallKind.CALLABLE_REFERENCE
);
context, nameExpression.getReferencedNameAsName(), nameExpression,
NewResolutionOldInference.ResolutionKind.CallableReference.INSTANCE);
}
@NotNull
@@ -136,7 +140,9 @@ public class CallResolver {
@NotNull Name name
) {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
return computeTasksAndResolveCall(callResolutionContext, name, functionReference, KotlinCallKind.FUNCTION);
return computeTasksAndResolveCall(
callResolutionContext, name, functionReference,
NewResolutionOldInference.ResolutionKind.Function.INSTANCE);
}
@NotNull
@@ -147,7 +153,7 @@ public class CallResolver {
@NotNull TracingStrategy tracing
) {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
return computeTasksAndResolveCall(callResolutionContext, name, tracing, KotlinCallKind.FUNCTION);
return computeTasksAndResolveCall(callResolutionContext, name, tracing, NewResolutionOldInference.ResolutionKind.Function.INSTANCE);
}
@NotNull
@@ -155,7 +161,9 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context,
@NotNull TracingStrategy tracing
) {
return computeTasksAndResolveCall(context, OperatorNameConventions.INVOKE, tracing, KotlinCallKind.INVOKE);
return computeTasksAndResolveCall(
context, OperatorNameConventions.INVOKE, tracing,
NewResolutionOldInference.ResolutionKind.Invoke.INSTANCE);
}
// this declaration is used by compiler plugins
@@ -165,7 +173,7 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context,
@NotNull Name name,
@NotNull KtReferenceExpression referenceExpression,
@NotNull KotlinCallKind kind
@NotNull NewResolutionOldInference.ResolutionKind kind
) {
TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
return computeTasksAndResolveCall(context, name, tracing, kind);
@@ -178,7 +186,7 @@ public class CallResolver {
@NotNull BasicCallResolutionContext context,
@NotNull Name name,
@NotNull TracingStrategy tracing,
@NotNull KotlinCallKind kind
@NotNull NewResolutionOldInference.ResolutionKind kind
) {
return callResolvePerfCounter.<OverloadResolutionResults<D>>time(() -> {
ResolutionTask<D> resolutionTask = new ResolutionTask<>(kind, name);
@@ -239,7 +247,7 @@ public class CallResolver {
TracingStrategy.EMPTY,
KotlinCallKind.VARIABLE,
null,
dispatchReceiver != null ? CallResolverUtilKt.transformToReceiverWithSmartCastInfo(context, dispatchReceiver) : null
dispatchReceiver != null ? NewResolutionOldInferenceKt.transformToReceiverWithSmartCastInfo(context, dispatchReceiver) : null
);
}
@@ -253,7 +261,7 @@ public class CallResolver {
) {
TracingStrategy tracingStrategy = TracingStrategyImpl.create(expression, call);
ReceiverValueWithSmartCastInfo dispatchReceiverValue =
CallResolverUtilKt.transformToReceiverWithSmartCastInfo(context, receiver);
NewResolutionOldInferenceKt.transformToReceiverWithSmartCastInfo(context, receiver);
return resolveCallWithGivenDescriptors(
context, call, functionDescriptors, tracingStrategy, null, null, dispatchReceiverValue
);
@@ -318,13 +326,17 @@ public class CallResolver {
if (callType == Call.CallType.ARRAY_GET_METHOD || callType == Call.CallType.ARRAY_SET_METHOD) {
Name name = callType == Call.CallType.ARRAY_GET_METHOD ? OperatorNameConventions.GET : OperatorNameConventions.SET;
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) context.call.getCallElement();
return computeTasksAndResolveCall(context, name, arrayAccessExpression, KotlinCallKind.FUNCTION);
return computeTasksAndResolveCall(
context, name, arrayAccessExpression,
NewResolutionOldInference.ResolutionKind.Function.INSTANCE);
}
KtExpression calleeExpression = context.call.getCalleeExpression();
if (calleeExpression instanceof KtSimpleNameExpression) {
KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression;
return computeTasksAndResolveCall(context, expression.getReferencedNameAsName(), expression, KotlinCallKind.FUNCTION);
return computeTasksAndResolveCall(
context, expression.getReferencedNameAsName(), expression,
NewResolutionOldInference.ResolutionKind.Function.INSTANCE);
}
else if (calleeExpression instanceof KtConstructorCalleeExpression) {
return (OverloadResolutionResults) resolveConstructorCall(context, (KtConstructorCalleeExpression) calleeExpression);
@@ -545,7 +557,7 @@ public class CallResolver {
Call call = context.call;
tracing.bindCall(context.trace, call);
KotlinCallKind resolutionKind = resolutionTask.resolutionKind;
NewResolutionOldInference.ResolutionKind resolutionKind = resolutionTask.resolutionKind;
assert resolutionTask.name != null;
BindingContextUtilsKt.recordScope(context.trace, context.scope, context.call.getCalleeExpression());
@@ -563,9 +575,12 @@ public class CallResolver {
@Nullable
final Name name;
@NotNull
final KotlinCallKind resolutionKind;
final NewResolutionOldInference.ResolutionKind resolutionKind;
private ResolutionTask(@NotNull KotlinCallKind kind, @Nullable Name name) {
private ResolutionTask(
@NotNull NewResolutionOldInference.ResolutionKind kind,
@Nullable Name name
) {
this.name = name;
resolutionKind = kind;
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -37,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.util.isCallWithSuperReceiver
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeIntersector
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.DiagnosticReporterByTrackingStrategy
import org.jetbrains.kotlin.resolve.calls.util.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.isFakeElement
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
@@ -26,7 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.util.*
import org.jetbrains.kotlin.resolve.calls.util.makeNullableTypeIfSafeReceiver
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.transformToReceiverWithSmartCastInfo
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.error.ErrorTypeKind
@@ -0,0 +1,678 @@
/*
* Copyright 2010-2017 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.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
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.context.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.tasks.*
import org.jetbrains.kotlin.resolve.calls.util.*
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.resolve.scopes.utils.canBeResolvedWithoutDeprecation
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.TypeApproximator
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
import org.jetbrains.kotlin.utils.sure
class NewResolutionOldInference(
private val towerResolver: TowerResolver,
private val resolutionResultsHandler: ResolutionResultsHandler,
private val dynamicCallableDescriptors: DynamicCallableDescriptors,
private val syntheticScopes: SyntheticScopes,
private val languageVersionSettings: LanguageVersionSettings,
private val deprecationResolver: DeprecationResolver,
private val typeApproximator: TypeApproximator,
private val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
private val callResolver: CallResolver,
private val candidateInterceptor: CandidateInterceptor
) {
sealed class ResolutionKind {
abstract internal fun createTowerProcessor(
outer: NewResolutionOldInference,
name: Name,
tracing: TracingStrategy,
scopeTower: ImplicitScopeTower,
explicitReceiver: DetailedReceiver?,
context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate>
object Function : ResolutionKind() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate> {
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
return createFunctionProcessor(
scopeTower,
name,
functionFactory,
outer.CandidateFactoryProviderForInvokeImpl(functionFactory),
explicitReceiver
)
}
}
object Variable : ResolutionKind() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate> {
val variableFactory = outer.CandidateFactoryImpl(name, context, tracing)
return createVariableAndObjectProcessor(scopeTower, name, variableFactory, explicitReceiver)
}
}
object CallableReference : ResolutionKind() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate> {
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
val variableFactory = outer.CandidateFactoryImpl(name, context, tracing)
return PrioritizedCompositeScopeTowerProcessor(
createSimpleFunctionProcessor(scopeTower, name, functionFactory, explicitReceiver, classValueReceiver = false),
createVariableProcessor(scopeTower, name, variableFactory, explicitReceiver, classValueReceiver = false)
)
}
}
object Invoke : ResolutionKind() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate> {
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
// todo
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
}
return createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
createCallTowerProcessorForExplicitInvoke(
scopeTower,
functionFactory,
context.transformToReceiverWithSmartCastInfo(call.dispatchReceiver),
it
)
}
}
}
class GivenCandidates : ResolutionKind() {
override fun createTowerProcessor(
outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy,
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
): ScopeTowerProcessor<MyCandidate> {
throw IllegalStateException("Should be not called")
}
}
}
fun <D : CallableDescriptor> runResolution(
context: BasicCallResolutionContext,
name: Name,
kind: ResolutionKind,
tracing: TracingStrategy
): OverloadResolutionResultsImpl<D> {
val explicitReceiver = context.call.explicitReceiver
val detailedReceiver = if (explicitReceiver is QualifierReceiver?) {
explicitReceiver
} else {
context.transformToReceiverWithSmartCastInfo(explicitReceiver as ReceiverValue)
}
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
val scopeTower = ImplicitScopeTowerImpl(
context, dynamicScope, syntheticScopes, context.call.createLookupLocation(), typeApproximator, implicitsResolutionFilter, callResolver, candidateInterceptor
)
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
val isBinaryRemOperator = isBinaryRemOperator(context.call)
val nameToResolve = if (isBinaryRemOperator && !shouldUseOperatorRem)
OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]!!
else
name
val processor = kind.createTowerProcessor(this, nameToResolve, tracing, scopeTower, detailedReceiver, context)
if (context.collectAllCandidates) {
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor, nameToResolve))
}
var candidates =
towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference, name = nameToResolve)
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
candidates.all { it.resultingApplicability.isInapplicable }
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
val processorForDeprecatedName =
kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
candidates = towerResolver.runResolve(
scopeTower,
processorForDeprecatedName,
useOrder = kind != ResolutionKind.CallableReference,
name = deprecatedName
)
}
if (candidates.isEmpty()) {
if (reportAdditionalDiagnosticIfNoCandidates(context, nameToResolve, kind, scopeTower, detailedReceiver)) {
return OverloadResolutionResultsImpl.nameNotFound()
}
}
val overloadResults = convertToOverloadResults<D>(candidates, tracing, context)
return overloadResults
}
fun <D : CallableDescriptor> runResolutionForGivenCandidates(
basicCallContext: BasicCallResolutionContext,
tracing: TracingStrategy,
candidates: Collection<OldResolutionCandidate<D>>
): OverloadResolutionResultsImpl<D> {
val resolvedCandidates = candidates.map { candidate ->
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments)
if (deprecationResolver.isHiddenInResolution(
candidate.descriptor, basicCallContext.call, basicCallContext.trace.bindingContext, basicCallContext.isSuperCall
)
) {
return@map MyCandidate(listOf(HiddenDescriptor), resolvedCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
resolvedCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
CandidateResolveMode.EXIT_ON_FIRST_ERROR
)
val diagnostics = listOfNotNull(createPreviousResolveError(resolvedCall.status))
MyCandidate(diagnostics, resolvedCall) {
resolvedCall.performRemainingTasks()
listOfNotNull(createPreviousResolveError(resolvedCall.status))
}
}
if (basicCallContext.collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolvedCandidates),
TowerResolver.AllCandidatesCollector(), useOrder = false
)
return allCandidatesResult(allCandidates)
}
val processedCandidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolvedCandidates),
TowerResolver.SuccessfulResultCollector(), useOrder = true
)
return convertToOverloadResults(processedCandidates, tracing, basicCallContext)
}
private fun <D : CallableDescriptor> allCandidatesResult(allCandidates: Collection<MyCandidate>) =
OverloadResolutionResultsImpl.nameNotFound<D>().apply {
this.allCandidates = allCandidates.map {
@Suppress("UNCHECKED_CAST")
it.resolvedCall as MutableResolvedCall<D>
}
}
private fun <D : CallableDescriptor> convertToOverloadResults(
candidates: Collection<MyCandidate>,
tracing: TracingStrategy,
basicCallContext: BasicCallResolutionContext
): OverloadResolutionResultsImpl<D> {
val resolvedCalls = candidates.map {
val (diagnostics, 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 diagnostics) {
when (error) {
is UnsupportedInnerClassCall -> resolvedCall.trace.report(
Errors.UNSUPPORTED.on(
resolvedCall.call.callElement,
error.message
)
)
is NestedClassViaInstanceReference -> tracing.nestedClassAccessViaInstanceReference(
resolvedCall.trace,
error.classDescriptor,
resolvedCall.explicitReceiverKind
)
is ErrorDescriptorDiagnostic -> {
// todo
// return@map null
}
is ResolvedUsingDeprecatedVisibility -> {
reportResolvedUsingDeprecatedVisibility(
resolvedCall.call, resolvedCall.candidateDescriptor,
resolvedCall.resultingDescriptor, error, resolvedCall.trace
)
}
}
}
}
@Suppress("UNCHECKED_CAST")
resolvedCall as MutableResolvedCall<D>
}
return resolutionResultsHandler.computeResultAndReportErrors(basicCallContext, tracing, resolvedCalls, languageVersionSettings)
}
// true if we found something
private fun reportAdditionalDiagnosticIfNoCandidates(
context: BasicCallResolutionContext,
name: Name,
kind: ResolutionKind,
scopeTower: ImplicitScopeTower,
detailedReceiver: DetailedReceiver?
): Boolean {
val reference = context.call.calleeExpression as? KtReferenceExpression ?: return false
val errorCandidates = when (kind) {
ResolutionKind.Function -> collectErrorCandidatesForFunction(scopeTower, name, detailedReceiver)
ResolutionKind.Variable -> collectErrorCandidatesForVariable(scopeTower, name, detailedReceiver)
else -> emptyList()
}
val candidate = errorCandidates.firstOrNull() as? ErrorCandidate.Classifier ?: return false
context.trace.record(BindingContext.REFERENCE_TARGET, reference, candidate.descriptor)
context.trace.report(Errors.RESOLUTION_TO_CLASSIFIER.on(reference, candidate.descriptor, candidate.kind, candidate.errorMessage))
return true
}
public class ImplicitScopeTowerImpl(
val resolutionContext: BasicCallResolutionContext,
override val dynamicScope: MemberScope,
override val syntheticScopes: SyntheticScopes,
override val location: LookupLocation,
override val typeApproximator: TypeApproximator,
override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
val callResolver: CallResolver,
val candidateInterceptor: CandidateInterceptor
) : ImplicitScopeTower {
private val cache = HashMap<ReceiverValue, ReceiverValueWithSmartCastInfo>()
override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? =
scope.implicitReceiver?.value?.let {
cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) }
}
override fun getContextReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> =
scope.contextReceiversGroup.map { cache.getOrPut(it.value) { resolutionContext.transformToReceiverWithSmartCastInfo(it.value) } }
override fun getNameForGivenImportAlias(name: Name): Name? =
(resolutionContext.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name)
override val lexicalScope: LexicalScope get() = resolutionContext.scope
override val isDebuggerContext: Boolean get() = resolutionContext.isDebuggerContext
override val isNewInferenceEnabled: Boolean
get() = resolutionContext.languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
override val areContextReceiversEnabled: Boolean
get() = resolutionContext.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)
override val languageVersionSettings: LanguageVersionSettings
get() = resolutionContext.languageVersionSettings
override fun interceptFunctionCandidates(
resolutionScope: ResolutionScope,
name: Name,
initialResults: Collection<FunctionDescriptor>,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<FunctionDescriptor> {
return candidateInterceptor.interceptFunctionCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location)
}
override fun interceptVariableCandidates(
resolutionScope: ResolutionScope,
name: Name,
initialResults: Collection<VariableDescriptor>,
location: LookupLocation,
dispatchReceiver: ReceiverValueWithSmartCastInfo?,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<VariableDescriptor> {
return candidateInterceptor.interceptVariableCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location)
}
}
class MyCandidate(
// Diagnostics that are already computed
// if resultingApplicability is successful they must be the same as `diagnostics`,
// otherwise they might be a bit different but result remains unsuccessful
val eagerDiagnostics: List<KotlinCallDiagnostic>,
val resolvedCall: MutableResolvedCall<*>,
finalDiagnosticsComputation: (() -> List<KotlinCallDiagnostic>)? = null
) : Candidate {
val diagnostics: List<KotlinCallDiagnostic> by lazy(LazyThreadSafetyMode.NONE) {
finalDiagnosticsComputation?.invoke() ?: eagerDiagnostics
}
operator fun component1() = diagnostics
operator fun component2() = resolvedCall
override val resultingApplicability: CandidateApplicability by lazy(LazyThreadSafetyMode.NONE) {
getResultApplicability(diagnostics)
}
override fun addCompatibilityWarning(other: Candidate) {
// Only applicable for new inference
}
override val isSuccessful = getResultApplicability(eagerDiagnostics).isSuccess
}
private inner class CandidateFactoryImpl(
val name: Name,
val basicCallContext: BasicCallResolutionContext,
val tracing: TracingStrategy
) : CandidateFactory<MyCandidate> {
override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): MyCandidate {
val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate")
val candidateCall = ResolvedCallImpl(
basicCallContext.call, towerCandidate.descriptor,
towerCandidate.dispatchReceiver?.receiverValue, extensionReceiver?.receiverValue,
explicitReceiverKind, null, candidateTrace, tracing,
basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments
)
/**
* See https://jetbrains.quip.com/qcTDAFcgFLEM
*
* For now we have only 2 functions with dynamic receivers: iterator() and unsafeCast()
* Both this function are marked via @kotlin.internal.DynamicExtension.
*/
if (extensionReceiver != null) {
val parameterIsDynamic = towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()
val argumentIsDynamic = extensionReceiver.receiverValue.type.isDynamic()
if (parameterIsDynamic != argumentIsDynamic ||
(parameterIsDynamic && !towerCandidate.descriptor.hasDynamicExtensionAnnotation())
) {
return MyCandidate(listOf(HiddenExtensionRelatedToDynamicTypes), candidateCall)
}
}
if (deprecationResolver.isHiddenInResolution(
towerCandidate.descriptor, basicCallContext.call, basicCallContext.trace.bindingContext, basicCallContext.isSuperCall
)
) {
return MyCandidate(listOf(HiddenDescriptor), candidateCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
candidateCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
CandidateResolveMode.EXIT_ON_FIRST_ERROR
)
val diagnostics = createDiagnosticsForCandidate(towerCandidate, candidateCall)
return MyCandidate(diagnostics, candidateCall) {
candidateCall.performRemainingTasks()
createDiagnosticsForCandidate(towerCandidate, candidateCall)
}
}
/**
* The function is called only inside [NoExplicitReceiverScopeTowerProcessor] with [TowerData.BothTowerLevelAndContextReceiversGroup].
* This case involves only [SimpleCandidateFactory].
*/
override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
explicitReceiverKind: ExplicitReceiverKind,
extensionReceiverCandidates: List<ReceiverValueWithSmartCastInfo>
): MyCandidate = error("${this::class.simpleName} doesn't support candidates with multiple extension receiver candidates")
override fun createErrorCandidate(): MyCandidate {
throw IllegalStateException("Not supported creating error candidate for the old type inference candidate factory")
}
private fun createDiagnosticsForCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
candidateCall: ResolvedCallImpl<CallableDescriptor>
): List<ResolutionDiagnostic> =
mutableListOf<ResolutionDiagnostic>().apply {
addAll(towerCandidate.diagnostics)
addAll(checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor))
addIfNotNull(createPreviousResolveError(candidateCall.status))
}
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
if (descriptor !is FunctionDescriptor || ErrorUtils.isError(descriptor)) return emptyList()
if (descriptor.name != name && (name == OperatorNameConventions.UNARY_PLUS || name == OperatorNameConventions.UNARY_MINUS)) {
return listOf(DeprecatedUnaryPlusAsPlus)
}
val conventionError = if (isConventionCall(call) && !descriptor.isOperator) InvokeConventionCallNoOperatorModifier else null
val infixError = if (isInfixCall(call) && !descriptor.isInfix) InfixCallNoInfixModifier else null
return listOfNotNull(conventionError, infixError)
}
}
private inner class CandidateFactoryProviderForInvokeImpl(
val functionContext: CandidateFactoryImpl
) : CandidateFactoryProviderForInvoke<MyCandidate> {
override fun transformCandidate(
variable: MyCandidate,
invoke: MyCandidate
): MyCandidate {
@Suppress("UNCHECKED_CAST") val resolvedCallImpl = VariableAsFunctionResolvedCallImpl(
invoke.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
variable.resolvedCall as MutableResolvedCall<VariableDescriptor>
)
assert(variable.resultingApplicability.isSuccess) {
"Variable call must be success: $variable"
}
return MyCandidate(variable.eagerDiagnostics + invoke.eagerDiagnostics, resolvedCallImpl) {
variable.diagnostics + invoke.diagnostics
}
}
override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<MyCandidate> {
val newCall = CallTransformer.stripCallArguments(functionContext.basicCallContext.call).let {
if (stripExplicitReceiver) CallTransformer.stripReceiver(it) else it
}
return CandidateFactoryImpl(
functionContext.name,
functionContext.basicCallContext.replaceCall(newCall),
functionContext.tracing
)
}
override fun factoryForInvoke(
variable: MyCandidate,
useExplicitReceiver: Boolean
): Pair<ReceiverValueWithSmartCastInfo, CandidateFactory<MyCandidate>>? {
assert(variable.resolvedCall.status.possibleTransformToSuccess()) {
"Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " +
"and descriptor: ${variable.resolvedCall.candidateDescriptor}"
}
val calleeExpression = variable.resolvedCall.call.calleeExpression
val variableDescriptor = variable.resolvedCall.resultingDescriptor as VariableDescriptor
assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null) {
"Unexpected variable candidate: $variable"
}
val variableType = variableDescriptor.type
if (variableType is DeferredType && variableType.isComputing) {
return null // todo: create special check that there is no invoke on variable
}
val basicCallContext = functionContext.basicCallContext
val variableReceiver = ExpressionReceiver.create(
calleeExpression!!,
variableType,
basicCallContext.trace.bindingContext
)
// used for smartCasts, see: DataFlowValueFactory.getIdForSimpleNameExpression
functionContext.tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall)
// todo hacks
val functionCall = CallTransformer.CallForImplicitInvoke(
basicCallContext.call.explicitReceiver?.takeIf { useExplicitReceiver },
variableReceiver, basicCallContext.call, true
)
val tracingForInvoke = TracingStrategyForInvoke(calleeExpression, functionCall, variableReceiver.type)
val basicCallResolutionContext = basicCallContext.replaceBindingTrace(variable.resolvedCall.trace)
.replaceCall(functionCall)
.replaceContextDependency(ContextDependency.DEPENDENT) // todo
val newContext = CandidateFactoryImpl(OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke)
return basicCallResolutionContext.transformToReceiverWithSmartCastInfo(variableReceiver) to newContext
}
}
}
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) =
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings, dataFlowValueFactory)
fun transformToReceiverWithSmartCastInfo(
containingDescriptor: DeclarationDescriptor,
bindingContext: BindingContext,
dataFlowInfo: DataFlowInfo,
receiver: ReceiverValue,
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): ReceiverValueWithSmartCastInfo {
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
return ReceiverValueWithSmartCastInfo(
receiver,
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings).compactIfPossible(),
dataFlowValue.isStable
)
}
internal class PreviousResolutionError(candidateLevel: CandidateApplicability) : ResolutionDiagnostic(candidateLevel)
internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResolutionError? {
val level = when (status) {
ResolutionStatus.SUCCESS, ResolutionStatus.INCOMPLETE_TYPE_INFERENCE -> return null
ResolutionStatus.UNSAFE_CALL_ERROR -> CandidateApplicability.UNSAFE_CALL
ResolutionStatus.ARGUMENTS_MAPPING_ERROR -> CandidateApplicability.INAPPLICABLE_ARGUMENTS_MAPPING_ERROR
ResolutionStatus.RECEIVER_TYPE_ERROR -> CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
else -> CandidateApplicability.INAPPLICABLE
}
return PreviousResolutionError(level)
}
internal fun Call.isCallWithSuperReceiver(): Boolean = explicitReceiver is SuperCallReceiverValue
private val BasicCallResolutionContext.isSuperCall: Boolean get() = call.isCallWithSuperReceiver()
internal fun reportResolvedUsingDeprecatedVisibility(
call: Call,
candidateDescriptor: CallableDescriptor,
resultingDescriptor : CallableDescriptor,
diagnostic: ResolvedUsingDeprecatedVisibility,
trace: BindingTrace
) {
trace.record(
BindingContext.DEPRECATED_SHORT_NAME_ACCESS,
call.calleeExpression
)
val descriptorToLookup: DeclarationDescriptor = when (candidateDescriptor) {
is ClassConstructorDescriptor -> candidateDescriptor.containingDeclaration
is FakeCallableDescriptorForObject -> candidateDescriptor.classDescriptor
is SyntheticMemberDescriptor<*> -> candidateDescriptor.baseDescriptorForSynthetic
is PropertyDescriptor, is FunctionDescriptor -> candidateDescriptor
else -> error(
"Unexpected candidate descriptor of resolved call with " +
"ResolvedUsingDeprecatedVisibility-diagnostic: $candidateDescriptor\n" +
"Call context: ${call.callElement.parent?.text}"
)
}
// If this descriptor was resolved from HierarchicalScope, then there can be another, non-deprecated path
// in parents of base scope
val sourceScope = diagnostic.baseSourceScope
val canBeResolvedWithoutDeprecation = if (sourceScope is HierarchicalScope) {
descriptorToLookup.canBeResolvedWithoutDeprecation(
sourceScope,
diagnostic.lookupLocation
)
} else {
// Normally, that should be unreachable, but instead of asserting that, we will report diagnostic
false
}
if (!canBeResolvedWithoutDeprecation) {
trace.report(
Errors.DEPRECATED_ACCESS_BY_SHORT_NAME.on(call.callElement, resultingDescriptor)
)
}
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.contracts.EffectSystem
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandida
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
@@ -48,7 +46,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isUnderscoreNamed
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.resolve.scopes.utils.canBeResolvedWithoutDeprecation
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.expressions.*
@@ -90,14 +87,23 @@ class PSICallResolver(
private val arePartiallySpecifiedTypeArgumentsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.PartiallySpecifiedTypeArguments)
val defaultResolutionKinds = setOf(
NewResolutionOldInference.ResolutionKind.Function,
NewResolutionOldInference.ResolutionKind.Variable,
NewResolutionOldInference.ResolutionKind.Invoke,
NewResolutionOldInference.ResolutionKind.CallableReference
)
fun <D : CallableDescriptor> runResolutionAndInference(
context: BasicCallResolutionContext,
name: Name,
kotlinCallKind: KotlinCallKind,
resolutionKind: NewResolutionOldInference.ResolutionKind,
tracingStrategy: TracingStrategy
): OverloadResolutionResults<D> {
val isBinaryRemOperator = isBinaryRemOperator(context.call)
val refinedName = refineNameForRemOperator(isBinaryRemOperator, name)
val kotlinCallKind = resolutionKind.toKotlinCallKind()
val kotlinCall = toKotlinCall(context, kotlinCallKind, context.call, refinedName, tracingStrategy, isSpecialFunction = false)
val scopeTower = ASTScopeTower(context)
val resolutionCallbacks = createResolutionCallbacks(context)
@@ -582,6 +588,15 @@ class PSICallResolver(
}
}
private fun NewResolutionOldInference.ResolutionKind.toKotlinCallKind(): KotlinCallKind =
when (this) {
is NewResolutionOldInference.ResolutionKind.Function -> KotlinCallKind.FUNCTION
is NewResolutionOldInference.ResolutionKind.Variable -> KotlinCallKind.VARIABLE
is NewResolutionOldInference.ResolutionKind.Invoke -> KotlinCallKind.INVOKE
is NewResolutionOldInference.ResolutionKind.CallableReference -> KotlinCallKind.CALLABLE_REFERENCE
is NewResolutionOldInference.ResolutionKind.GivenCandidates -> KotlinCallKind.UNSUPPORTED
}
private fun toKotlinCall(
context: BasicCallResolutionContext,
kotlinCallKind: KotlinCallKind,
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.psi.*
@@ -34,20 +33,15 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
import org.jetbrains.kotlin.resolve.calls.inference.getNestedTypeVariables
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.isParameterOfAnnotation
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.resolve.scopes.collectSyntheticConstructors
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.resolve.scopes.receivers.SuperCallReceiverValue
import org.jetbrains.kotlin.resolve.scopes.utils.canBeResolvedWithoutDeprecation
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
@@ -59,7 +53,6 @@ import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.util.buildNotFixedVariablesToPossibleResultType
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
enum class ResolveArgumentsMode {
RESOLVE_FUNCTION_ARGUMENTS,
@@ -415,69 +408,3 @@ fun checkForConstructorCallOnFunctionalType(
context.trace.report(factory.on(context.call.getValueArgumentListOrElement()))
}
}
fun transformToReceiverWithSmartCastInfo(
containingDescriptor: DeclarationDescriptor,
bindingContext: BindingContext,
dataFlowInfo: DataFlowInfo,
receiver: ReceiverValue,
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): ReceiverValueWithSmartCastInfo {
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
return ReceiverValueWithSmartCastInfo(
receiver,
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings).compactIfPossible(),
dataFlowValue.isStable
)
}
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) = transformToReceiverWithSmartCastInfo(
scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings, dataFlowValueFactory
)
internal fun Call.isCallWithSuperReceiver(): Boolean = explicitReceiver is SuperCallReceiverValue
internal fun reportResolvedUsingDeprecatedVisibility(
call: Call,
candidateDescriptor: CallableDescriptor,
resultingDescriptor: CallableDescriptor,
diagnostic: ResolvedUsingDeprecatedVisibility,
trace: BindingTrace
) {
trace.record(
BindingContext.DEPRECATED_SHORT_NAME_ACCESS,
call.calleeExpression
)
val descriptorToLookup: DeclarationDescriptor = when (candidateDescriptor) {
is ClassConstructorDescriptor -> candidateDescriptor.containingDeclaration
is FakeCallableDescriptorForObject -> candidateDescriptor.classDescriptor
is SyntheticMemberDescriptor<*> -> candidateDescriptor.baseDescriptorForSynthetic
is PropertyDescriptor, is FunctionDescriptor -> candidateDescriptor
else -> error(
"Unexpected candidate descriptor of resolved call with " +
"ResolvedUsingDeprecatedVisibility-diagnostic: $candidateDescriptor\n" +
"Call context: ${call.callElement.parent?.text}"
)
}
// If this descriptor was resolved from HierarchicalScope, then there can be another, non-deprecated path
// in parents of base scope
val sourceScope = diagnostic.baseSourceScope
val canBeResolvedWithoutDeprecation = if (sourceScope is HierarchicalScope) {
descriptorToLookup.canBeResolvedWithoutDeprecation(
sourceScope,
diagnostic.lookupLocation
)
} else {
// Normally, that should be unreachable, but instead of asserting that, we will report diagnostic
false
}
if (!canBeResolvedWithoutDeprecation) {
trace.report(
Errors.DEPRECATED_ACCESS_BY_SHORT_NAME.on(call.callElement, resultingDescriptor)
)
}
}