diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index d341bca28..e27cafcfd 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -633,6 +633,10 @@ fn code_exprs(p: &mut Parser, mut stop: impl FnMut(&Parser) -> bool) { code_expr(p); if !p.end() && !stop(p) && !p.eat_if(SyntaxKind::Semicolon) { p.expected("semicolon or line break"); + if p.at(SyntaxKind::Label) { + p.hint("labels can only be applied in markup mode"); + p.hint("try wrapping your code in a markup block (`[ ]`)"); + } } } @@ -1838,6 +1842,14 @@ impl<'s> Parser<'s> { self.nodes.insert(m.0, error); } + /// Produce a hint. + fn hint(&mut self, hint: &str) { + let m = self.before_trivia(); + if let Some(error) = self.nodes.get_mut(m.0 - 1) { + error.hint(hint); + } + } + /// Consume the next token (if any) and produce an error stating that it was /// unexpected. fn unexpected(&mut self) { diff --git a/tests/suite/foundations/label.typ b/tests/suite/foundations/label.typ index 2cde102c3..28c6383bb 100644 --- a/tests/suite/foundations/label.typ +++ b/tests/suite/foundations/label.typ @@ -68,3 +68,9 @@ _Visible_ #test(str(), "hey") #test(str(label("hey")), "hey") #test(str([Hmm].label), "hey") + +--- label-in-code-mode-hint --- +// Error: 7-7 expected semicolon or line break +// Hint: 7-7 labels can only be applied in markup mode +// Hint: 7-7 try wrapping your code in a markup block (`[ ]`) +#{ [A] }