K1: introduce assignment checkers and convert JvmSyntheticAssignmentChecker

Related to KT-56061
This commit is contained in:
Mikhail Glukhikh
2023-01-25 14:17:09 +01:00
committed by Space Team
parent 5fc0aa769b
commit 7cc3f7de62
6 changed files with 48 additions and 13 deletions
@@ -5,32 +5,27 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.AssignmentChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.tower.isSynthesized
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.BasicExpressionTypingVisitor
import org.jetbrains.kotlin.types.typeUtil.isNothing
object JvmSyntheticAssignmentChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
object JvmSyntheticAssignmentChecker : AssignmentChecker {
override fun check(assignmentExpression: KtBinaryExpression, context: CallCheckerContext) {
val left = assignmentExpression.left ?: return
val resolvedCall = left.getResolvedCall(context.trace.bindingContext) ?: return
val resultingDescriptor = resolvedCall.resultingDescriptor
if (!resultingDescriptor.isSynthesized) return
if (resultingDescriptor !is SyntheticJavaPropertyDescriptor) return
if (reportOn !is KtNameReferenceExpression) return
val binaryExpression = reportOn.getParentOfType<KtBinaryExpression>(strict = true) ?: return
if (!BasicExpressionTypingVisitor.isLValue(reportOn, binaryExpression)) return
val receiverType = resolvedCall.extensionReceiver?.type ?: return
val unsubstitutedReceiverType = resolvedCall.candidateDescriptor.extensionReceiverParameter?.type ?: return
if (receiverType.constructor !== unsubstitutedReceiverType.constructor) return
@@ -50,6 +45,6 @@ object JvmSyntheticAssignmentChecker : CallChecker {
)
val substitutedPropertyType = substitutor.substitute(propertyType.unwrap(), Variance.IN_VARIANCE)
if (substitutedPropertyType == null || !substitutedPropertyType.isNothing()) return
context.trace.report(ErrorsJvm.SYNTHETIC_SETTER_PROJECTED_OUT.on(binaryExpression.left ?: reportOn, resultingDescriptor))
context.trace.report(ErrorsJvm.SYNTHETIC_SETTER_PROJECTED_OUT.on(left, resultingDescriptor))
}
}
@@ -63,11 +63,14 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
SamInterfaceConstructorReferenceCallChecker,
EnumDeclaringClassDeprecationChecker,
UpperBoundViolatedInTypealiasConstructorChecker,
JvmSyntheticAssignmentChecker,
LateinitIntrinsicApplicabilityChecker(isWarningInPre19 = false),
JvmPropertyVsFieldAmbiguityCallChecker,
),
additionalAssignmentCheckers = listOf(
JvmSyntheticAssignmentChecker,
),
additionalTypeCheckers = listOf(
RuntimeAssertionsTypeChecker,
JavaGenericVarianceViolationTypeChecker,
@@ -110,6 +110,7 @@ abstract class PlatformConfiguratorBase(
private val dynamicTypesSettings: DynamicTypesSettings? = null,
private val additionalDeclarationCheckers: List<DeclarationChecker> = emptyList(),
private val additionalCallCheckers: List<CallChecker> = emptyList(),
private val additionalAssignmentCheckers: List<AssignmentChecker> = emptyList(),
private val additionalTypeCheckers: List<AdditionalTypeChecker> = emptyList(),
private val additionalClassifierUsageCheckers: List<ClassifierUsageChecker> = emptyList(),
private val additionalAnnotationCheckers: List<AdditionalAnnotationChecker> = emptyList(),
@@ -135,6 +136,7 @@ abstract class PlatformConfiguratorBase(
useInstanceIfNotNull(dynamicTypesSettings)
additionalDeclarationCheckers.forEach { useInstance(it) }
additionalCallCheckers.forEach { useInstance(it) }
additionalAssignmentCheckers.forEach { useInstance(it) }
additionalTypeCheckers.forEach { useInstance(it) }
additionalClassifierUsageCheckers.forEach { useInstance(it) }
additionalAnnotationCheckers.forEach { useInstance(it) }
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2023 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.calls.checkers
import org.jetbrains.kotlin.psi.KtBinaryExpression
interface AssignmentChecker {
fun check(assignmentExpression: KtBinaryExpression, context: CallCheckerContext)
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
import org.jetbrains.kotlin.resolve.calls.CallResolver;
import org.jetbrains.kotlin.resolve.calls.checkers.AssignmentChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.RttiExpressionChecker;
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallComponents;
@@ -52,6 +53,7 @@ public class ExpressionTypingComponents {
public ModifiersChecker modifiersChecker;
public DataFlowAnalyzer dataFlowAnalyzer;
public Iterable<CallChecker> callCheckers;
public Iterable<AssignmentChecker> assignmentCheckers;
public IdentifierChecker identifierChecker;
public DeclarationsCheckerBuilder declarationsCheckerBuilder;
public LocalVariableResolver localVariableResolver;
@@ -188,6 +190,11 @@ public class ExpressionTypingComponents {
this.callCheckers = callCheckers;
}
@Inject
public void setAssignmentCheckers(@NotNull Iterable<AssignmentChecker> assignmentCheckers) {
this.assignmentCheckers = assignmentCheckers;
}
@Inject
public void setDeclarationsCheckerBuilder(@NotNull DeclarationsCheckerBuilder declarationsCheckerBuilder) {
this.declarationsCheckerBuilder = declarationsCheckerBuilder;
@@ -32,6 +32,8 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
import org.jetbrains.kotlin.resolve.calls.checkers.AssignmentChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext;
import org.jetbrains.kotlin.resolve.calls.checkers.NewSchemeOfIntegerOperatorResolutionChecker;
import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
@@ -482,6 +484,19 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
if (expectedType != null && leftOperand != null) { //if expectedType == null, some other error has been generated
basic.checkLValue(context.trace, context, leftOperand, right, expression, false);
CallCheckerContext callCheckerContext =
new CallCheckerContext(
context,
components.deprecationResolver,
components.moduleDescriptor,
components.missingSupertypesResolver,
components.callComponents,
context.trace
);
for (AssignmentChecker checker : components.assignmentCheckers) {
checker.check(expression, callCheckerContext);
}
}
if (!refineJavaFieldInTypeProperly) {