FIR checker: report type parameters on anonymous objects
This commit is contained in:
committed by
TeamCityServer
parent
4d9102f749
commit
a18daa5d62
+1
@@ -500,6 +500,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<FirRegularClassSymbol>("outer")
|
parameter<FirRegularClassSymbol>("outer")
|
||||||
}
|
}
|
||||||
val TYPE_PARAMETERS_IN_OBJECT by error<PsiElement>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
val TYPE_PARAMETERS_IN_OBJECT by error<PsiElement>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||||
|
val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error<PsiElement>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||||
val ILLEGAL_PROJECTION_USAGE by error<PsiElement>()
|
val ILLEGAL_PROJECTION_USAGE by error<PsiElement>()
|
||||||
val TYPE_PARAMETERS_IN_ENUM by error<PsiElement>()
|
val TYPE_PARAMETERS_IN_ENUM by error<PsiElement>()
|
||||||
val CONFLICTING_PROJECTION by error<KtTypeProjection>(PositioningStrategy.VARIANCE_MODIFIER) {
|
val CONFLICTING_PROJECTION by error<KtTypeProjection>(PositioningStrategy.VARIANCE_MODIFIER) {
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ object FirErrors {
|
|||||||
val NO_TYPE_ARGUMENTS_ON_RHS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
|
val NO_TYPE_ARGUMENTS_ON_RHS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
|
||||||
val OUTER_CLASS_ARGUMENTS_REQUIRED by error1<PsiElement, FirRegularClassSymbol>()
|
val OUTER_CLASS_ARGUMENTS_REQUIRED by error1<PsiElement, FirRegularClassSymbol>()
|
||||||
val TYPE_PARAMETERS_IN_OBJECT by error0<PsiElement>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
val TYPE_PARAMETERS_IN_OBJECT by error0<PsiElement>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||||
|
val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error0<PsiElement>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||||
val ILLEGAL_PROJECTION_USAGE by error0<PsiElement>()
|
val ILLEGAL_PROJECTION_USAGE by error0<PsiElement>()
|
||||||
val TYPE_PARAMETERS_IN_ENUM by error0<PsiElement>()
|
val TYPE_PARAMETERS_IN_ENUM by error0<PsiElement>()
|
||||||
val CONFLICTING_PROJECTION by error1<KtTypeProjection, ConeKotlinType>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
val CONFLICTING_PROJECTION by error1<KtTypeProjection, ConeKotlinType>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
||||||
|
|||||||
+1
-1
@@ -72,6 +72,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirMemberFunctionsChecker,
|
FirMemberFunctionsChecker,
|
||||||
FirMemberPropertiesChecker,
|
FirMemberPropertiesChecker,
|
||||||
FirImplementationMismatchChecker,
|
FirImplementationMismatchChecker,
|
||||||
|
FirTypeParametersInObjectChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
@@ -89,7 +90,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirMethodOfAnyImplementedInInterfaceChecker,
|
FirMethodOfAnyImplementedInInterfaceChecker,
|
||||||
FirDataClassPrimaryConstructorChecker,
|
FirDataClassPrimaryConstructorChecker,
|
||||||
FirPrimaryConstructorSuperTypeChecker,
|
FirPrimaryConstructorSuperTypeChecker,
|
||||||
FirTypeParametersInObjectChecker,
|
|
||||||
FirFunInterfaceDeclarationChecker,
|
FirFunInterfaceDeclarationChecker,
|
||||||
FirNestedClassChecker,
|
FirNestedClassChecker,
|
||||||
FirInlineClassDeclarationChecker,
|
FirInlineClassDeclarationChecker,
|
||||||
|
|||||||
+21
-4
@@ -5,21 +5,38 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
|
|
||||||
object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
object FirTypeParametersInObjectChecker : FirClassChecker() {
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration.classKind != ClassKind.OBJECT) {
|
if (declaration.classKind != ClassKind.OBJECT) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.typeParameters.isNotEmpty()) {
|
when (declaration) {
|
||||||
reporter.reportOn(declaration.source, FirErrors.TYPE_PARAMETERS_IN_OBJECT, context)
|
is FirRegularClass -> if (declaration.typeParameters.isNotEmpty()) {
|
||||||
|
reporter.reportOn(declaration.source, FirErrors.TYPE_PARAMETERS_IN_OBJECT, context)
|
||||||
|
}
|
||||||
|
is FirAnonymousObject -> if (declaration.source?.getChild(KtNodeTypes.TYPE_PARAMETER_LIST, depth = 1) != null) {
|
||||||
|
val diagnosticFactory =
|
||||||
|
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitTypeParametersInAnonymousObjects)) {
|
||||||
|
FirErrors.TYPE_PARAMETERS_IN_OBJECT
|
||||||
|
} else {
|
||||||
|
FirErrors.TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT
|
||||||
|
}
|
||||||
|
reporter.reportOn(declaration.source, diagnosticFactory, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -406,6 +406,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NO
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_CANT_BE_USED_FOR_CONST_VAL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ENUM
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ENUM
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_OBJECT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_OBJECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_NOT_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_NOT_ALLOWED
|
||||||
@@ -825,6 +826,8 @@ class FirDefaultErrorMessages {
|
|||||||
RENDER_CLASS_OR_OBJECT_NAME
|
RENDER_CLASS_OR_OBJECT_NAME
|
||||||
)
|
)
|
||||||
map.put(TYPE_PARAMETERS_IN_OBJECT, "Type parameters are not allowed for objects")
|
map.put(TYPE_PARAMETERS_IN_OBJECT, "Type parameters are not allowed for objects")
|
||||||
|
map.put(TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT, "Type parameters for anonymous objects are deprecated")
|
||||||
|
|
||||||
// map.put(ILLEGAL_PROJECTION_USAGE, ...) // &
|
// map.put(ILLEGAL_PROJECTION_USAGE, ...) // &
|
||||||
map.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters")
|
map.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters")
|
||||||
map.put(
|
map.put(
|
||||||
|
|||||||
+7
-7
@@ -3,23 +3,23 @@
|
|||||||
// ISSUE: KT-28999
|
// ISSUE: KT-28999
|
||||||
|
|
||||||
fun case_1() {
|
fun case_1() {
|
||||||
val x = object<T> { } // type of x is <anonymous object><T>
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> { } // type of x is <anonymous object><T>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_2() {
|
fun case_2() {
|
||||||
val x = object<T : Number, K: Comparable<K>> { }
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T : Number, K: Comparable<K>><!> { }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_3() {
|
fun case_3() {
|
||||||
val x = object<T> <!SYNTAX!>where T : Comparable<T><!> { } // ERROR: Where clause is not allowed for objects
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> <!SYNTAX!>where T : Comparable<T><!> { } // ERROR: Where clause is not allowed for objects
|
||||||
}
|
}
|
||||||
|
|
||||||
val x = object<T, K: Comparable<K>> {
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T, K: Comparable<K>><!> {
|
||||||
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!> // OK
|
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!> // OK
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_4() {
|
fun case_4() {
|
||||||
val x = object<T> {
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> {
|
||||||
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!>
|
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ fun case_4() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> case_5() {
|
inline fun <reified T> case_5() {
|
||||||
val x = object<T> {
|
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> {
|
||||||
fun test() = 10 as T
|
fun test() = 10 as T
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ inline fun <reified T> case_5() {
|
|||||||
<!UNRESOLVED_REFERENCE!>println<!>(z)
|
<!UNRESOLVED_REFERENCE!>println<!>(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
val a = object<A> {
|
val a = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><A><!> {
|
||||||
fun test() = 42 as <!UNRESOLVED_REFERENCE!>A<!>
|
fun test() = 42 as <!UNRESOLVED_REFERENCE!>A<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+7
-7
@@ -3,23 +3,23 @@
|
|||||||
// ISSUE: KT-28999
|
// ISSUE: KT-28999
|
||||||
|
|
||||||
fun case_1() {
|
fun case_1() {
|
||||||
val x = object<T> { } // type of x is <anonymous object><T>
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> { } // type of x is <anonymous object><T>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_2() {
|
fun case_2() {
|
||||||
val x = object<T : Number, K: Comparable<K>> { }
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T : Number, K: Comparable<K>><!> { }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_3() {
|
fun case_3() {
|
||||||
val x = object<T> <!SYNTAX!>where T : Comparable<T><!> { } // ERROR: Where clause is not allowed for objects
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> <!SYNTAX!>where T : Comparable<T><!> { } // ERROR: Where clause is not allowed for objects
|
||||||
}
|
}
|
||||||
|
|
||||||
val x = object<T, K: Comparable<K>> {
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T, K: Comparable<K>><!> {
|
||||||
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!> // OK
|
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!> // OK
|
||||||
}
|
}
|
||||||
|
|
||||||
fun case_4() {
|
fun case_4() {
|
||||||
val x = object<T> {
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> {
|
||||||
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!>
|
fun test() = 10 as <!UNRESOLVED_REFERENCE!>T<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ fun case_4() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> case_5() {
|
inline fun <reified T> case_5() {
|
||||||
val x = object<T> {
|
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> {
|
||||||
fun test() = 10 as T
|
fun test() = 10 as T
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ inline fun <reified T> case_5() {
|
|||||||
<!UNRESOLVED_REFERENCE!>println<!>(z)
|
<!UNRESOLVED_REFERENCE!>println<!>(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
val a = object<A> {
|
val a = object<!TYPE_PARAMETERS_IN_OBJECT!><A><!> {
|
||||||
fun test() = 42 as <!UNRESOLVED_REFERENCE!>A<!>
|
fun test() = 42 as <!UNRESOLVED_REFERENCE!>A<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -1486,6 +1486,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT) { firDiagnostic ->
|
||||||
|
TypeParametersInAnonymousObjectImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.ILLEGAL_PROJECTION_USAGE) { firDiagnostic ->
|
add(FirErrors.ILLEGAL_PROJECTION_USAGE) { firDiagnostic ->
|
||||||
IllegalProjectionUsageImpl(
|
IllegalProjectionUsageImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic,
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
|||||||
+4
@@ -1057,6 +1057,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = TypeParametersInObject::class
|
override val diagnosticClass get() = TypeParametersInObject::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class TypeParametersInAnonymousObject : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = TypeParametersInAnonymousObject::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class IllegalProjectionUsage : KtFirDiagnostic<PsiElement>() {
|
abstract class IllegalProjectionUsage : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = IllegalProjectionUsage::class
|
override val diagnosticClass get() = IllegalProjectionUsage::class
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -1691,6 +1691,13 @@ internal class TypeParametersInObjectImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class TypeParametersInAnonymousObjectImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.TypeParametersInAnonymousObject(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class IllegalProjectionUsageImpl(
|
internal class IllegalProjectionUsageImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic,
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user