diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 955b7fbbbcb..dbbf45b7420 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -212,6 +212,11 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error(PositioningStrategy.DECLARATION_NAME) } + val REFLECTION by object : DiagnosticGroup("Reflection") { + val CLASS_LITERAL_LHS_NOT_A_CLASS by error() + val NULLABLE_TYPE_IN_CLASS_LITERAL_LHS by error() + } + val OVERRIDES by object : DiagnosticGroup("overrides") { val NOTHING_TO_OVERRIDE by error(PositioningStrategy.OVERRIDE_MODIFIER) { parameter("declaration") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index c96f58c1ea8..d5e745662b5 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -171,6 +171,10 @@ object FirErrors { val GENERIC_THROWABLE_SUBCLASS by error0() val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0(SourceElementPositioningStrategies.DECLARATION_NAME) + // Reflection + val CLASS_LITERAL_LHS_NOT_A_CLASS by error0() + val NULLABLE_TYPE_IN_CLASS_LITERAL_LHS by error0() + // overrides val NOTHING_TO_OVERRIDE by error1(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChild.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChild.kt index e173eec7cb2..59e78603f95 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChild.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChild.kt @@ -9,16 +9,14 @@ import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.fir.* -fun FirSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1): FirSourceElement? { - return getChild(setOf(type), index, depth) -} +fun FirSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1): FirSourceElement? = + getChild(setOf(type), index, depth) -fun FirSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1): FirSourceElement? { - return getChild(types.types.toSet(), index, depth) -} +fun FirSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1): FirSourceElement? = + getChild(types.types.toSet(), index, depth) -fun FirSourceElement.getChild(types: Set, index: Int = 0, depth: Int = -1): FirSourceElement? { - return when (this) { +fun FirSourceElement.getChild(types: Set, index: Int = 0, depth: Int = -1): FirSourceElement? = + when (this) { is FirPsiSourceElement<*> -> { getChild(types, index, depth) } @@ -27,7 +25,6 @@ fun FirSourceElement.getChild(types: Set, index: Int = 0, depth: I } else -> null } -} private fun FirPsiSourceElement<*>.getChild(types: Set, index: Int, depth: Int): FirSourceElement? { val visitor = PsiElementFinderByType(types, index, depth) @@ -36,6 +33,5 @@ private fun FirPsiSourceElement<*>.getChild(types: Set, index: Int private fun FirLightSourceElement.getChild(types: Set, index: Int, depth: Int): FirSourceElement? { val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth) - return visitor.find(lighterASTNode)?.toFirLightSourceElement(treeStructure) -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/LighterTreeElementFinderByType.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/LighterTreeElementFinderByType.kt index f8ccd676417..ab6b90c4f86 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/LighterTreeElementFinderByType.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/LighterTreeElementFinderByType.kt @@ -21,7 +21,7 @@ class LighterTreeElementFinderByType( return visitNode(node, 0) } - fun visitNode(node: LighterASTNode, currentDepth: Int): LighterASTNode? { + private fun visitNode(node: LighterASTNode, currentDepth: Int): LighterASTNode? { if (node.tokenType in types) { if (index == 0) { return node @@ -44,4 +44,5 @@ class LighterTreeElementFinderByType( tree.getChildren(this, ref) return ref.get()?.filterNotNull() ?: emptyList() } -} \ No newline at end of file + +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/PsiElementFinderByType.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/PsiElementFinderByType.kt index c72d0f6b83f..0fc7dee9a8f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/PsiElementFinderByType.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/PsiElementFinderByType.kt @@ -18,7 +18,7 @@ class PsiElementFinderByType( return visitElement(root, 0) } - fun visitElement(element: PsiElement, currentDepth: Int): PsiElement? { + private fun visitElement(element: PsiElement, currentDepth: Int): PsiElement? { if (element.node.elementType in types) { if (index == 0) { return element @@ -28,11 +28,12 @@ class PsiElementFinderByType( if (currentDepth == depth) return null - for (children in element.allChildren) { - val result = visitElement(children, currentDepth + 1) + for (child in element.allChildren) { + val result = visitElement(child, currentDepth + 1) if (result != null) return result } return null } -} \ No newline at end of file + +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt new file mode 100644 index 00000000000..a328e52f99c --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.fir.FirFakeSourceElementKind +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +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.getChild +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner +import org.jetbrains.kotlin.fir.expressions.FirGetClassCall +import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.lexer.KtTokens.QUEST + +object FirGetClassCallChecker : FirBasicExpressionChecker() { + override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { + if (expression !is FirGetClassCall) return + val source = expression.source ?: return + if (source.kind is FirFakeSourceElementKind) return + + val argument = expression.argument as? FirResolvedQualifier ?: return + // Note that raw FIR drops marked nullability "?" in, e.g., `A?::class`, `A::class`, or `A?::class`. + // That is, AST structures for those expressions have token type QUEST, whereas FIR element doesn't have any information about it. + // + // A?::class -> CLASS_LITERAL_EXPRESSION(REFERENCE_EXPRESSION QUEST COLONCOLON "class") + // A::class -> CLASS_LITERAL_EXPRESSION(REFERENCE_EXPRESSION TYPE_ARGUMENT_LIST COLONCOLON "class") + // A?::class -> CLASS_LITERAL_EXPRESSION(REFERENCE_EXPRESSION TYPE_ARGUMENT_LIST QUEST COLONCOLON "class") + // where TYPE_ARGUMENT_LIST may have QUEST in it + // + // Only the 2nd example is valid, and we want to check if token type QUEST doesn't exist at the same level as COLONCOLON. + val markedNullable = source.getChild(QUEST, depth = 1) != null + if (argument.isNullableLHSForCallableReference || markedNullable) { + reporter.reportOn(source, FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, context) + return + } + // TODO: differentiate RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS + if (argument.typeArguments.isNotEmpty() && !argument.typeRef.coneType.isAllowedInClassLiteral(context)) { + val typeParameters = (argument.symbol?.fir as? FirTypeParameterRefsOwner)?.typeParameters + // Among type parameter references, only count actual type parameter while discarding [FirOuterClassTypeParameterRef] + val expectedTypeArgumentSize = typeParameters?.filterIsInstance()?.size ?: 0 + if (expectedTypeArgumentSize != argument.typeArguments.size) { + // Will be reported as WRONG_NUMBER_OF_TYPE_ARGUMENTS + return + } + reporter.reportOn(source, FirErrors.CLASS_LITERAL_LHS_NOT_A_CLASS, context) + } + } + + private fun ConeKotlinType.isAllowedInClassLiteral(context: CheckerContext): Boolean = + when (this) { + is ConeClassLikeType -> { + if (isNonPrimitiveArray) { + typeArguments.none { typeArgument -> + when (typeArgument) { + is ConeStarProjection -> true + is ConeKotlinTypeProjection -> !typeArgument.type.isAllowedInClassLiteral(context) + } + } + } else + typeArguments.isEmpty() + } + is ConeTypeParameterType -> this.lookupTag.typeParameterSymbol.fir.isReified + else -> false + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 1a369ce9bd6..68bb00f4095 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_REPLACED_W import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CAN_BE_VAL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE 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.COMPONENT_FUNCTION_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_MISSING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_ON_NULLABLE @@ -114,6 +115,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_TYPE_FOR_TYPE_PARAMETER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER @@ -360,6 +362,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(REIFIED_TYPE_IN_CATCH_CLAUSE, "Reified type is forbidden for catch parameter") map.put(TYPE_PARAMETER_IN_CATCH_CLAUSE, "Type parameter is forbidden for catch parameter") + // Reflection + map.put(CLASS_LITERAL_LHS_NOT_A_CLASS, "Only classes are allowed on the left hand side of a class literal") + map.put(NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, "Type in a class literal must not be nullable") + // Overrides map.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", DECLARATION_NAME) map.put(OVERRIDING_FINAL_MEMBER, "''{0}'' in ''{1}'' is final and cannot be overridden", NAME, TO_STRING) diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index 6022624fcc4..39ba8e1152e 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -69,6 +69,10 @@ val ConeKotlinType.isArrayType: Boolean return isBuiltinType(StandardClassIds.Array, false) || StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) } } +// Same as [KotlinBuiltIns#isNonPrimitiveArray] +val ConeKotlinType.isNonPrimitiveArray: Boolean + get() = this is ConeClassLikeType && lookupTag.classId == StandardClassIds.Array + private val builtinUnsignedTypes = setOf(StandardClassIds.UInt, StandardClassIds.UByte, StandardClassIds.ULong, StandardClassIds.UShort) val ConeKotlinType.isUnsignedTypeOrNullableUnsignedType: Boolean get() = isAnyOfBuiltinType(builtinUnsignedTypes) diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index fb52cf9a047..7e9d8df84e2 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.* object CommonExpressionCheckers : ExpressionCheckers() { override val basicExpressionCheckers: Set = setOf( FirAnonymousFunctionChecker, + FirGetClassCallChecker, ) override val qualifiedAccessCheckers: Set = setOf( diff --git a/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt index 28e72987269..2a1e83866cc 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/genericArrays.fir.kt @@ -1,11 +1,11 @@ import kotlin.reflect.KClass -fun f1(): KClass> = Array::class -fun f2(): KClass>> = Array>::class +fun f1(): KClass> = Array::class +fun f2(): KClass>> = Array>::class inline fun f3() = Array::class inline fun f4() = Array>::class -fun f5(): KClass> = Array<*>::class +fun f5(): KClass> = Array<*>::class fun f6(): KClass> = Array::class -fun f7() = Array>::class -fun f8() = Array?>::class -fun f9() = Array?>::class +fun f7() = Array>::class +fun f8() = Array?>::class +fun f9() = Array?>::class diff --git a/compiler/testData/diagnostics/tests/classLiteral/genericClasses.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/genericClasses.fir.kt index 816f61b5303..b424eeac499 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/genericClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/genericClasses.fir.kt @@ -7,20 +7,20 @@ class A { } val a1 = A::class -val a2 = A<*>::class -val a3 = A::class -val a4 = A::class +val a2 = A<*>::class +val a3 = A::class +val a4 = A::class val n1 = A.Nested::class -val n2 = A.Nested<*>::class +val n2 = A.Nested<*>::class val i1 = A.Inner::class -val i2 = A<*>.Inner<*>::class -val i3 = A.Inner::class +val i2 = A<*>.Inner<*>::class +val i3 = A.Inner::class val m1 = Map::class -val m2 = Map::class +val m2 = Map::class val m3 = Map.Entry::class val b1 = Int::class -val b2 = Nothing::class \ No newline at end of file +val b2 = Nothing::class diff --git a/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.fir.kt index 3619f534be9..6fd94cfa680 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.fir.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/nonClassesOnLHS.fir.kt @@ -2,11 +2,11 @@ class A -val a1 = A?::class -val a2 = A??::class +val a1 = A?::class +val a2 = A??::class -val l1 = List?::class -val l2 = List?::class +val l1 = List?::class +val l2 = List?::class fun foo() { val t1 = T::class diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.fir.kt b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.fir.kt index 9a5435fc1a9..ed339f1d945 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.fir.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotationWithKClass.fir.kt @@ -18,7 +18,7 @@ fun test2() {} @Foo([Array::class]) fun test3() {} -@Foo([Gen::class]) +@Foo([Gen::class]) fun test4() {} @Foo([""]) diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kClassInSignature.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/kClassInSignature.fir.kt index 9a1eca03800..f6b043ae163 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/kClassInSignature.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/kClassInSignature.fir.kt @@ -10,7 +10,7 @@ fun test5() = listOf(T::class) fun test6(): kotlin.reflect.KClass = T::class fun test7(): kotlin.reflect.KClass<*> = T::class -fun test8() = String?::class +fun test8() = String?::class fun listOf(e: T): List = null!! diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundClassLiteral.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundClassLiteral.fir.kt index 12d5a76b87e..660ac65c9b4 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundClassLiteral.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundClassLiteral.fir.kt @@ -13,6 +13,6 @@ enum class E { val ok4 = E.Entry::class val fail1 = ""::class -val fail2 = String?::class +val fail2 = String?::class val fail3 = (C)::class val fail4 = (C.Companion)::class diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 1130250376c..934d379ee29 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -679,6 +679,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.CLASS_LITERAL_LHS_NOT_A_CLASS) { firDiagnostic -> + ClassLiteralLhsNotAClassImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS) { firDiagnostic -> + NullableTypeInClassLiteralLhsImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.NOTHING_TO_OVERRIDE) { firDiagnostic -> NothingToOverrideImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a as FirDeclaration), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 23da3e760bc..d55ce4b3050 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -483,6 +483,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = InnerClassOfGenericThrowableSubclass::class } + abstract class ClassLiteralLhsNotAClass : KtFirDiagnostic() { + override val diagnosticClass get() = ClassLiteralLhsNotAClass::class + } + + abstract class NullableTypeInClassLiteralLhs : KtFirDiagnostic() { + override val diagnosticClass get() = NullableTypeInClassLiteralLhs::class + } + abstract class NothingToOverride : KtFirDiagnostic() { override val diagnosticClass get() = NothingToOverride::class abstract val declaration: KtSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index a0ac3680b5f..e5881e8d257 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -775,6 +775,20 @@ internal class InnerClassOfGenericThrowableSubclassImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class ClassLiteralLhsNotAClassImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.ClassLiteralLhsNotAClass(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class NullableTypeInClassLiteralLhsImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.NullableTypeInClassLiteralLhs(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class NothingToOverrideImpl( override val declaration: KtSymbol, firDiagnostic: FirPsiDiagnostic<*>,