[FE 1.0] Introduce AssignResolutionAltererExtension

This extension can be used to override resolution of assign statements
  with custom logic

WARNING: there is no compatibility guarantees for this extension
This commit is contained in:
Dmitriy Novozhilov
2022-08-11 16:03:36 +03:00
committed by teamcity
parent c0ab367281
commit f843883985
3 changed files with 58 additions and 0 deletions
@@ -23,6 +23,9 @@
<extensionPoint qualifiedName="org.jetbrains.kotlin.syntheticResolveExtension"
interface="org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension"
area="IDEA_PROJECT" dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.assignResolutionAltererExtension"
interface="org.jetbrains.kotlin.resolve.extensions.AssignResolutionAltererExtension"
area="IDEA_PROJECT" dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.jsSyntheticTranslateExtension"
interface="org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension"
area="IDEA_PROJECT" dynamic="true"/>
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2022 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.extensions
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingComponents
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
@InternalNonStableExtensionPoints
interface AssignResolutionAltererExtension : AnnotationBasedExtension {
companion object : ProjectExtensionDescriptor<AssignResolutionAltererExtension>(
"org.jetbrains.kotlin.assignResolutionAltererExtension",
AssignResolutionAltererExtension::class.java
)
fun needOverloadAssign(expression: KtBinaryExpression, leftType: KotlinType?, bindingContext: BindingContext): Boolean
fun resolveAssign(
bindingContext: BindingContext,
expression: KtBinaryExpression,
leftOperand: KtExpression,
left: KtExpression,
leftInfo: KotlinTypeInfo,
context: ExpressionTypingContext,
components: ExpressionTypingComponents,
scope: LexicalWritableScope
): KotlinTypeInfo?
}
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.extensions.AssignResolutionAltererExtension;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
@@ -56,6 +57,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.psi.KtPsiUtil.deparenthesize;
@@ -441,6 +444,19 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
? refineTypeByPropertyInType(bindingContext, leftOperand, leftType)
: refineTypeFromPropertySetterIfPossible(bindingContext, leftOperand, leftType);
List<AssignResolutionAltererExtension> assignAlterers = AssignResolutionAltererExtension.Companion.getInstances(expression.getProject());
if (!assignAlterers.isEmpty()) {
KotlinTypeInfo alteredTypeInfo = assignAlterers.stream()
.filter((it) -> it.needOverloadAssign(expression, leftType, bindingContext))
.map((it) -> it.resolveAssign(bindingContext, expression, leftOperand, left, leftInfo, context, components, scope))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
if (alteredTypeInfo != null) {
return alteredTypeInfo;
}
}
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
KotlinTypeInfo resultInfo;
if (right != null) {