From 21eb21d88ee11fc9eed64ed910b82a0375ce985a Mon Sep 17 00:00:00 2001 From: Marcel Joss Date: Sat, 27 May 2023 16:20:54 +0200 Subject: [PATCH 1/2] fix(parser): fix invalid location when putting question mark before type --- parser/src/main/kotlin/tools/samt/parser/Parser.kt | 2 +- .../src/test/kotlin/tools/samt/parser/ParserTest.kt | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/parser/src/main/kotlin/tools/samt/parser/Parser.kt b/parser/src/main/kotlin/tools/samt/parser/Parser.kt index 112771b4..d63e74cd 100644 --- a/parser/src/main/kotlin/tools/samt/parser/Parser.kt +++ b/parser/src/main/kotlin/tools/samt/parser/Parser.kt @@ -497,7 +497,7 @@ class Parser private constructor( else -> { diagnostic.fatal { message("Expected an expression") - highlight(locationFromStart(start), highlightBeginningOnly = true) + highlight(current!!.location, highlightBeginningOnly = true) } } } diff --git a/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt b/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt index dc4265fd..38bc350b 100644 --- a/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt +++ b/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt @@ -542,6 +542,17 @@ class ParserTest { val exception = parseWithFatalError(source) assertEquals("Expected an expression", exception.message) } + + @Test + fun `unexpected question mark`() { + val source = """ + package a + + typealias A = ?String + """ + val exception = parseWithFatalError(source) + assertEquals("Expected an expression", exception.message) + } } @Nested From a60b3752d05293db249e8219bfddd22df302f683 Mon Sep 17 00:00:00 2001 From: Marcel Joss Date: Sat, 27 May 2023 16:38:09 +0200 Subject: [PATCH 2/2] fix(parser): make question mark before type into recoverable error --- parser/src/main/kotlin/tools/samt/parser/Parser.kt | 10 ++++++++++ parser/src/test/kotlin/tools/samt/parser/ParserTest.kt | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/parser/src/main/kotlin/tools/samt/parser/Parser.kt b/parser/src/main/kotlin/tools/samt/parser/Parser.kt index d63e74cd..30300e80 100644 --- a/parser/src/main/kotlin/tools/samt/parser/Parser.kt +++ b/parser/src/main/kotlin/tools/samt/parser/Parser.kt @@ -493,6 +493,16 @@ class Parser private constructor( check() -> parseObjectNode() skip() -> WildcardNode(locationFromStart(start)) + skip() -> { + val literal = parseLiteral() + diagnostic.error { + message("Nullability is indicated after a type") + highlight(locationFromStart(start), highlightBeginningOnly = true) + info("A valid nullable type looks like 'Int?' or 'String(size(1..*))?'") + help("To declare the type nullable move the question mark to the end of the type") + } + literal + } else -> { diagnostic.fatal { diff --git a/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt b/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt index 38bc350b..05d8b69b 100644 --- a/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt +++ b/parser/src/test/kotlin/tools/samt/parser/ParserTest.kt @@ -550,8 +550,8 @@ class ParserTest { typealias A = ?String """ - val exception = parseWithFatalError(source) - assertEquals("Expected an expression", exception.message) + val (_, diagnostics) = parseWithRecoverableError(source) + assertEquals("Nullability is indicated after a type", diagnostics.messages.single().message) } }