diff --git a/parser/src/main/kotlin/tools/samt/parser/Parser.kt b/parser/src/main/kotlin/tools/samt/parser/Parser.kt index 112771b4..30300e80 100644 --- a/parser/src/main/kotlin/tools/samt/parser/Parser.kt +++ b/parser/src/main/kotlin/tools/samt/parser/Parser.kt @@ -493,11 +493,21 @@ 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 { 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..05d8b69b 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 (_, diagnostics) = parseWithRecoverableError(source) + assertEquals("Nullability is indicated after a type", diagnostics.messages.single().message) + } } @Nested