Add some changes to introduced extension points

This commit is contained in:
Stanislav Erokhin
2019-10-16 21:01:11 +03:00
parent 267287118b
commit 84aff5f630
16 changed files with 158 additions and 163 deletions
@@ -85,6 +85,8 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
@@ -585,8 +587,8 @@ class KotlinCoreEnvironment private constructor(
IrGenerationExtension.registerExtensionPoint(project)
ScriptEvaluationExtension.registerExtensionPoint(project)
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptorExtension.registerExtensionPoint(project)
CallResolutionInterceptorExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)
CandidateInterceptor.registerExtensionPoint(project)
}
internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) {
@@ -1,46 +0,0 @@
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<CallResolutionInterceptorExtension>(
"org.jetbrains.kotlin.callResolutionInterceptorExtension",
CallResolutionInterceptorExtension::class.java
)
fun interceptCandidates(
candidates: Collection<NewResolutionOldInference.MyCandidate>,
context: BasicCallResolutionContext,
candidateResolver: CandidateResolver,
callResolver: CallResolver?,
name: Name,
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): Collection<NewResolutionOldInference.MyCandidate> {
return candidates
}
fun interceptCandidates(
candidates: Collection<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver?,
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> {
return candidates
}
}
@@ -1,31 +0,0 @@
/*
* 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<TypeResolutionInterceptorExtension>(
"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
}
@@ -3,10 +3,11 @@
* 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
package org.jetbrains.kotlin.extensions.internal
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.extensions.CallResolutionInterceptorExtension
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.CallResolver
@@ -17,8 +18,11 @@ 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<CallResolutionInterceptorExtension>) {
fun interceptCandidates(
@UseExperimental(InternalNonStableExtensionPoints::class)
class CandidateInterceptor(project: Project) {
private val extensions = getInstances(project)
fun interceptResolvedCandidates(
candidates: Collection<NewResolutionOldInference.MyCandidate>,
context: BasicCallResolutionContext,
candidateResolver: CandidateResolver,
@@ -26,10 +30,8 @@ class CandidateInterceptor(private val extensions: Collection<CallResolutionInte
name: Name,
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): Collection<NewResolutionOldInference.MyCandidate> {
return extensions.fold(candidates) { candidates, extension ->
extension.interceptCandidates(candidates, context, candidateResolver, callResolver, name, kind, tracing)
}
) = extensions.fold(candidates) { it, extension ->
extension.interceptCandidates(it, context, candidateResolver, callResolver, name, kind, tracing)
}
fun interceptCandidates(
@@ -40,10 +42,12 @@ class CandidateInterceptor(private val extensions: Collection<CallResolutionInte
callResolver: CallResolver?,
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> {
return extensions.fold(candidates) { candidates, extension ->
extension.interceptCandidates(candidates, scopeTower, resolutionContext, resolutionScope, callResolver, name, location)
}
): Collection<FunctionDescriptor> = extensions.fold(candidates) { it, extension ->
extension.interceptCandidates(it, scopeTower, resolutionContext, resolutionScope, callResolver, name, location)
}
companion object : ProjectExtensionDescriptor<CallResolutionInterceptorExtension>(
"org.jetbrains.kotlin.extensions.internal.callResolutionInterceptorExtension",
CallResolutionInterceptorExtension::class.java
)
}
@@ -0,0 +1,70 @@
/*
* 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.extensions.internal
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtLambdaExpression
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.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
/**
* This is marker for non-stable experimental extension points.
* Extension points marked with this meta-annotation will be broken in the future version.
* Please do not use them in general code.
*/
@Experimental(level = Experimental.Level.ERROR)
@Retention(AnnotationRetention.BINARY)
internal annotation class InternalNonStableExtensionPoints
@InternalNonStableExtensionPoints
interface TypeResolutionInterceptorExtension {
fun interceptFunctionLiteralDescriptor(
expression: KtLambdaExpression,
context: ExpressionTypingContext,
descriptor: AnonymousFunctionDescriptor
): AnonymousFunctionDescriptor = descriptor
fun interceptType(
element: KtElement,
context: ExpressionTypingContext,
resultType: KotlinType
): KotlinType = resultType
}
@InternalNonStableExtensionPoints
interface CallResolutionInterceptorExtension {
fun interceptCandidates(
candidates: Collection<NewResolutionOldInference.MyCandidate>,
context: BasicCallResolutionContext,
candidateResolver: CandidateResolver,
callResolver: CallResolver?,
name: Name,
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): Collection<NewResolutionOldInference.MyCandidate> = candidates
fun interceptCandidates(
candidates: Collection<FunctionDescriptor>,
scopeTower: ImplicitScopeTower,
resolutionContext: BasicCallResolutionContext,
resolutionScope: ResolutionScope,
callResolver: CallResolver?,
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> = candidates
}
@@ -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.extensions.internal
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
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
@UseExperimental(InternalNonStableExtensionPoints::class)
class TypeResolutionInterceptor(project: Project) {
private val extensions = getInstances(project)
fun interceptFunctionLiteralDescriptor(
expression: KtLambdaExpression,
context: ExpressionTypingContext,
descriptor: AnonymousFunctionDescriptor
) = extensions.fold(descriptor) { it, extension ->
extension.interceptFunctionLiteralDescriptor(expression, context, it)
}
fun interceptType(
element: KtElement,
context: ExpressionTypingContext,
resultType: KotlinType?
): KotlinType? {
// null means that source code has errors and in such scenarios shouldn't be passed into extension point
if (resultType == null) return null
return extensions.fold(resultType) { it, extension ->
extension.interceptType(element, context, it)
}
}
fun isEmpty() = extensions.isEmpty()
companion object : ProjectExtensionDescriptor<TypeResolutionInterceptorExtension>(
"org.jetbrains.kotlin.extensions.internal.typeResolutionInterceptorExtension",
TypeResolutionInterceptorExtension::class.java
)
}
@@ -23,7 +23,6 @@ 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
@@ -74,8 +73,6 @@ fun StorageComponentContainer.configureModule(
extension.registerModuleComponents(this, platform, moduleContext.module)
}
useInstance(CandidateInterceptor(CallResolutionInterceptorExtension.getInstances(moduleContext.project)))
useImpl<NewKotlinTypeCheckerImpl>()
if (languageVersionSettings.isTypeRefinementEnabled) {
@@ -1,47 +0,0 @@
/*
* 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()
}
@@ -681,7 +681,7 @@ public class CallResolver {
OverloadResolutionResultsImpl<D> result;
if (!(resolutionTask.resolutionKind instanceof NewResolutionOldInference.ResolutionKind.GivenCandidates)) {
assert resolutionTask.name != null;
result = newResolutionOldInference.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing, this);
result = newResolutionOldInference.runResolution(context, resolutionTask.name, resolutionTask.resolutionKind, tracing);
}
else {
assert resolutionTask.givenCandidates != null;
@@ -27,7 +27,7 @@ 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.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.CallTransformer
@@ -74,6 +74,7 @@ class NewResolutionOldInference(
private val coroutineInferenceSupport: CoroutineInferenceSupport,
private val deprecationResolver: DeprecationResolver,
private val typeApproximator: TypeApproximator,
private val callResolver: CallResolver,
private val candidateInterceptor: CandidateInterceptor
) {
sealed class ResolutionKind {
@@ -162,8 +163,7 @@ class NewResolutionOldInference(
context: BasicCallResolutionContext,
name: Name,
kind: ResolutionKind,
tracing: TracingStrategy,
callResolver: CallResolver
tracing: TracingStrategy
): OverloadResolutionResultsImpl<D> {
val explicitReceiver = context.call.explicitReceiver
val detailedReceiver = if (explicitReceiver is QualifierReceiver?) {
@@ -208,7 +208,7 @@ class NewResolutionOldInference(
)
}
candidates = candidateInterceptor.interceptCandidates(candidates, context, candidateResolver, callResolver, name, kind, tracing)
candidates = candidateInterceptor.interceptResolvedCandidates(candidates, context, candidateResolver, callResolver, name, kind, tracing)
if (candidates.isEmpty()) {
if (reportAdditionalDiagnosticIfNoCandidates(context, nameToResolve, kind, scopeTower, detailedReceiver)) {
@@ -382,11 +382,10 @@ class NewResolutionOldInference(
override fun interceptCandidates(
resolutionScope: ResolutionScope,
name: Name,
candidates: Collection<FunctionDescriptor>,
initialResults: Collection<FunctionDescriptor>,
location: LookupLocation
): Collection<FunctionDescriptor> {
val project = resolutionContext.call.callElement.project
return candidateInterceptor.interceptCandidates(candidates, this, resolutionContext, resolutionScope, callResolver, name, location)
return candidateInterceptor.interceptCandidates(initialResults, this, resolutionContext, resolutionScope, callResolver, name, location)
}
}
@@ -10,7 +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.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@@ -40,7 +40,6 @@ 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.*
@@ -404,11 +403,10 @@ class PSICallResolver(
override fun interceptCandidates(
resolutionScope: ResolutionScope,
name: Name,
candidates: Collection<FunctionDescriptor>,
initialResults: Collection<FunctionDescriptor>,
location: LookupLocation
): Collection<FunctionDescriptor> {
val project = context.call.callElement.project
return candidateInterceptor.interceptCandidates(candidates, this, context, resolutionScope, null, name, location)
return candidateInterceptor.interceptCandidates(initialResults, this, context, resolutionScope, null, name, location)
}
}
@@ -35,7 +35,6 @@ 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;
@@ -1636,10 +1635,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (baseExpression == null) {
return TypeInfoFactoryKt.noTypeInfo(context);
}
if (components.typeResolutionInterceptor.isEmpty()) 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);
components.dataFlowAnalyzer.checkType(newResultType, expression, context);
return resultTypeInfo.getType() == newResultType ? resultTypeInfo : resultTypeInfo.replaceType(newResultType);
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.RttiExpressionChecker;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver;
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor;
import org.jetbrains.kotlin.types.WrappedTypeFactory;
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker;
@@ -178,7 +178,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(),
context.expectedType.isSuspendFunctionType()
).let {
TypeResolutionInterceptor(expression.project).interceptFunctionLiteralDescriptor(expression, context, it)
facade.components.typeResolutionInterceptor.interceptFunctionLiteralDescriptor(expression, context, it)
}
components.functionDescriptorResolver.initializeFunctionDescriptorAndExplicitReturnType(
context.scope.ownerDescriptor, context.scope, functionLiteral,
@@ -380,7 +380,7 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors(
result.addAll(scopeTower.syntheticScopes.collectSyntheticStaticFunctions(this, name, location))
result.addAll(scopeTower.syntheticScopes.collectSyntheticConstructors(this, name, location))
return scopeTower.interceptCandidates(this, name, result, location).toList()
return scopeTower.interceptCandidates(this, name, result, location)
}
private fun getConstructorsOfClassifier(classifier: ClassifierDescriptor?): List<ConstructorDescriptor> {
@@ -8,11 +8,11 @@
<extensionPoint qualifiedName="org.jetbrains.kotlin.analyzeCompleteHandlerExtension"
interface="org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.callResolutionInterceptorExtension"
interface="org.jetbrains.kotlin.extensions.CallResolutionInterceptorExtension"
<extensionPoint qualifiedName="org.jetbrains.kotlin.extensions.internal.callResolutionInterceptorExtension"
interface="org.jetbrains.kotlin.extensions.internal.CallResolutionInterceptorExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.typeResolutionInterceptorExtension"
interface="org.jetbrains.kotlin.extensions.TypeResolutionInterceptorExtension"
<extensionPoint qualifiedName="org.jetbrains.kotlin.extensions.internal.typeResolutionInterceptorExtension"
interface="org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptorExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.expressionCodegenExtension"
interface="org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension"