[FIR] Introduce OPERATOR_CALL_ON_CONSTRUCTOR diagnostic

#KT-59943
This commit is contained in:
Evgeniy.Zhelenskiy
2023-10-20 21:17:01 +02:00
committed by Space Team
parent 649bbcf35f
commit f4d18da6a0
12 changed files with 56 additions and 24 deletions
@@ -1636,6 +1636,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.OPERATOR_CALL_ON_CONSTRUCTOR) { firDiagnostic ->
OperatorCallOnConstructorImpl(
firDiagnostic.a,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.INFIX_MODIFIER_REQUIRED) { firDiagnostic ->
InfixModifierRequiredImpl(
firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firDiagnostic.a),
@@ -1182,6 +1182,11 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val name: String
}
interface OperatorCallOnConstructor : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = OperatorCallOnConstructor::class
val name: String
}
interface InfixModifierRequired : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = InfixModifierRequired::class
val functionSymbol: KtFunctionLikeSymbol
@@ -1414,6 +1414,12 @@ internal class OperatorModifierRequiredImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OperatorModifierRequired
internal class OperatorCallOnConstructorImpl(
override val name: String,
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.OperatorCallOnConstructor
internal class InfixModifierRequiredImpl(
override val functionSymbol: KtFunctionLikeSymbol,
firDiagnostic: KtPsiDiagnostic,
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
import org.jetbrains.kotlin.fir.declarations.FirFunction
@@ -42,7 +41,6 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Inco
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.PrivateForInline
import java.util.Optional
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
@@ -498,6 +496,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<FirNamedFunctionSymbol>("functionSymbol")
parameter<String>("name")
}
val OPERATOR_CALL_ON_CONSTRUCTOR by error<PsiElement> {
parameter<String>("name")
}
val INFIX_MODIFIER_REQUIRED by error<PsiElement> {
parameter<FirNamedFunctionSymbol>("functionSymbol")
}
@@ -343,6 +343,7 @@ object FirErrors {
val REDUNDANT_OPEN_IN_INTERFACE by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.OPEN_MODIFIER)
val WRONG_MODIFIER_TARGET by error2<PsiElement, KtModifierKeywordToken, String>()
val OPERATOR_MODIFIER_REQUIRED by error2<PsiElement, FirNamedFunctionSymbol, String>()
val OPERATOR_CALL_ON_CONSTRUCTOR by error1<PsiElement, String>()
val INFIX_MODIFIER_REQUIRED by error1<PsiElement, FirNamedFunctionSymbol>()
val WRONG_MODIFIER_CONTAINING_DECLARATION by error2<PsiElement, KtModifierKeywordToken, String>()
val DEPRECATED_MODIFIER_CONTAINING_DECLARATION by warning2<PsiElement, KtModifierKeywordToken, String>()
@@ -204,6 +204,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
"INCOMPATIBLE_MODIFIERS",
"WRONG_MODIFIER_TARGET",
"OPERATOR_MODIFIER_REQUIRED",
"OPERATOR_CALL_ON_CONSTRUCTOR",
"INFIX_MODIFIER_REQUIRED",
"WRONG_MODIFIER_CONTAINING_DECLARATION",
"INAPPLICABLE_OPERATOR_MODIFIER",
@@ -127,7 +127,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAST_NEVER_SUCCEE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_CANNOT_BE_EXTENDED_DIRECTLY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_INHERITS_JAVA_SEALED_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SEALED_FUN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CLASS_LITERAL_LHS_NOT_A_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT
@@ -198,8 +197,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_SINCE_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_TYPE_PARAMETER_SYNTAX
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VERSION_REQUIREMENT_DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VERSION_REQUIREMENT_DEPRECATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DIVISION_BY_ZERO
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DSL_SCOPE_VIOLATION
@@ -382,8 +379,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE_DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER
@@ -461,6 +458,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULL_FOR_NONNULL_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_CALL_ON_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_MODIFIER_REQUIRED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY
@@ -599,8 +597,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPEALIAS_EXPANSI
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPEALIAS_EXPANSION_DEPRECATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
@@ -643,8 +641,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SUSPEND_TEST
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_INHERITANCE_FROM_JAVA_MEMBER_REFERENCING_KOTLIN_FUNCTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SEALED_FUN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SUSPEND_TEST
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
@@ -686,6 +685,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_OVERRIDDEN_BY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_INHERITANCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VERSION_REQUIREMENT_DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VERSION_REQUIREMENT_DEPRECATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VIRTUAL_MEMBER_HIDDEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VOLATILE_ON_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VOLATILE_ON_VALUE
@@ -1149,6 +1150,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members.")
map.put(WRONG_MODIFIER_TARGET, "Modifier ''{0}'' is not applicable to ''{1}''.", TO_STRING, STRING)
map.put(OPERATOR_MODIFIER_REQUIRED, "''operator'' modifier is required on ''{0}'' in ''{1}''.", TO_STRING, STRING)
map.put(OPERATOR_CALL_ON_CONSTRUCTOR, "Constructor of ''{0}'' cannot be used as an operator.", STRING)
map.put(INFIX_MODIFIER_REQUIRED, "''infix'' modifier is required on ''{0}''.", TO_STRING)
map.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''.", TO_STRING, STRING)
map.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''.", TO_STRING, STRING)
@@ -330,6 +330,7 @@ private fun mapInapplicableCandidateError(
is OperatorCallOfNonOperatorFunction ->
FirErrors.OPERATOR_MODIFIER_REQUIRED.createOn(source, rootCause.function, rootCause.function.name.asString())
is OperatorCallOfConstructor -> FirErrors.OPERATOR_CALL_ON_CONSTRUCTOR.createOn(source, rootCause.constructor.name.asString())
is UnstableSmartCast -> FirErrors.SMARTCAST_IMPOSSIBLE.createOn(
rootCause.argument.source,
rootCause.targetType,
@@ -673,14 +673,20 @@ internal object PostponedVariablesInitializerResolutionStage : ResolutionStage()
internal object CheckCallModifiers : CheckerStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
if (callInfo.callSite is FirFunctionCall) {
val functionSymbol = candidate.symbol as? FirNamedFunctionSymbol ?: return
when {
callInfo.callSite.origin == FirFunctionCallOrigin.Infix && !functionSymbol.fir.isInfix ->
sink.reportDiagnostic(InfixCallOfNonInfixFunction(functionSymbol))
callInfo.callSite.origin == FirFunctionCallOrigin.Operator && !functionSymbol.fir.isOperator ->
sink.reportDiagnostic(OperatorCallOfNonOperatorFunction(functionSymbol))
callInfo.isImplicitInvoke && !functionSymbol.fir.isOperator ->
sink.reportDiagnostic(OperatorCallOfNonOperatorFunction(functionSymbol))
when (val functionSymbol = candidate.symbol) {
is FirNamedFunctionSymbol -> when {
callInfo.callSite.origin == FirFunctionCallOrigin.Infix && !functionSymbol.fir.isInfix ->
sink.reportDiagnostic(InfixCallOfNonInfixFunction(functionSymbol))
callInfo.callSite.origin == FirFunctionCallOrigin.Operator && !functionSymbol.fir.isOperator ->
sink.reportDiagnostic(OperatorCallOfNonOperatorFunction(functionSymbol))
callInfo.isImplicitInvoke && !functionSymbol.fir.isOperator ->
sink.reportDiagnostic(OperatorCallOfNonOperatorFunction(functionSymbol))
}
is FirConstructorSymbol -> {
if (callInfo.callSite.origin == FirFunctionCallOrigin.Operator) {
sink.reportDiagnostic(OperatorCallOfConstructor(functionSymbol))
}
}
}
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
@@ -123,6 +124,7 @@ class ManyLambdaExpressionArguments(
class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(CONVENTION_ERROR)
class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(CONVENTION_ERROR)
class OperatorCallOfConstructor(val constructor: FirConstructorSymbol) : ResolutionDiagnostic(CONVENTION_ERROR)
class InferenceError(val constraintError: ConstraintSystemError) : ResolutionDiagnostic(constraintError.applicability)
class Unsupported(val message: String, val source: KtSourceElement?) : ResolutionDiagnostic(K2_UNSUPPORTED)
@@ -151,12 +151,12 @@ package testPackCase5
class Case5() {
fun f(c: Case5){
this + 1 //OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
c + 1 //OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
this <!OPERATOR_CALL_ON_CONSTRUCTOR!>+<!> 1 // OPERATOR_CALL_ON_CONSTRUCTOR/OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
c <!OPERATOR_CALL_ON_CONSTRUCTOR!>+<!> 1 // OPERATOR_CALL_ON_CONSTRUCTOR/OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
}
inner class plus constructor(val i:Int){
operator fun invoke(i:Int) {} //(1)
inner class plus /* (1) */ constructor(val i:Int){
operator fun invoke(i:Int) {}
}
}
@@ -151,12 +151,12 @@ package testPackCase5
class Case5() {
fun f(c: Case5){
this <!OPERATOR_MODIFIER_REQUIRED!>+<!> 1 //OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
c <!OPERATOR_MODIFIER_REQUIRED!>+<!> 1 //OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
this <!OPERATOR_MODIFIER_REQUIRED!>+<!> 1 // OPERATOR_CALL_ON_CONSTRUCTOR/OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
c <!OPERATOR_MODIFIER_REQUIRED!>+<!> 1 // OPERATOR_CALL_ON_CONSTRUCTOR/OPERATOR_MODIFIER_REQUIRED for class plus, resolved to (1)
}
inner class plus constructor(val i:Int){
operator fun invoke(i:Int) {} //(1)
inner class plus /* (1) */ constructor(val i:Int){
operator fun invoke(i:Int) {}
}
}