Report invisible setter error if it's resolved to synthetic property of base class with public getter and protected setter

^KT-11713 Fixed
This commit is contained in:
Victor Petukhov
2020-09-21 23:53:13 +03:00
parent fdd71c0bce
commit fcfabb70d5
21 changed files with 372 additions and 36 deletions
@@ -1033,7 +1033,7 @@ public interface Errors {
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtTypeParameterList> LOCAL_VARIABLE_WITH_TYPE_PARAMETERS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory3<KtExpression, DeclarationDescriptor, DescriptorVisibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<PsiElement, DeclarationDescriptor, DescriptorVisibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_LOOP_PARAMETER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_FUN_PARAMETER = DiagnosticFactory1.create(ERROR);
@@ -51,25 +51,23 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
): Boolean {
if (!TypeUtils.contains(expectedType) { it.isAnyOrNullableAny() || it.isNothing() || it.isNullableNothing() }) return false
val callPosition = this.callPosition
val (resolvedCall, correspondingNotApproximatedTypeByDescriptor: (CallableDescriptor) -> KotlinType?) = when (callPosition) {
is CallPosition.ValueArgumentPosition -> Pair(
callPosition.resolvedCall, { f: CallableDescriptor ->
is CallPosition.ValueArgumentPosition ->
callPosition.resolvedCall to { f: CallableDescriptor ->
getEffectiveExpectedType(f.valueParameters[callPosition.valueParameter.index], callPosition.valueArgument, this)
})
is CallPosition.ExtensionReceiverPosition -> Pair<ResolvedCall<*>, (CallableDescriptor) -> KotlinType?>(
callPosition.resolvedCall, { f: CallableDescriptor ->
f.extensionReceiverParameter?.type
})
is CallPosition.PropertyAssignment -> Pair<ResolvedCall<out CallableDescriptor>, (CallableDescriptor) -> KotlinType?>(
callPosition.leftPart.getResolvedCall(trace.bindingContext) ?: return false, { f: CallableDescriptor ->
(f as? PropertyDescriptor)?.setter?.valueParameters?.get(0)?.type
})
}
is CallPosition.ExtensionReceiverPosition ->
callPosition.resolvedCall to { f: CallableDescriptor -> f.extensionReceiverParameter?.type }
is CallPosition.PropertyAssignment -> {
if (callPosition.isLeft) return false
val resolvedCall = callPosition.leftPart.getResolvedCall(trace.bindingContext) ?: return false
resolvedCall to { f: CallableDescriptor -> (f as? PropertyDescriptor)?.setter?.valueParameters?.get(0)?.type }
}
is CallPosition.Unknown -> return false
}
val receiverType = resolvedCall.smartCastDispatchReceiverType
?: (resolvedCall.dispatchReceiver ?: return false).type
?: (resolvedCall.dispatchReceiver ?: return false).type
val callableDescriptor = resolvedCall.resultingDescriptor.original
@@ -33,5 +33,5 @@ sealed class CallPosition {
val valueArgument: ValueArgument
) : CallPosition()
class PropertyAssignment(val leftPart: KtExpression?) : CallPosition()
class PropertyAssignment(val leftPart: KtExpression?, val isLeft: Boolean) : CallPosition()
}
@@ -304,7 +304,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
KotlinType expectedType = refineTypeFromPropertySetterIfPossible(context.trace.getBindingContext(), leftOperand, leftType);
components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(expectedType)
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()).replaceCallPosition(new CallPosition.PropertyAssignment(left)));
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()).replaceCallPosition(new CallPosition.PropertyAssignment(left, false)));
basic.checkLValue(context.trace, context, leftOperand, right, expression, false);
}
temporary.commit();
@@ -354,14 +354,21 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
basic.checkLValue(context.trace, context, arrayAccessExpression, right, expression, true);
return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
}
KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(
left,
context.replaceCallPosition(new CallPosition.PropertyAssignment(left, true)),
facade
);
KotlinType expectedType = refineTypeFromPropertySetterIfPossible(context.trace.getBindingContext(), leftOperand, leftInfo.getType());
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
KotlinTypeInfo resultInfo;
if (right != null) {
resultInfo = facade.getTypeInfo(
right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(expectedType).replaceCallPosition(
new CallPosition.PropertyAssignment(leftOperand)));
right,
context.replaceDataFlowInfo(dataFlowInfo)
.replaceExpectedType(expectedType)
.replaceCallPosition(new CallPosition.PropertyAssignment(leftOperand, false))
);
dataFlowInfo = resultInfo.getDataFlowInfo();
KotlinType rightType = resultInfo.getType();