diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index a02ff1ac3fc..65be09e6961 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -585,6 +585,8 @@ class KotlinCoreEnvironment private constructor( IrGenerationExtension.registerExtensionPoint(project) ScriptEvaluationExtension.registerExtensionPoint(project) ShellExtension.registerExtensionPoint(project) + TypeResolutionInterceptorExtension.registerExtensionPoint(project) + CallResolutionInterceptorExtension.registerExtensionPoint(project) } internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/CallResolutionInterceptorExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/CallResolutionInterceptorExtension.kt new file mode 100644 index 00000000000..30c7094a7bf --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/CallResolutionInterceptorExtension.kt @@ -0,0 +1,46 @@ +package org.jetbrains.kotlin.extensions + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.CallResolver +import org.jetbrains.kotlin.resolve.calls.CandidateResolver +import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy +import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower +import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference +import org.jetbrains.kotlin.resolve.scopes.ResolutionScope +import org.jetbrains.kotlin.types.expressions.ExpressionTypingFacade +import java.util.* + +interface CallResolutionInterceptorExtension { + companion object : ProjectExtensionDescriptor( + "org.jetbrains.kotlin.callResolutionInterceptorExtension", + CallResolutionInterceptorExtension::class.java + ) + + fun interceptCandidates( + candidates: Collection, + context: BasicCallResolutionContext, + candidateResolver: CandidateResolver, + callResolver: CallResolver?, + name: Name, + kind: NewResolutionOldInference.ResolutionKind, + tracing: TracingStrategy + ): Collection { + return candidates + } + + fun interceptCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: CallResolver?, + name: Name, + location: LookupLocation + ): Collection { + return candidates + } +} + diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/TypeResolutionInterceptorExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/TypeResolutionInterceptorExtension.kt new file mode 100644 index 00000000000..3fac60a2ec8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/TypeResolutionInterceptorExtension.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.extensions + +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtLambdaExpression +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext + +interface TypeResolutionInterceptorExtension { + companion object : ProjectExtensionDescriptor( + "org.jetbrains.kotlin.typeResolutionInterceptorExtension", + TypeResolutionInterceptorExtension::class.java + ) + + fun interceptFunctionLiteralDescriptor( + expression: KtLambdaExpression, + context: ExpressionTypingContext, + descriptor: AnonymousFunctionDescriptor + ): AnonymousFunctionDescriptor = descriptor + + fun interceptType( + element: KtElement, + context: ExpressionTypingContext, + resultType: KotlinType + ): KotlinType = resultType +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 2785b5e5a70..67efe81c85a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.contracts.ContractDeserializerImpl +import org.jetbrains.kotlin.extensions.CallResolutionInterceptorExtension import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker @@ -73,6 +74,8 @@ fun StorageComponentContainer.configureModule( extension.registerModuleComponents(this, platform, moduleContext.module) } + useInstance(CandidateInterceptor(CallResolutionInterceptorExtension.getInstances(moduleContext.project))) + useImpl() if (languageVersionSettings.isTypeRefinementEnabled) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CandidateInterceptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CandidateInterceptor.kt new file mode 100644 index 00000000000..1f24181c165 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CandidateInterceptor.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.extensions.CallResolutionInterceptorExtension +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.CallResolver +import org.jetbrains.kotlin.resolve.calls.CandidateResolver +import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext +import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy +import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower +import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference +import org.jetbrains.kotlin.resolve.scopes.ResolutionScope + +class CandidateInterceptor(private val extensions: Collection) { + fun interceptCandidates( + candidates: Collection, + context: BasicCallResolutionContext, + candidateResolver: CandidateResolver, + callResolver: CallResolver?, + name: Name, + kind: NewResolutionOldInference.ResolutionKind, + tracing: TracingStrategy + ): Collection { + return extensions.fold(candidates) { candidates, extension -> + extension.interceptCandidates(candidates, context, candidateResolver, callResolver, name, kind, tracing) + } + } + + fun interceptCandidates( + candidates: Collection, + scopeTower: ImplicitScopeTower, + resolutionContext: BasicCallResolutionContext, + resolutionScope: ResolutionScope, + callResolver: CallResolver?, + name: Name, + location: LookupLocation + ): Collection { + return extensions.fold(candidates) { candidates, extension -> + extension.interceptCandidates(candidates, scopeTower, resolutionContext, resolutionScope, callResolver, name, location) + } + + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionInterceptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionInterceptor.kt new file mode 100644 index 00000000000..fcb578f6c59 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolutionInterceptor.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve + +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor +import org.jetbrains.kotlin.extensions.TypeResolutionInterceptorExtension +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtLambdaExpression +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext + +class TypeResolutionInterceptor(private val project: Project) { + val extensions = TypeResolutionInterceptorExtension.getInstances(project) + fun interceptFunctionLiteralDescriptor( + expression: KtLambdaExpression, + context: ExpressionTypingContext, + descriptor: AnonymousFunctionDescriptor + ): AnonymousFunctionDescriptor { + var resultDescriptor = descriptor + for (extension in extensions) { + resultDescriptor = extension.interceptFunctionLiteralDescriptor( + expression, + context, + descriptor + ) + } + return resultDescriptor + } + + fun interceptType( + element: KtElement, + context: ExpressionTypingContext, + resultType: KotlinType + ): KotlinType { + var type = resultType + for (extension in extensions) { + type = extension.interceptType(element, context, type) + } + return type + } + + fun isEmpty() = extensions.isEmpty() +} 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 b85613e911b..3b842727013 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -681,7 +681,7 @@ public class CallResolver { OverloadResolutionResultsImpl result; if (!(resolutionTask.resolutionKind instanceof NewResolutionOldInference.ResolutionKind.GivenCandidates)) { assert resolutionTask.name != null; - result = newResolutionOldInference.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing); + result = newResolutionOldInference.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing, this); } else { assert resolutionTask.givenCandidates != null; 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 index df8920cda48..dc30153123a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -27,7 +27,9 @@ import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.KtReferenceExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.CandidateInterceptor import org.jetbrains.kotlin.resolve.TemporaryBindingTrace +import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CandidateResolver import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator @@ -49,10 +51,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.* import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.descriptorUtil.hasDynamicExtensionAnnotation -import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope -import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes +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 @@ -74,7 +73,8 @@ class NewResolutionOldInference( private val languageVersionSettings: LanguageVersionSettings, private val coroutineInferenceSupport: CoroutineInferenceSupport, private val deprecationResolver: DeprecationResolver, - private val typeApproximator: TypeApproximator + private val typeApproximator: TypeApproximator, + private val candidateInterceptor: CandidateInterceptor ) { sealed class ResolutionKind { abstract internal fun createTowerProcessor( @@ -162,7 +162,8 @@ class NewResolutionOldInference( context: BasicCallResolutionContext, name: Name, kind: ResolutionKind, - tracing: TracingStrategy + tracing: TracingStrategy, + callResolver: CallResolver ): OverloadResolutionResultsImpl { val explicitReceiver = context.call.explicitReceiver val detailedReceiver = if (explicitReceiver is QualifierReceiver?) { @@ -173,7 +174,7 @@ class NewResolutionOldInference( val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) val scopeTower = ImplicitScopeTowerImpl( - context, dynamicScope, syntheticScopes, context.call.createLookupLocation(), typeApproximator + context, dynamicScope, syntheticScopes, context.call.createLookupLocation(), typeApproximator, callResolver, candidateInterceptor ) val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem) @@ -207,6 +208,8 @@ class NewResolutionOldInference( ) } + candidates = candidateInterceptor.interceptCandidates(candidates, context, candidateResolver, callResolver, name, kind, tracing) + if (candidates.isEmpty()) { if (reportAdditionalDiagnosticIfNoCandidates(context, nameToResolve, kind, scopeTower, detailedReceiver)) { return OverloadResolutionResultsImpl.nameNotFound() @@ -353,12 +356,14 @@ class NewResolutionOldInference( return true } - private class ImplicitScopeTowerImpl( - val resolutionContext: ResolutionContext<*>, + public class ImplicitScopeTowerImpl( + val resolutionContext: BasicCallResolutionContext, override val dynamicScope: MemberScope, override val syntheticScopes: SyntheticScopes, override val location: LookupLocation, - override val typeApproximator: TypeApproximator + override val typeApproximator: TypeApproximator, + val callResolver: CallResolver, + val candidateInterceptor: CandidateInterceptor ) : ImplicitScopeTower { private val cache = HashMap() @@ -373,9 +378,19 @@ class NewResolutionOldInference( override val isNewInferenceEnabled: Boolean get() = resolutionContext.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) + + override fun interceptCandidates( + resolutionScope: ResolutionScope, + name: Name, + candidates: Collection, + location: LookupLocation + ): Collection { + val project = resolutionContext.call.callElement.project + return candidateInterceptor.interceptCandidates(candidates, this, resolutionContext, resolutionScope, callResolver, name, location) + } } - internal class MyCandidate( + 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 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 f9363e5491e..575811059ea 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 @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.contracts.EffectSystem import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.extensions.CallResolutionInterceptorExtension import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.types.* @@ -67,7 +69,8 @@ class PSICallResolver( private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter, private val deprecationResolver: DeprecationResolver, private val moduleDescriptor: ModuleDescriptor, - private val callableReferenceResolver: CallableReferenceResolver + private val callableReferenceResolver: CallableReferenceResolver, + private val candidateInterceptor: CandidateInterceptor ) { private val givenCandidatesName = Name.special("") @@ -397,6 +400,16 @@ class PSICallResolver( context.transformToReceiverWithSmartCastInfo(implicitReceiver.value) } } + + override fun interceptCandidates( + resolutionScope: ResolutionScope, + name: Name, + candidates: Collection, + location: LookupLocation + ): Collection { + val project = context.call.callElement.project + return candidateInterceptor.interceptCandidates(candidates, this, context, resolutionScope, null, name, location) + } } private inner class FactoryProviderForInvoke( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 42b2eedad22..6ae2a1e4612 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.diagnostics.Errors; +import org.jetbrains.kotlin.extensions.TypeResolutionInterceptorExtension; import org.jetbrains.kotlin.incremental.KotlinLookupLocation; import org.jetbrains.kotlin.lexer.KtKeywordToken; import org.jetbrains.kotlin.lexer.KtTokens; @@ -1635,7 +1636,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (baseExpression == null) { return TypeInfoFactoryKt.noTypeInfo(context); } - return facade.getTypeInfo(baseExpression, context, isStatement); + KotlinType newExpectedType = components.typeResolutionInterceptor.interceptType(baseExpression, context, context.expectedType); + KotlinTypeInfo resultTypeInfo = facade.getTypeInfo(baseExpression, newExpectedType == context.expectedType ? context : context.replaceExpectedType(newExpectedType), isStatement); + KotlinType newResultType = components.typeResolutionInterceptor.interceptType(baseExpression, context, resultTypeInfo.getType()); + if(!components.typeResolutionInterceptor.isEmpty()) components.dataFlowAnalyzer.checkType(newResultType, expression, context); + return resultTypeInfo.getType() == newResultType ? resultTypeInfo : resultTypeInfo.replaceType(newResultType); } protected void resolveAnnotationsOnExpression(KtAnnotatedExpression expression, ExpressionTypingContext context) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index dd435a35f84..8472f9886e9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -64,6 +64,7 @@ public class ExpressionTypingComponents { /*package*/ ContractParsingServices contractParsingServices; /*package*/ DataFlowValueFactory dataFlowValueFactory; /*package*/ NewKotlinTypeChecker kotlinTypeChecker; + /*package*/ TypeResolutionInterceptor typeResolutionInterceptor; @Inject @@ -245,4 +246,9 @@ public class ExpressionTypingComponents { public void setKotlinTypeChecker(@NotNull NewKotlinTypeChecker kotlinTypeChecker) { this.kotlinTypeChecker = kotlinTypeChecker; } + + @Inject + public void setTypeResolutionInterceptor(@NotNull TypeResolutionInterceptor typeResolutionInterceptor) { + this.typeResolutionInterceptor = typeResolutionInterceptor; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index a4575dedcc4..d72548770a2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -21,11 +21,8 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.checkReservedPrefixWord import org.jetbrains.kotlin.psi.psiUtil.checkReservedYieldBeforeLambda import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries -import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE -import org.jetbrains.kotlin.resolve.BindingContextUtils -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker @@ -147,7 +144,12 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected) functionDescriptor.setReturnType(safeReturnType) - val resultType = functionDescriptor.createFunctionType(components.builtIns, suspendFunctionTypeExpected)!! + val resultType = components.typeResolutionInterceptor.interceptType( + expression, + context, + functionDescriptor.createFunctionType(components.builtIns, suspendFunctionTypeExpected)!! + ) + if (functionTypeExpected) { // all checks were done before return createTypeInfo(resultType, context) @@ -175,7 +177,9 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace), CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(), context.expectedType.isSuspendFunctionType() - ) + ).let { + TypeResolutionInterceptor(expression.project).interceptFunctionLiteralDescriptor(expression, context, it) + } components.functionDescriptorResolver.initializeFunctionDescriptorAndExplicitReturnType( context.scope.ownerDescriptor, context.scope, functionLiteral, functionDescriptor, context.trace, context.expectedType, context.dataFlowInfo diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt index 58211e54faa..34d7e4b891d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt @@ -16,9 +16,7 @@ package org.jetbrains.kotlin.resolve.calls.tower -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter @@ -45,6 +43,13 @@ interface ImplicitScopeTower { val isNewInferenceEnabled: Boolean val typeApproximator: TypeApproximator + + fun interceptCandidates( + resolutionScope: ResolutionScope, + name: Name, + initialResults: Collection, + location: LookupLocation + ): Collection } interface ScopeTowerLevel { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 66d5c79cf38..f306b2ccce6 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -17,6 +17,9 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast @@ -207,7 +210,7 @@ internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qual .getContributedFunctionsAndConstructors( name, location, - scopeTower.syntheticScopes + scopeTower ).map { createCandidateDescriptor(it, dispatchReceiver = null) } @@ -255,7 +258,7 @@ internal open class ScopeBasedTowerLevel protected constructor( ): Collection { val result: ArrayList = ArrayList() - resolutionScope.getContributedFunctionsAndConstructors(name, location, scopeTower.syntheticScopes).mapTo(result) { + resolutionScope.getContributedFunctionsAndConstructors(name, location, scopeTower).mapTo(result) { createCandidateDescriptor( it, dispatchReceiver = null, @@ -366,7 +369,7 @@ private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocatio private fun ResolutionScope.getContributedFunctionsAndConstructors( name: Name, location: LookupLocation, - syntheticScopes: SyntheticScopes + scopeTower: ImplicitScopeTower ): Collection { val result = ArrayList(getContributedFunctions(name, location)) @@ -374,10 +377,10 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors( result.addAll(getConstructorsOfClassifier(it)) } - result.addAll(syntheticScopes.collectSyntheticStaticFunctions(this, name, location)) - result.addAll(syntheticScopes.collectSyntheticConstructors(this, name, location)) + result.addAll(scopeTower.syntheticScopes.collectSyntheticStaticFunctions(this, name, location)) + result.addAll(scopeTower.syntheticScopes.collectSyntheticConstructors(this, name, location)) - return result.toList() + return scopeTower.interceptCandidates(this, name, result, location).toList() } private fun getConstructorsOfClassifier(classifier: ClassifierDescriptor?): List { diff --git a/idea/resources/META-INF/extensions/compiler.xml b/idea/resources/META-INF/extensions/compiler.xml index 7f36a7ec2de..68f90fb2c3d 100644 --- a/idea/resources/META-INF/extensions/compiler.xml +++ b/idea/resources/META-INF/extensions/compiler.xml @@ -5,6 +5,15 @@ + + +