[FIR] Disallow operators not on functions
Introduce `NOT_FUNCTION_AS_OPERATOR` and use it instead of `PROPERTY_AS_OPERATOR` ^KT-65881 Fixed Merge-request: KT-MR-14547
This commit is contained in:
committed by
Space Team
parent
df9d59851d
commit
2d4f4b9bb5
+3
-2
@@ -1585,8 +1585,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirNamedFunctionSymbol>("functionSymbol")
|
||||
parameter<String>("operator")
|
||||
}
|
||||
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||
parameter<FirPropertySymbol>("property")
|
||||
val NOT_FUNCTION_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||
parameter<String>("elementName")
|
||||
parameter<FirBasedSymbol<*>>("elementSymbol")
|
||||
}
|
||||
val DSL_SCOPE_VIOLATION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
|
||||
parameter<FirBasedSymbol<*>>("calleeSymbol")
|
||||
|
||||
+1
-1
@@ -796,7 +796,7 @@ object FirErrors {
|
||||
val IMPLICIT_BOXING_IN_IDENTITY_EQUALS: KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val INC_DEC_SHOULD_NOT_RETURN_UNIT: KtDiagnosticFactory0 by error0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT: KtDiagnosticFactory2<FirNamedFunctionSymbol, String> by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val PROPERTY_AS_OPERATOR: KtDiagnosticFactory1<FirPropertySymbol> by error1<PsiElement, FirPropertySymbol>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val NOT_FUNCTION_AS_OPERATOR: KtDiagnosticFactory2<String, FirBasedSymbol<*>> by error2<PsiElement, String, FirBasedSymbol<*>>(SourceElementPositioningStrategies.OPERATOR)
|
||||
val DSL_SCOPE_VIOLATION: KtDiagnosticFactory1<FirBasedSymbol<*>> by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
|
||||
// Type alias
|
||||
|
||||
+1
-1
@@ -533,7 +533,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"FORBIDDEN_IDENTITY_EQUALS",
|
||||
"INC_DEC_SHOULD_NOT_RETURN_UNIT",
|
||||
"ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT",
|
||||
"PROPERTY_AS_OPERATOR",
|
||||
"NOT_FUNCTION_AS_OPERATOR",
|
||||
"DSL_SCOPE_VIOLATION",
|
||||
"TOPLEVEL_TYPEALIASES_ONLY",
|
||||
"RECURSIVE_TYPEALIAS_EXPANSION",
|
||||
|
||||
+29
-13
@@ -11,23 +11,21 @@ import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConePropertyAsOperator
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeNotFunctionAsOperator
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.resolvedType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.Common) {
|
||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// PROPERTY_AS_OPERATOR can only happen for function calls and it's reported on the receiver expression.
|
||||
checkPropertyAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
||||
checkPropertyAsOperator(expression, expression.extensionReceiver, context, reporter)
|
||||
checkNotFunctionAsOperator(expression, expression.dispatchReceiver, context, reporter)
|
||||
checkNotFunctionAsOperator(expression, expression.extensionReceiver, context, reporter)
|
||||
val calleeReference = expression.calleeReference as? FirErrorNamedReference ?: return
|
||||
val diagnostic = calleeReference.diagnostic as? ConeUnresolvedNameError ?: return
|
||||
|
||||
@@ -39,7 +37,7 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyAsOperator(
|
||||
private fun checkNotFunctionAsOperator(
|
||||
callExpression: FirFunctionCall,
|
||||
receiver: FirExpression?,
|
||||
context: CheckerContext,
|
||||
@@ -47,9 +45,27 @@ object FirConventionFunctionCallChecker : FirFunctionCallChecker(MppCheckerKind.
|
||||
) {
|
||||
if (callExpression.dispatchReceiver?.resolvedType is ConeDynamicType) return
|
||||
// KT-61905: TODO: Return also in case of error type.
|
||||
val unwrapped = receiver?.unwrapSmartcastExpression()
|
||||
if (unwrapped !is FirPropertyAccessExpression) return
|
||||
val diagnostic = unwrapped.nonFatalDiagnostics.firstIsInstanceOrNull<ConePropertyAsOperator>() ?: return
|
||||
reporter.reportOn(callExpression.calleeReference.source, FirErrors.PROPERTY_AS_OPERATOR, diagnostic.symbol, context)
|
||||
val unwrapped = receiver?.unwrapSmartcastExpression() ?: return
|
||||
val nonFatalDiagnostics = when (unwrapped) {
|
||||
is FirQualifiedAccessExpression -> unwrapped.nonFatalDiagnostics
|
||||
is FirResolvedQualifier -> unwrapped.nonFatalDiagnostics
|
||||
else -> return
|
||||
}
|
||||
val diagnosticSymbol = nonFatalDiagnostics.firstIsInstanceOrNull<ConeNotFunctionAsOperator>()?.symbol ?: return
|
||||
when {
|
||||
unwrapped.resolvedType.classId!!.shortClassName == OperatorNameConventions.ITERATOR -> {
|
||||
reporter.reportOn(unwrapped.source, FirErrors.ITERATOR_MISSING, context)
|
||||
}
|
||||
else -> {
|
||||
// NOT_FUNCTION_AS_OPERATOR can only happen for function calls and it's reported on the receiver expression.
|
||||
reporter.reportOn(
|
||||
callExpression.calleeReference.source,
|
||||
FirErrors.NOT_FUNCTION_AS_OPERATOR,
|
||||
if (diagnosticSymbol is FirPropertySymbol) "Property" else "Object",
|
||||
diagnosticSymbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.resolve.calls.UnsafeCall
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FirForLoopChecker : FirBlockChecker(MppCheckerKind.Common) {
|
||||
|
||||
+4
-3
@@ -451,6 +451,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_FUNCTION_LA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_MULTIPLATFORM_COMPILATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_FUNCTION_AS_OPERATOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE
|
||||
@@ -521,7 +522,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_AS_OPERATOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
||||
@@ -2410,8 +2410,9 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
TO_STRING
|
||||
)
|
||||
map.put(
|
||||
PROPERTY_AS_OPERATOR,
|
||||
"Property ''{0}'' cannot be used as operator.",
|
||||
NOT_FUNCTION_AS_OPERATOR,
|
||||
"{0} ''{1}'' cannot be used as operator.",
|
||||
STRING,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
|
||||
Reference in New Issue
Block a user