[FIR] Implement EXPANDED_TYPE_CANNOT_BE_INHERITED, PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
Add `starAsModifier` to `modifierSetPosition`
This commit is contained in:
committed by
teamcityserver
parent
937846b62d
commit
ec20f52707
+4
@@ -136,6 +136,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<String>("reason")
|
||||
}
|
||||
val CYCLIC_INHERITANCE_HIERARCHY by error<PsiElement>()
|
||||
val EXPANDED_TYPE_CANNOT_BE_INHERITED by error<KtTypeReference> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error<KtModifierListOwner>(PositioningStrategy.VARIANCE_MODIFIER)
|
||||
}
|
||||
|
||||
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
|
||||
|
||||
@@ -144,6 +144,8 @@ object FirErrors {
|
||||
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<KtTypeReference>()
|
||||
val SUPERTYPE_NOT_A_CLASS_OR_INTERFACE by error1<KtElement, String>()
|
||||
val CYCLIC_INHERITANCE_HIERARCHY by error0<PsiElement>()
|
||||
val EXPANDED_TYPE_CANNOT_BE_INHERITED by error1<KtTypeReference, ConeKotlinType>()
|
||||
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
||||
|
||||
// Constructor problems
|
||||
val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
@@ -521,6 +521,8 @@ private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
val ConeTypeProjection.isConflictingOrNotInvariant: Boolean get() = kind != ProjectionKind.INVARIANT || this is ConeKotlinTypeConflictingProjection
|
||||
|
||||
fun checkTypeMismatch(
|
||||
lValueOriginalType: ConeKotlinType,
|
||||
rValue: FirExpression,
|
||||
@@ -600,8 +602,8 @@ fun extractArgumentTypeRefAndSource(typeRef: FirTypeRef?, index: Int): FirTypeRe
|
||||
}
|
||||
|
||||
val typeArgument = currentTypeArguments?.elementAtOrNull(currentIndex)
|
||||
if (typeArgument is FirTypeProjectionWithVariance) {
|
||||
return FirTypeRefSource(typeArgument.typeRef, typeArgument.source)
|
||||
if (typeArgument is FirTypeProjection) {
|
||||
return FirTypeRefSource((typeArgument as? FirTypeProjectionWithVariance)?.typeRef, typeArgument.source)
|
||||
}
|
||||
} else if (delegatedTypeRef is FirFunctionTypeRef) {
|
||||
val valueParameters = delegatedTypeRef.valueParameters
|
||||
|
||||
+30
-4
@@ -7,7 +7,9 @@ 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.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
@@ -15,12 +17,11 @@ 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.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirSupertypesChecker : FirClassChecker() {
|
||||
@@ -80,6 +81,31 @@ object FirSupertypesChecker : FirClassChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val fullyExpandedType = coneType.fullyExpandedType(context.session)
|
||||
val symbol = fullyExpandedType.toSymbol(context.session)
|
||||
|
||||
if (coneType.typeArguments.isNotEmpty()) {
|
||||
for ((index, typeArgument) in coneType.typeArguments.withIndex()) {
|
||||
if (typeArgument.isConflictingOrNotInvariant) {
|
||||
val (_, argSource) = extractArgumentTypeRefAndSource(superTypeRef, index) ?: continue
|
||||
reporter.reportOn(
|
||||
argSource ?: superTypeRef.source,
|
||||
FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (symbol is FirRegularClassSymbol && symbol.fir.classKind == ClassKind.INTERFACE) {
|
||||
for (typeArgument in fullyExpandedType.typeArguments) {
|
||||
if (typeArgument.isConflictingOrNotInvariant) {
|
||||
reporter.reportOn(superTypeRef.source, FirErrors.EXPANDED_TYPE_CANNOT_BE_INHERITED, coneType, context)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -113,6 +113,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EQUALITY_NOT_APPLICABLE_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_IN_CONTRACT_DESCRIPTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPANDED_TYPE_CANNOT_BE_INHERITED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DECLARATION_WITH_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_DELEGATED_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_LATEINIT_PROPERTY
|
||||
@@ -250,6 +251,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_FUNCTION_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_PROPERTY_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY
|
||||
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_INITIALIZER_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
||||
@@ -458,6 +460,12 @@ class FirDefaultErrorMessages {
|
||||
map.put(SEALED_SUPERTYPE_IN_LOCAL_CLASS, "Local class cannot extend a sealed class")
|
||||
map.put(SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, "Supertype is not a class or interface", TO_STRING)
|
||||
map.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type")
|
||||
map.put(
|
||||
EXPANDED_TYPE_CANNOT_BE_INHERITED,
|
||||
"Type alias expands to {0}, which is not a class, an interface, or an object",
|
||||
RENDER_TYPE
|
||||
)
|
||||
map.put(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, "Projections are not allowed for immediate arguments of a supertype")
|
||||
|
||||
// Constructor problems
|
||||
map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects")
|
||||
|
||||
@@ -363,7 +363,7 @@ object PositioningStrategies {
|
||||
val LATEINIT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.LATEINIT_KEYWORD)
|
||||
|
||||
@JvmField
|
||||
val VARIANCE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD)
|
||||
val VARIANCE_MODIFIER: PositioningStrategy<KtModifierListOwner> = projectionPosition()
|
||||
|
||||
@JvmField
|
||||
val CONST_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.CONST_KEYWORD)
|
||||
@@ -414,11 +414,29 @@ object PositioningStrategies {
|
||||
return markElement(modifier)
|
||||
}
|
||||
}
|
||||
|
||||
throw IllegalStateException("None of the modifiers is found: " + listOf(*tokens))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun projectionPosition(): PositioningStrategy<KtModifierListOwner> {
|
||||
return object : PositioningStrategy<KtModifierListOwner>() {
|
||||
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
||||
if (element is KtTypeProjection && element.projectionKind == KtProjectionKind.STAR) {
|
||||
return markElement(element)
|
||||
}
|
||||
|
||||
val modifierList = element.modifierList.sure { "No modifier list, but modifier has been found by the analyzer" }
|
||||
modifierList.getModifier(KtTokens.IN_KEYWORD)?.let { return markElement(it) }
|
||||
modifierList.getModifier(KtTokens.OUT_KEYWORD)?.let { return markElement(it) }
|
||||
|
||||
throw IllegalStateException("None of the modifiers is found: in, out")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val ARRAY_ACCESS: PositioningStrategy<KtArrayAccessExpression> = object : PositioningStrategy<KtArrayAccessExpression>() {
|
||||
override fun mark(element: KtArrayAccessExpression): List<TextRange> {
|
||||
|
||||
@@ -3,4 +3,4 @@ interface B<T> {}
|
||||
interface C<T> {}
|
||||
interface D<T> {}
|
||||
|
||||
interface Test : A<in Int>, B<out Int>, C<*>??<!NULLABLE_SUPERTYPE!>?<!>, D<Int> {}
|
||||
interface Test : A<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>in<!> Int>, B<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>out<!> Int>, C<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>>??<!NULLABLE_SUPERTYPE!>?<!>, D<Int> {}
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ class Generic<T1> {
|
||||
inner class Test1 : GI<T1>()
|
||||
inner class Test2 : <!UNRESOLVED_REFERENCE!>GIInt<!>()
|
||||
inner class Test3 : GIStar()
|
||||
inner class Test3a : test.Generic<*>.Inner()
|
||||
inner class Test3a : test.Generic<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>>.Inner()
|
||||
|
||||
inner class Test4<T2> : GG<T1, T2>()
|
||||
inner class Test5 : GG<T1, Int>()
|
||||
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
open class C<T>
|
||||
|
||||
typealias CStar = C<*>
|
||||
typealias CIn = C<in Int>
|
||||
typealias COut = C<out Int>
|
||||
typealias CT<T> = C<T>
|
||||
|
||||
class Test1 : CStar()
|
||||
class Test2 : CIn()
|
||||
class Test3 : COut()
|
||||
|
||||
class Test4 : CStar {
|
||||
constructor() : super()
|
||||
}
|
||||
|
||||
class Test5 : CT<*>()
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
open class C<T>
|
||||
|
||||
typealias CStar = C<*>
|
||||
|
||||
Vendored
+10
-10
@@ -15,18 +15,18 @@ typealias InStar = In<*>
|
||||
typealias InIn = In<<!REDUNDANT_PROJECTION!>in<!> Int>
|
||||
typealias InT<T> = In<T>
|
||||
|
||||
class Test1 : InvStar
|
||||
class Test2 : InvIn
|
||||
class Test3 : InvOut
|
||||
class Test4 : InvT<*>
|
||||
class Test1 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvStar<!>
|
||||
class Test2 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvIn<!>
|
||||
class Test3 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvOut<!>
|
||||
class Test4 : InvT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>>
|
||||
class Test5 : InvT<InvT<*>>
|
||||
|
||||
class Test6 : OutStar
|
||||
class Test7 : OutOut
|
||||
class Test6 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>OutStar<!>
|
||||
class Test7 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>OutOut<!>
|
||||
class Test8 : OutT<Int>
|
||||
class Test9 : OutT<<!REDUNDANT_PROJECTION!>out<!> Int>
|
||||
class Test9 : OutT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, REDUNDANT_PROJECTION!>out<!> Int>
|
||||
|
||||
class Test10 : InStar
|
||||
class Test11 : InIn
|
||||
class Test10 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InStar<!>
|
||||
class Test11 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InIn<!>
|
||||
class Test12 : InT<Int>
|
||||
class Test13 : InT<<!REDUNDANT_PROJECTION!>in<!> Int>
|
||||
class Test13 : InT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, REDUNDANT_PROJECTION!>in<!> Int>
|
||||
|
||||
+13
@@ -412,6 +412,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPANDED_TYPE_CANNOT_BE_INHERITED) { firDiagnostic ->
|
||||
ExpandedTypeCannotBeInheritedImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE) { firDiagnostic ->
|
||||
ProjectionInImmediateArgumentToSupertypeImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic ->
|
||||
ConstructorInObjectImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
|
||||
+9
@@ -307,6 +307,15 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = CyclicInheritanceHierarchy::class
|
||||
}
|
||||
|
||||
abstract class ExpandedTypeCannotBeInherited : KtFirDiagnostic<KtTypeReference>() {
|
||||
override val diagnosticClass get() = ExpandedTypeCannotBeInherited::class
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class ProjectionInImmediateArgumentToSupertype : KtFirDiagnostic<KtModifierListOwner>() {
|
||||
override val diagnosticClass get() = ProjectionInImmediateArgumentToSupertype::class
|
||||
}
|
||||
|
||||
abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() {
|
||||
override val diagnosticClass get() = ConstructorInObject::class
|
||||
}
|
||||
|
||||
+15
@@ -479,6 +479,21 @@ internal class CyclicInheritanceHierarchyImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExpandedTypeCannotBeInheritedImpl(
|
||||
override val type: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ExpandedTypeCannotBeInherited(), KtAbstractFirDiagnostic<KtTypeReference> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ProjectionInImmediateArgumentToSupertypeImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ProjectionInImmediateArgumentToSupertype(), KtAbstractFirDiagnostic<KtModifierListOwner> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ConstructorInObjectImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ interface B<T> {}
|
||||
interface C<T> {}
|
||||
interface D<T> {}
|
||||
|
||||
interface Test : A<in Int>, B<out Int>, C<*>??<error descr="[NULLABLE_SUPERTYPE] A supertype cannot be nullable">?</error>, D<Int> {}
|
||||
interface Test : A<<error descr="[PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE] Projections are not allowed for immediate arguments of a supertype">in</error> Int>, B<<error descr="[PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE] Projections are not allowed for immediate arguments of a supertype">out</error> Int>, C<<error descr="[PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE] Projections are not allowed for immediate arguments of a supertype">*</error>>??<error descr="[NULLABLE_SUPERTYPE] A supertype cannot be nullable">?</error>, D<Int> {}
|
||||
|
||||
Reference in New Issue
Block a user