[FIR] Implement DELEGATION_NOT_TO_INTERFACE
This commit is contained in:
committed by
teamcityserver
parent
c3a6ba52f6
commit
fb9ce06ff5
+2
-2
@@ -1,9 +1,9 @@
|
||||
open class A
|
||||
|
||||
interface B : <!DELEGATION_IN_INTERFACE, INTERFACE_WITH_SUPERCLASS!>A<!> by <!UNRESOLVED_REFERENCE!>a<!> {
|
||||
interface B : <!DELEGATION_IN_INTERFACE, DELEGATION_NOT_TO_INTERFACE, INTERFACE_WITH_SUPERCLASS!>A<!> by <!UNRESOLVED_REFERENCE!>a<!> {
|
||||
val a: A
|
||||
}
|
||||
|
||||
val test = A()
|
||||
|
||||
interface C : <!DELEGATION_IN_INTERFACE, INTERFACE_WITH_SUPERCLASS!>A<!> by test
|
||||
interface C : <!DELEGATION_IN_INTERFACE, DELEGATION_NOT_TO_INTERFACE, INTERFACE_WITH_SUPERCLASS!>A<!> by test
|
||||
|
||||
+1
@@ -60,6 +60,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val NOT_A_LOOP_LABEL by error<PsiElement>()
|
||||
val VARIABLE_EXPECTED by error<PsiElement>(PositioningStrategy.ASSIGNMENT_LHS)
|
||||
val DELEGATION_IN_INTERFACE by error<PsiElement>()
|
||||
val DELEGATION_NOT_TO_INTERFACE by error<PsiElement>()
|
||||
val NESTED_CLASS_NOT_ALLOWED by error<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<String>("declaration")
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ object FirErrors {
|
||||
val NOT_A_LOOP_LABEL by error0<PsiElement>()
|
||||
val VARIABLE_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.ASSIGNMENT_LHS)
|
||||
val DELEGATION_IN_INTERFACE by error0<PsiElement>()
|
||||
val DELEGATION_NOT_TO_INTERFACE by error0<PsiElement>()
|
||||
val NESTED_CLASS_NOT_ALLOWED by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INCORRECT_CHARACTER_LITERAL by error0<PsiElement>()
|
||||
val EMPTY_CHARACTER_LITERAL by error0<PsiElement>()
|
||||
|
||||
@@ -521,6 +521,8 @@ private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
val Name.isDelegated: Boolean get() = asString().startsWith("<\$\$delegate_")
|
||||
|
||||
val ConeTypeProjection.isConflictingOrNotInvariant: Boolean get() = kind != ProjectionKind.INVARIANT || this is ConeKotlinTypeConflictingProjection
|
||||
|
||||
fun checkTypeMismatch(
|
||||
|
||||
+18
-8
@@ -7,17 +7,14 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkInconsistentTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isConflictingOrNotInvariant
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
@@ -85,6 +82,9 @@ object FirSupertypesChecker : FirClassChecker() {
|
||||
|
||||
val fullyExpandedType = coneType.fullyExpandedType(context.session)
|
||||
val symbol = fullyExpandedType.toSymbol(context.session)
|
||||
if (symbol is FirRegularClassSymbol && symbol.classId == StandardClassIds.Enum) {
|
||||
reporter.reportOn(superTypeRef.source, FirErrors.CLASS_CANNOT_BE_EXTENDED_DIRECTLY, symbol, context)
|
||||
}
|
||||
|
||||
if (coneType.typeArguments.isNotEmpty()) {
|
||||
for ((index, typeArgument) in coneType.typeArguments.withIndex()) {
|
||||
@@ -107,9 +107,19 @@ object FirSupertypesChecker : FirClassChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol is FirRegularClassSymbol && symbol.classId == StandardClassIds.Enum) {
|
||||
reporter.reportOn(superTypeRef.source, FirErrors.CLASS_CANNOT_BE_EXTENDED_DIRECTLY, symbol, context)
|
||||
for (subDeclaration in declaration.declarations) {
|
||||
if (subDeclaration is FirField) {
|
||||
if (subDeclaration.visibility == Visibilities.Local &&
|
||||
subDeclaration.name.isSpecial &&
|
||||
subDeclaration.name.isDelegated
|
||||
) {
|
||||
val subDeclFir = subDeclaration.returnTypeRef.toRegularClass(context.session)
|
||||
if (subDeclFir is FirRegularClass && subDeclFir.classKind != ClassKind.INTERFACE) {
|
||||
reporter.reportOn(subDeclaration.returnTypeRef.source, FirErrors.DELEGATION_NOT_TO_INTERFACE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_POSITION_VARIANCE
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING
|
||||
@@ -16,10 +17,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NOT_RENDERED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VARIABLE_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY
|
||||
@@ -99,6 +100,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATE_SPECIAL_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_NOT_TO_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_MODIFIER_PAIR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE
|
||||
@@ -414,6 +416,7 @@ class FirDefaultErrorMessages {
|
||||
map.put(NOT_A_LOOP_LABEL, "The label does not denote a loop") // *
|
||||
map.put(VARIABLE_EXPECTED, "Variable expected")
|
||||
map.put(DELEGATION_IN_INTERFACE, "Interfaces cannot use delegation")
|
||||
map.put(DELEGATION_NOT_TO_INTERFACE, "Only interfaces can be delegated to")
|
||||
map.put(NESTED_CLASS_NOT_ALLOWED, "{0} is not allowed here", TO_STRING)
|
||||
map.put(VAL_OR_VAR_ON_LOOP_PARAMETER, "''{0}'' on loop parameter is not allowed", TO_STRING)
|
||||
map.put(VAL_OR_VAR_ON_FUN_PARAMETER, "''{0}'' on function parameter is not allowed", TO_STRING)
|
||||
|
||||
@@ -2,7 +2,7 @@ open class Foo() {
|
||||
|
||||
}
|
||||
|
||||
class Barrr() : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> by Foo() {}
|
||||
class Barrr() : <!DELEGATION_NOT_TO_INTERFACE, SUPERTYPE_NOT_INITIALIZED!>Foo<!> by Foo() {}
|
||||
|
||||
interface T {}
|
||||
|
||||
@@ -12,4 +12,4 @@ open enum class EN() {
|
||||
A
|
||||
}
|
||||
|
||||
class Test2(e : EN) : EN by e {}
|
||||
class Test2(e : EN) : <!DELEGATION_NOT_TO_INTERFACE!>EN<!> by e {}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// JAVAC_EXPECTED_FILE
|
||||
class TestIface(r : Runnable) : Runnable by r {}
|
||||
|
||||
class TestObject(o : Object) : <!SUPERTYPE_NOT_INITIALIZED!>Object<!> by o {}
|
||||
class TestObject(o : Object) : <!DELEGATION_NOT_TO_INTERFACE, SUPERTYPE_NOT_INITIALIZED!>Object<!> by o {}
|
||||
|
||||
@@ -11,4 +11,4 @@ public abstract class A {
|
||||
// FILE: main.kt
|
||||
import foo.A
|
||||
|
||||
class DelegatedA(val a: A) : <!SUPERTYPE_NOT_INITIALIZED!>A<!> by a
|
||||
class DelegatedA(val a: A) : <!DELEGATION_NOT_TO_INTERFACE, SUPERTYPE_NOT_INITIALIZED!>A<!> by a
|
||||
|
||||
+6
@@ -138,6 +138,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.DELEGATION_NOT_TO_INTERFACE) { firDiagnostic ->
|
||||
DelegationNotToInterfaceImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.NESTED_CLASS_NOT_ALLOWED) { firDiagnostic ->
|
||||
NestedClassNotAllowedImpl(
|
||||
firDiagnostic.a,
|
||||
|
||||
+4
@@ -121,6 +121,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = DelegationInInterface::class
|
||||
}
|
||||
|
||||
abstract class DelegationNotToInterface : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = DelegationNotToInterface::class
|
||||
}
|
||||
|
||||
abstract class NestedClassNotAllowed : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = NestedClassNotAllowed::class
|
||||
abstract val declaration: String
|
||||
|
||||
+7
@@ -161,6 +161,13 @@ internal class DelegationInInterfaceImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class DelegationNotToInterfaceImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.DelegationNotToInterface(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class NestedClassNotAllowedImpl(
|
||||
override val declaration: String,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
|
||||
Reference in New Issue
Block a user