diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 13732b55c5f..432c0e64bc6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -24,7 +24,6 @@ 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; @@ -35,7 +34,6 @@ 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; @@ -117,9 +115,7 @@ public class CallResolver { assert calleeExpression instanceof KtSimpleNameExpression; KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) calleeExpression; Name referencedName = nameExpression.getReferencedNameAsName(); - return computeTasksAndResolveCall( - context, referencedName, nameExpression, - NewResolutionOldInference.ResolutionKind.Variable.INSTANCE); + return computeTasksAndResolveCall(context, referencedName, nameExpression, KotlinCallKind.VARIABLE); } @NotNull @@ -128,8 +124,8 @@ public class CallResolver { @NotNull BasicCallResolutionContext context ) { return computeTasksAndResolveCall( - context, nameExpression.getReferencedNameAsName(), nameExpression, - NewResolutionOldInference.ResolutionKind.CallableReference.INSTANCE); + context, nameExpression.getReferencedNameAsName(), nameExpression, KotlinCallKind.CALLABLE_REFERENCE + ); } @NotNull @@ -140,9 +136,7 @@ public class CallResolver { @NotNull Name name ) { BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS); - return computeTasksAndResolveCall( - callResolutionContext, name, functionReference, - NewResolutionOldInference.ResolutionKind.Function.INSTANCE); + return computeTasksAndResolveCall(callResolutionContext, name, functionReference, KotlinCallKind.FUNCTION); } @NotNull @@ -153,7 +147,7 @@ public class CallResolver { @NotNull TracingStrategy tracing ) { BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS); - return computeTasksAndResolveCall(callResolutionContext, name, tracing, NewResolutionOldInference.ResolutionKind.Function.INSTANCE); + return computeTasksAndResolveCall(callResolutionContext, name, tracing, KotlinCallKind.FUNCTION); } @NotNull @@ -161,9 +155,7 @@ public class CallResolver { @NotNull BasicCallResolutionContext context, @NotNull TracingStrategy tracing ) { - return computeTasksAndResolveCall( - context, OperatorNameConventions.INVOKE, tracing, - NewResolutionOldInference.ResolutionKind.Invoke.INSTANCE); + return computeTasksAndResolveCall(context, OperatorNameConventions.INVOKE, tracing, KotlinCallKind.INVOKE); } // this declaration is used by compiler plugins @@ -173,7 +165,7 @@ public class CallResolver { @NotNull BasicCallResolutionContext context, @NotNull Name name, @NotNull KtReferenceExpression referenceExpression, - @NotNull NewResolutionOldInference.ResolutionKind kind + @NotNull KotlinCallKind kind ) { TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call); return computeTasksAndResolveCall(context, name, tracing, kind); @@ -186,7 +178,7 @@ public class CallResolver { @NotNull BasicCallResolutionContext context, @NotNull Name name, @NotNull TracingStrategy tracing, - @NotNull NewResolutionOldInference.ResolutionKind kind + @NotNull KotlinCallKind kind ) { return callResolvePerfCounter.>time(() -> { ResolutionTask resolutionTask = new ResolutionTask<>(kind, name); @@ -247,7 +239,7 @@ public class CallResolver { TracingStrategy.EMPTY, KotlinCallKind.VARIABLE, null, - dispatchReceiver != null ? NewResolutionOldInferenceKt.transformToReceiverWithSmartCastInfo(context, dispatchReceiver) : null + dispatchReceiver != null ? CallResolverUtilKt.transformToReceiverWithSmartCastInfo(context, dispatchReceiver) : null ); } @@ -261,7 +253,7 @@ public class CallResolver { ) { TracingStrategy tracingStrategy = TracingStrategyImpl.create(expression, call); ReceiverValueWithSmartCastInfo dispatchReceiverValue = - NewResolutionOldInferenceKt.transformToReceiverWithSmartCastInfo(context, receiver); + CallResolverUtilKt.transformToReceiverWithSmartCastInfo(context, receiver); return resolveCallWithGivenDescriptors( context, call, functionDescriptors, tracingStrategy, null, null, dispatchReceiverValue ); @@ -326,17 +318,13 @@ 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, - NewResolutionOldInference.ResolutionKind.Function.INSTANCE); + return computeTasksAndResolveCall(context, name, arrayAccessExpression, KotlinCallKind.FUNCTION); } KtExpression calleeExpression = context.call.getCalleeExpression(); if (calleeExpression instanceof KtSimpleNameExpression) { KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression; - return computeTasksAndResolveCall( - context, expression.getReferencedNameAsName(), expression, - NewResolutionOldInference.ResolutionKind.Function.INSTANCE); + return computeTasksAndResolveCall(context, expression.getReferencedNameAsName(), expression, KotlinCallKind.FUNCTION); } else if (calleeExpression instanceof KtConstructorCalleeExpression) { return (OverloadResolutionResults) resolveConstructorCall(context, (KtConstructorCalleeExpression) calleeExpression); @@ -557,7 +545,7 @@ public class CallResolver { Call call = context.call; tracing.bindCall(context.trace, call); - NewResolutionOldInference.ResolutionKind resolutionKind = resolutionTask.resolutionKind; + KotlinCallKind resolutionKind = resolutionTask.resolutionKind; assert resolutionTask.name != null; BindingContextUtilsKt.recordScope(context.trace, context.scope, context.call.getCalleeExpression()); @@ -575,12 +563,9 @@ public class CallResolver { @Nullable final Name name; @NotNull - final NewResolutionOldInference.ResolutionKind resolutionKind; + final KotlinCallKind resolutionKind; - private ResolutionTask( - @NotNull NewResolutionOldInference.ResolutionKind kind, - @Nullable Name name - ) { + private ResolutionTask(@NotNull KotlinCallKind kind, @Nullable Name name) { this.name = name; resolutionKind = kind; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 762370f6b7e..7ca1da45f50 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -17,7 +17,6 @@ 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 @@ -38,6 +37,7 @@ 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.checker.KotlinTypeRefiner import org.jetbrains.kotlin.utils.addToStdlib.safeAs diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 47e651048cb..389881f4e44 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -14,9 +14,6 @@ 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 @@ -29,7 +26,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.makeNullableTypeIfSafeReceiver +import org.jetbrains.kotlin.resolve.calls.util.* import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index df22f4d94f4..34261a1ca6b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -24,6 +24,7 @@ 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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt deleted file mode 100644 index 60dec9bb14e..00000000000 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ /dev/null @@ -1,678 +0,0 @@ -/* - * 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 - - object Function : ResolutionKind() { - override fun createTowerProcessor( - outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext - ): ScopeTowerProcessor { - 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 { - 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 { - 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 { - 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 { - throw IllegalStateException("Should be not called") - } - } - } - - fun runResolution( - context: BasicCallResolutionContext, - name: Name, - kind: ResolutionKind, - tracing: TracingStrategy - ): OverloadResolutionResultsImpl { - 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(candidates, tracing, context) - return overloadResults - } - - fun runResolutionForGivenCandidates( - basicCallContext: BasicCallResolutionContext, - tracing: TracingStrategy, - candidates: Collection> - ): OverloadResolutionResultsImpl { - 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 allCandidatesResult(allCandidates: Collection) = - OverloadResolutionResultsImpl.nameNotFound().apply { - this.allCandidates = allCandidates.map { - @Suppress("UNCHECKED_CAST") - it.resolvedCall as MutableResolvedCall - } - } - - private fun convertToOverloadResults( - candidates: Collection, - tracing: TracingStrategy, - basicCallContext: BasicCallResolutionContext - ): OverloadResolutionResultsImpl { - 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 - } - - 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() - - override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? = - scope.implicitReceiver?.value?.let { - cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) } - } - - override fun getContextReceivers(scope: LexicalScope): List = - 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, - location: LookupLocation, - dispatchReceiver: ReceiverValueWithSmartCastInfo?, - extensionReceiver: ReceiverValueWithSmartCastInfo? - ): Collection { - return candidateInterceptor.interceptFunctionCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location) - } - - override fun interceptVariableCandidates( - resolutionScope: ResolutionScope, - name: Name, - initialResults: Collection, - location: LookupLocation, - dispatchReceiver: ReceiverValueWithSmartCastInfo?, - extensionReceiver: ReceiverValueWithSmartCastInfo? - ): Collection { - 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, - val resolvedCall: MutableResolvedCall<*>, - finalDiagnosticsComputation: (() -> List)? = null - ) : Candidate { - val diagnostics: List 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 { - 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 - ): 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 - ): List = - mutableListOf().apply { - addAll(towerCandidate.diagnostics) - addAll(checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor)) - addIfNotNull(createPreviousResolveError(candidateCall.status)) - } - - private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List { - 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 { - - override fun transformCandidate( - variable: MyCandidate, - invoke: MyCandidate - ): MyCandidate { - @Suppress("UNCHECKED_CAST") val resolvedCallImpl = VariableAsFunctionResolvedCallImpl( - invoke.resolvedCall as MutableResolvedCall, - variable.resolvedCall as MutableResolvedCall - ) - 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 { - 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>? { - 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) - ) - } - -} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index d90519be957..86167326578 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -9,6 +9,7 @@ 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 @@ -26,6 +27,7 @@ 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 @@ -45,6 +47,7 @@ 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.* @@ -86,23 +89,14 @@ 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 runResolutionAndInference( context: BasicCallResolutionContext, name: Name, - resolutionKind: NewResolutionOldInference.ResolutionKind, + kotlinCallKind: KotlinCallKind, tracingStrategy: TracingStrategy ): OverloadResolutionResults { 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) @@ -579,15 +573,6 @@ 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, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt index b2b2833272b..7dba7eb67d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/util/CallResolverUtil.kt @@ -14,6 +14,7 @@ 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.* @@ -33,15 +34,20 @@ 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 @@ -53,6 +59,7 @@ 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, @@ -408,3 +415,69 @@ 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) + ) + } +}