K1: Deprecate incorrect callable references resolution behavior
^KT-54316 Related ^KT-54832 Fixed
This commit is contained in:
committed by
Space Team
parent
a3fd63fb1d
commit
2953e600ff
@@ -889,6 +889,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtExpression> RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtParenthesizedExpression> PARENTHESIZED_COMPANION_LHS_DEPRECATION = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> INCORRECT_CALLABLE_REFERENCE_RESOLUTION_FOR_COMPANION_LHS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> RESOLUTION_TO_PRIVATE_CONSTRUCTOR_OF_SEALED_CLASS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
|
||||
+5
@@ -460,6 +460,11 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(PARENTHESIZED_COMPANION_LHS_DEPRECATION, "Access to companion object through parenthesized class name is deprecated. Please, add explicit Companion qualifier.");
|
||||
|
||||
MAP.put(
|
||||
INCORRECT_CALLABLE_REFERENCE_RESOLUTION_FOR_COMPANION_LHS,
|
||||
"Callable reference to the companion's member is incorrectly resolved as unbound. Please, add explicit Companion qualifier to the left-hand-side. See https://youtrack.jetbrains.com/issue/KT-54316 for details"
|
||||
);
|
||||
|
||||
|
||||
MAP.put(RESOLUTION_TO_PRIVATE_CONSTRUCTOR_OF_SEALED_CLASS, "The private constructor of a sealed class will become inaccessible here in future. See https://youtrack.jetbrains.com/issue/KT-44866 for details");
|
||||
MAP.put(
|
||||
|
||||
@@ -70,7 +70,7 @@ private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
ReferencingToUnderscoreNamedParameterOfCatchBlockChecker, VarargWrongExecutionOrderChecker, SelfCallInNestedObjectConstructorChecker,
|
||||
NewSchemeOfIntegerOperatorResolutionChecker, EnumEntryVsCompanionPriorityCallChecker, CompanionInParenthesesLHSCallChecker,
|
||||
ResolutionToPrivateConstructorOfSealedClassChecker, EqualityCallChecker, UnsupportedUntilOperatorChecker,
|
||||
BuilderInferenceAssignmentChecker, IncorrectCapturedApproximationCallChecker,
|
||||
BuilderInferenceAssignmentChecker, IncorrectCapturedApproximationCallChecker, CompanionIncorrectlyUnboundedWhenUsedAsLHSCallChecker,
|
||||
)
|
||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
||||
|
||||
+45
-9
@@ -13,8 +13,11 @@ import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
/**
|
||||
* Deprecate callable references in a form of (SomeClass)::name when SomeClass has a companion
|
||||
@@ -27,16 +30,49 @@ object CompanionInParenthesesLHSCallChecker : CallChecker {
|
||||
val unwrappedLhs = parenthesizedExpression.expression ?: return
|
||||
val expressionReceiver = resolvedCall.call.explicitReceiver as? ExpressionReceiver ?: return
|
||||
|
||||
val referencedClass = expressionReceiver.type.constructor.declarationDescriptor as? ClassDescriptor ?: return
|
||||
if (!referencedClass.isCompanionObject) return
|
||||
|
||||
// We should also consider cases like (package.MyClassWithCompanion)::foo
|
||||
val simpleReference =
|
||||
((unwrappedLhs as? KtDotQualifiedExpression)?.selectorExpression ?: unwrappedLhs) as? KtReferenceExpression
|
||||
?: return
|
||||
|
||||
if (context.trace.bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, simpleReference] == null) return
|
||||
if (!isReferenceToShortFormCompanion(expressionReceiver, unwrappedLhs, context)) return
|
||||
|
||||
context.trace.report(Errors.PARENTHESIZED_COMPANION_LHS_DEPRECATION.on(parenthesizedExpression))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report warnings on top-level callable references (one that are not nested in any call) that have short-formed LHS resolved to companion
|
||||
* Because they have wrong function type shape at K1
|
||||
* (see relevant testData)
|
||||
*/
|
||||
object CompanionIncorrectlyUnboundedWhenUsedAsLHSCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
val callableReference = resolvedCall.call.callElement.parent as? KtCallableReferenceExpression ?: return
|
||||
val classQualifier = resolvedCall.call.explicitReceiver as? ClassQualifier ?: return
|
||||
val dispatchReceiver = resolvedCall.dispatchReceiver ?: return
|
||||
|
||||
if (dispatchReceiver != classQualifier.classValueReceiver) return
|
||||
|
||||
// Only top-level callable references may have callPosition like this
|
||||
// References nested in calls have CallPosition.Unknown
|
||||
if (context.resolutionContext.callPosition !is CallPosition.CallableReferenceRhs) return
|
||||
|
||||
val referencedClass = dispatchReceiver.type.constructor.declarationDescriptor as? ClassDescriptor ?: return
|
||||
if (!referencedClass.isCompanionObject) return
|
||||
|
||||
context.trace.report(Errors.INCORRECT_CALLABLE_REFERENCE_RESOLUTION_FOR_COMPANION_LHS.on(callableReference))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun isReferenceToShortFormCompanion(
|
||||
receiver: ReceiverValue,
|
||||
lhs: PsiElement?,
|
||||
context: CallCheckerContext
|
||||
): Boolean {
|
||||
val referencedClass = receiver.type.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
if (!referencedClass.isCompanionObject) return false
|
||||
|
||||
// We should also consider cases like (package.MyClassWithCompanion)::foo
|
||||
val simpleReference =
|
||||
((lhs as? KtDotQualifiedExpression)?.selectorExpression ?: lhs) as? KtReferenceExpression
|
||||
?: return false
|
||||
|
||||
return context.trace.bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, simpleReference] != null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user