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