From 404c69ded7431c5dbccb6d958dcecfa156552b93 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 6 Apr 2021 15:11:31 +0300 Subject: [PATCH] [FIR] Implement INCORRECT_CHARACTER_LITERAL, EMPTY_CHARACTER_LITERAL, TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL, ILLEGAL_ESCAPE, ILLEGAL_ESCAPE_SEQUENCE diagnostics, fix tests --- .../diagnostics/superIsNotAnExpression.kt | 2 +- .../diagnostics/FirDiagnosticsList.kt | 4 ++ .../fir/analysis/diagnostics/FirErrors.kt | 4 ++ .../coneDiagnosticToFirDiagnostic.kt | 4 ++ .../fir/lightTree/converter/BaseConverter.kt | 2 +- .../kotlin/fir/builder/BaseFirBuilder.kt | 11 +++- .../kotlin/fir/builder/ConversionUtils.kt | 62 ++++++++++++------- .../fir/diagnostics/ConeSimpleDiagnostic.kt | 6 ++ .../tests/CharacterLiterals.fir.kt | 12 ++-- .../tests/IncorrectCharacterLiterals.fir.kt | 34 +++++----- .../tests/StringPrefixAndSuffix.fir.kt | 10 +-- .../defaultValuesInAnnotation.fir.kt | 2 +- .../character-literals/p-1/neg/1.1.fir.kt | 16 ++--- .../character-literals/p-4/neg/1.1.fir.kt | 14 ++--- .../diagnostics/KtFirDataClassConverters.kt | 24 +++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 16 +++++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 28 +++++++++ 17 files changed, 181 insertions(+), 70 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt index 5537e7af33f..9eb0c508944 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt @@ -7,7 +7,7 @@ class B: A() { invoke() super { - println('weird') + println('weird') } } } 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 30ba1c28f42..bc791990cb9 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 @@ -63,6 +63,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val NESTED_CLASS_NOT_ALLOWED by error(PositioningStrategy.DECLARATION_NAME) { parameter("declaration") } + val INCORRECT_CHARACTER_LITERAL by error() + val EMPTY_CHARACTER_LITERAL by error() + val TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL by error() + val ILLEGAL_ESCAPE by error() } val UNRESOLVED by object : DiagnosticGroup("Unresolved") { 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 a755496c22b..1db1e0f74c1 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 @@ -79,6 +79,10 @@ object FirErrors { val VARIABLE_EXPECTED by error0() val DELEGATION_IN_INTERFACE by error0() val NESTED_CLASS_NOT_ALLOWED by error1(SourceElementPositioningStrategies.DECLARATION_NAME) + val INCORRECT_CHARACTER_LITERAL by error0() + val EMPTY_CHARACTER_LITERAL by error0() + val TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL by error0() + val ILLEGAL_ESCAPE by error0() // Unresolved val HIDDEN by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 67043f2c2f7..0be28b11cee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -175,6 +175,10 @@ private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0 FirErrors.ILLEGAL_PROJECTION_USAGE DiagnosticKind.MissingStdlibClass -> FirErrors.MISSING_STDLIB_CLASS DiagnosticKind.Other -> FirErrors.OTHER_ERROR + DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL + DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL + DiagnosticKind.TooManyCharactersInCharacterLiteral -> FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL + DiagnosticKind.IllegalEscape -> FirErrors.ILLEGAL_ESCAPE else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") } } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt index cb1a714b309..9d3b2936fe5 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt @@ -46,7 +46,7 @@ abstract class BaseConverter( override val LighterASTNode.unescapedValue: String get() { val escape = this.asText - return escapedStringToCharacter(escape)?.toString() + return escapedStringToCharacter(escape).value?.toString() ?: escape.replace("\\", "").replace("u", "\\u") } diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index cf400220a78..fbbf24cb91a 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -332,13 +332,18 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte ConeSimpleDiagnostic("Incorrect double: $text", DiagnosticKind.IllegalConstExpression) ) } - CHARACTER_CONSTANT -> + CHARACTER_CONSTANT -> { + val characterWithDiagnostic = text.parseCharacter() buildConstOrErrorExpression( sourceElement, ConstantValueKind.Char, - text.parseCharacter(), - ConeSimpleDiagnostic("Incorrect character: $text", DiagnosticKind.IllegalConstExpression) + characterWithDiagnostic.value, + ConeSimpleDiagnostic( + "Incorrect character: $text", + characterWithDiagnostic.getDiagnostic() ?: DiagnosticKind.IllegalConstExpression + ) ) + } BOOLEAN_CONSTANT -> buildConstExpression( sourceElement, diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 63be80096f5..2ba840ff299 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock @@ -40,30 +41,30 @@ import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions -fun String.parseCharacter(): Char? { +fun String.parseCharacter(): CharacterWithDiagnostic { // Strip the quotes if (length < 2 || this[0] != '\'' || this[length - 1] != '\'') { - return null + return CharacterWithDiagnostic(DiagnosticKind.IncorrectCharacterLiteral) } - val text = substring(1, length - 1) // now there're no quotes + val text = substring(1, length - 1) // now there is no quotes if (text.isEmpty()) { - return null + return CharacterWithDiagnostic(DiagnosticKind.EmptyCharacterLiteral) } return if (text[0] != '\\') { // No escape if (text.length == 1) { - text[0] + CharacterWithDiagnostic(text[0]) } else { - null + CharacterWithDiagnostic(DiagnosticKind.TooManyCharactersInCharacterLiteral) } } else { escapedStringToCharacter(text) } } -fun escapedStringToCharacter(text: String): Char? { +fun escapedStringToCharacter(text: String): CharacterWithDiagnostic { assert(text.isNotEmpty() && text[0] == '\\') { "Only escaped sequences must be passed to this routine: $text" } @@ -73,40 +74,59 @@ fun escapedStringToCharacter(text: String): Char? { when (escape.length) { 0 -> { // bare slash - return null + return CharacterWithDiagnostic(DiagnosticKind.IllegalEscape) } 1 -> { // one-char escape - return translateEscape(escape[0]) ?: return null + return translateEscape(escape[0]) } 5 -> { // unicode escape if (escape[0] == 'u') { try { val intValue = Integer.valueOf(escape.substring(1), 16) - return intValue.toInt().toChar() + return CharacterWithDiagnostic(intValue.toInt().toChar()) } catch (e: NumberFormatException) { // Will be reported below } } } } - return null + return CharacterWithDiagnostic(DiagnosticKind.IllegalEscape) } -internal fun translateEscape(c: Char): Char? = +internal fun translateEscape(c: Char): CharacterWithDiagnostic = when (c) { - 't' -> '\t' - 'b' -> '\b' - 'n' -> '\n' - 'r' -> '\r' - '\'' -> '\'' - '\"' -> '\"' - '\\' -> '\\' - '$' -> '$' - else -> null + 't' -> CharacterWithDiagnostic('\t') + 'b' -> CharacterWithDiagnostic('\b') + 'n' -> CharacterWithDiagnostic('\n') + 'r' -> CharacterWithDiagnostic('\r') + '\'' -> CharacterWithDiagnostic('\'') + '\"' -> CharacterWithDiagnostic('\"') + '\\' -> CharacterWithDiagnostic('\\') + '$' -> CharacterWithDiagnostic('$') + else -> CharacterWithDiagnostic(DiagnosticKind.IllegalEscape) } +class CharacterWithDiagnostic { + private val diagnostic: DiagnosticKind? + val value: Char? + + constructor(diagnostic: DiagnosticKind) { + this.diagnostic = diagnostic + this.value = null + } + + constructor(value: Char) { + this.diagnostic = null + this.value = value + } + + fun getDiagnostic(): DiagnosticKind? { + return diagnostic + } +} + fun IElementType.toBinaryName(): Name? { return OperatorConventions.BINARY_OPERATION_NAMES[this] } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt index 6c07409d8f8..bfb6668758e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt @@ -30,5 +30,11 @@ enum class DiagnosticKind { UnknownCallableKind, IllegalProjectionUsage, MissingStdlibClass, + + IncorrectCharacterLiteral, + EmptyCharacterLiteral, + TooManyCharactersInCharacterLiteral, + IllegalEscape, + Other } diff --git a/compiler/testData/diagnostics/tests/CharacterLiterals.fir.kt b/compiler/testData/diagnostics/tests/CharacterLiterals.fir.kt index 6fc44b50729..98cbf97a153 100644 --- a/compiler/testData/diagnostics/tests/CharacterLiterals.fir.kt +++ b/compiler/testData/diagnostics/tests/CharacterLiterals.fir.kt @@ -1,13 +1,13 @@ fun test(c : Char) { - test('') + test('') test('a') - test('aa') - test('a) - test(' - test(0' + test('aa') + test('a) + test(' + test(0' test('\n') test('\\') - test('''') + test('''') test('\'') test('\"') } diff --git a/compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.fir.kt b/compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.fir.kt index 33abadba3ea..ac59b859b09 100644 --- a/compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.fir.kt +++ b/compiler/testData/diagnostics/tests/IncorrectCharacterLiterals.fir.kt @@ -2,11 +2,11 @@ // KT-451 Incorrect character literals cause assertion failures fun ff() { - val b = '' - val c = '23' - val d = 'a - val e = 'ab - val f = '\' + val b = '' + val c = '23' + val d = 'a + val e = 'ab + val f = '\' } fun test() { @@ -19,19 +19,19 @@ fun test() { '\'' '\\' '\$' - '\x' - '\123' - '\ra' - '\000' - '\000' + '\x' + '\123' + '\ra' + '\000' + '\000' '\u0000' '\u000a' '\u000A' - '\u' - '\u0' - '\u00' - '\u000' - '\u000z' - '\\u000' - '\' + '\u' + '\u0' + '\u00' + '\u000' + '\u000z' + '\\u000' + '\' } diff --git a/compiler/testData/diagnostics/tests/StringPrefixAndSuffix.fir.kt b/compiler/testData/diagnostics/tests/StringPrefixAndSuffix.fir.kt index 8fec6b20155..5133b2c0c33 100644 --- a/compiler/testData/diagnostics/tests/StringPrefixAndSuffix.fir.kt +++ b/compiler/testData/diagnostics/tests/StringPrefixAndSuffix.fir.kt @@ -11,7 +11,7 @@ fun test(a: Any) { a foo"asd${a}sfsa" a foo"""sdf""" a foo'd' - a foo'' + a foo'' a foo""foo a a foo"asd"foo a @@ -19,17 +19,17 @@ fun test(a: Any) { a foo"asd${a}sfsa"foo a a foo"""sdf"""foo a a foo'd'foo a - a foo''foo a + a foo''foo a a in"foo" a in"""foo""" a in's' - a in'' + a in'' a !in"foo" a !in"""foo""" a !in's' - a !in'' + a !in'' if("s"is Any) {} if("s"is Any) {} @@ -37,4 +37,4 @@ fun test(a: Any) { a foo""1 a foo""1.0 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.fir.kt b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.fir.kt index a1bfe7d140d..06b630c16f6 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.fir.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/defaultValuesInAnnotation.fir.kt @@ -9,7 +9,7 @@ annotation class Foo( annotation class Bar( val a: Array = [' '], - val b: Array = ["", ''], + val b: Array = ["", ''], val c: Array = [1] ) diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-1/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-1/neg/1.1.fir.kt index 6fae0c6659e..281adbbb2a7 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-1/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-1/neg/1.1.fir.kt @@ -4,28 +4,28 @@ // TESTCASE NUMBER: 1 fun case1() { - val c = '' + val c = '' } // TESTCASE NUMBER: 2 fun case2() { - val c2: Char = ''' - val c3: Char = '\' + val c2: Char = ''' + val c3: Char = '\' } // TESTCASE NUMBER: 3 fun case3() { - val c1: Char = 'B a' - val c2: Char = ' ' - val c3: Char = 'Ba' + val c1: Char = 'B a' + val c2: Char = ' ' + val c3: Char = 'Ba' } // TESTCASE NUMBER: 4 fun case4() { - val cOutOfRaneMin = '𐀀' //u+10000 + val cOutOfRaneMin = '𐀀' //u+10000 - val cOutOfRangeAroundMax = '󠇿󠇿󟿿' //u+Dfffff + val cOutOfRangeAroundMax = '󠇿󠇿󟿿' //u+Dfffff } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-4/neg/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-4/neg/1.1.fir.kt index d4e44fac517..f1ec0f44246 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-4/neg/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/constant-literals/character-literals/p-4/neg/1.1.fir.kt @@ -6,19 +6,19 @@ fun case1() { //less then four hex digits - val c0 = '\u' - val c1 = '\uf' - val c2 = '\u1f' - val c3 = '\u1wf' + val c0 = '\u' + val c1 = '\uf' + val c2 = '\u1f' + val c3 = '\u1wf' //more then four hex digits - val c4 = '\u1wF2f' + val c4 = '\u1wF2f' } // TESTCASE NUMBER: 2 fun case2() { //not hex - val c1 = '\u000g' - val c2 = '\u000G' + val c1 = '\u000g' + val c2 = '\u000G' } 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 f1089dce220..0c04e662f8a 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 @@ -124,6 +124,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.INCORRECT_CHARACTER_LITERAL) { firDiagnostic -> + IncorrectCharacterLiteralImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.EMPTY_CHARACTER_LITERAL) { firDiagnostic -> + EmptyCharacterLiteralImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL) { firDiagnostic -> + TooManyCharactersInCharacterLiteralImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } + add(FirErrors.ILLEGAL_ESCAPE) { firDiagnostic -> + IllegalEscapeImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.HIDDEN) { firDiagnostic -> HiddenImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a.fir 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 47dec17150e..61fb10dd4be 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 @@ -108,6 +108,22 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val declaration: String } + abstract class IncorrectCharacterLiteral : KtFirDiagnostic() { + override val diagnosticClass get() = IncorrectCharacterLiteral::class + } + + abstract class EmptyCharacterLiteral : KtFirDiagnostic() { + override val diagnosticClass get() = EmptyCharacterLiteral::class + } + + abstract class TooManyCharactersInCharacterLiteral : KtFirDiagnostic() { + override val diagnosticClass get() = TooManyCharactersInCharacterLiteral::class + } + + abstract class IllegalEscape : KtFirDiagnostic() { + override val diagnosticClass get() = IllegalEscape::class + } + abstract class Hidden : KtFirDiagnostic() { override val diagnosticClass get() = Hidden::class abstract val hidden: 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 4059ceb6750..ffbaf969545 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 @@ -145,6 +145,34 @@ internal class NestedClassNotAllowedImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class IncorrectCharacterLiteralImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.IncorrectCharacterLiteral(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class EmptyCharacterLiteralImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.EmptyCharacterLiteral(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class TooManyCharactersInCharacterLiteralImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.TooManyCharactersInCharacterLiteral(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + +internal class IllegalEscapeImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.IllegalEscape(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class HiddenImpl( override val hidden: KtSymbol, firDiagnostic: FirPsiDiagnostic<*>,