feat(semantic): add help message for invalid let x?: number (#5969)

This commit is contained in:
DonIsaac 2024-09-22 15:59:49 +00:00
parent 47c2faa7a9
commit 74d8714d5a
2 changed files with 23 additions and 4 deletions

View file

@ -45,17 +45,35 @@ pub fn check_variable_declaration(decl: &VariableDeclaration, ctx: &SemanticBuil
}
}
fn unexpected_optional(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Unexpected `?` operator").with_label(span)
fn unexpected_optional(span: Span, type_annotation: Option<&str>) -> OxcDiagnostic {
let d = OxcDiagnostic::error("Unexpected `?` operator").with_label(span);
if let Some(ty) = type_annotation {
d.with_help(format!("If you want an optional type, use `{ty} | undefined` instead."))
} else {
d
}
}
#[allow(clippy::cast_possible_truncation)]
pub fn check_variable_declarator(decl: &VariableDeclarator, ctx: &SemanticBuilder<'_>) {
// Check for `let x?: number;`
if decl.id.optional {
// NOTE: BindingPattern spans cover the identifier _and_ the type annotation.
let start = decl.id.span().start;
let Some(offset) = ctx.source_text[start as usize..].find('?') else { return };
let Some(offset) = ctx.source_text[start as usize..].find('?') else {
debug_assert!(false, "Optional flag not found in source text. This is likely indicates a bug in the parser.");
return;
};
let offset = start + offset as u32;
ctx.error(unexpected_optional(Span::new(offset, offset)));
let span = Span::new(offset, offset);
let ty = decl
.id
.type_annotation
.as_ref()
.map(|ty| ty.type_annotation.span())
.map(|span| &ctx.source_text[span]);
ctx.error(unexpected_optional(span, ty));
}
}

View file

@ -250,6 +250,7 @@ Negative Passed: 20/20 (100.00%)
· ▲
2 │
╰────
help: If you want an optional type, use `number | undefined` instead.
× Unexpected token
╭─[misc/fail/oxc-5955-2.ts:3:8]