[FIR] Report separate error for delegated constructor call to interface

#KT-59216 Fixed
This commit is contained in:
Kirill Rakhman
2023-06-23 13:50:34 +02:00
committed by Space Team
parent 5abab2197b
commit e7c213e06e
19 changed files with 78 additions and 21 deletions
@@ -152,6 +152,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val CALL_RESOLUTION by object : DiagnosticGroup("Call resolution") {
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error<KtExpression>()
val NO_CONSTRUCTOR by error<PsiElement>(PositioningStrategy.VALUE_ARGUMENTS_LIST)
val FUNCTION_CALL_EXPECTED by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<String>("functionName")
parameter<Boolean>("hasValueParameters")
@@ -76,6 +76,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
USELESS_ELVIS,
NAME_OF_NAMED_ARGUMENT,
VALUE_ARGUMENTS,
VALUE_ARGUMENTS_LIST,
SUPERTYPES_LIST,
RETURN_WITH_LABEL,
PROPERTY_INITIALIZER,
@@ -165,6 +165,7 @@ object FirErrors {
// Call resolution
val CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS by error0<KtExpression>()
val NO_CONSTRUCTOR by error0<PsiElement>(SourceElementPositioningStrategies.VALUE_ARGUMENTS_LIST)
val FUNCTION_CALL_EXPECTED by error2<PsiElement, String, Boolean>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val ILLEGAL_SELECTOR by error0<PsiElement>()
val NO_RECEIVER_ALLOWED by error0<PsiElement>()
@@ -139,6 +139,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_GE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_WITH_NON_CONST_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONTRACT_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLE_IN_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_GENERIC_UPPER_BOUND
@@ -736,6 +737,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
TO_STRING
)
map.put(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, "Cannot create an instance of an abstract class")
map.put(NO_CONSTRUCTOR, "This type does not have a constructor.")
map.put(FUNCTION_CALL_EXPECTED, "Function invocation ''{0}({1})'' expected", TO_STRING, FUNCTION_PARAMETERS)
map.put(
FUNCTION_EXPECTED,
@@ -58,6 +58,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeUnresolvedTypeQualifierError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.qualifier)
is ConeFunctionCallExpectedError -> FirErrors.FUNCTION_CALL_EXPECTED.createOn(source, this.name.asString(), this.hasValueParameters)
is ConeFunctionExpectedError -> FirErrors.FUNCTION_EXPECTED.createOn(source, this.expression, this.type)
is ConeNoConstructorError -> FirErrors.NO_CONSTRUCTOR.createOn(callOrAssignmentSource ?: source)
is ConeResolutionToClassifierError -> when (this.candidateSymbol.classKind) {
ClassKind.INTERFACE -> FirErrors.INTERFACE_AS_FUNCTION.createOn(source, this.candidateSymbol)
ClassKind.CLASS -> when {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.isReferredViaField
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
@@ -697,10 +698,14 @@ class FirCallResolver(
}
candidates.isEmpty() -> {
if (name.asString() == "invoke" && explicitReceiver is FirConstExpression<*>) {
ConeFunctionExpectedError(explicitReceiver.value?.toString() ?: "", explicitReceiver.typeRef.coneType)
} else {
ConeUnresolvedNameError(name)
when {
name.asString() == "invoke" && explicitReceiver is FirConstExpression<*> ->
ConeFunctionExpectedError(
explicitReceiver.value?.toString() ?: "",
explicitReceiver.typeRef.coneType,
)
reference is FirSuperReference && (reference.superTypeRef.firClassLike(session) as? FirClass)?.isInterface == true -> ConeNoConstructorError
else -> ConeUnresolvedNameError(name)
}
}
@@ -82,6 +82,10 @@ class ConeFunctionExpectedError(val expression: String, val type: ConeKotlinType
override val reason: String get() = "Expression '$expression' of type '$type' cannot be invoked as a function"
}
object ConeNoConstructorError : ConeDiagnostic {
override val reason: String get() = "This type does not have a constructor"
}
class ConeResolutionToClassifierError(
override val candidate: AbstractCandidate,
override val candidateSymbol: FirRegularClassSymbol