mirror of
https://github.com/nushell/nushell.git
synced 2024-11-24 17:34:00 +01:00
make better messages for incomplete string (#12868)
# Description Fixes: #12795 The issue is caused by an empty position of `ParseError::UnexpectedEof`. So no detailed message is displayed. To fix the issue, I adjust the start of span to `span.end - 1`. In this way, we can make sure that it never points to an empty position. After lexing item, I also reorder the unclosed character checking . Now it will be checking unclosed opening delimiters first. # User-Facing Changes After this pr, it outputs detailed error message for incomplete string when running scripts. ## Before ``` ❯ nu -c "'ab" Error: nu::parser::unexpected_eof × Unexpected end of code. ╭─[source:1:4] 1 │ 'ab ╰──── > ./target/debug/nu -c "r#'ab" Error: nu::parser::unexpected_eof × Unexpected end of code. ╭─[source:1:6] 1 │ r#'ab ╰──── ``` ## After ``` > nu -c "'ab" Error: nu::parser::unexpected_eof × Unexpected end of code. ╭─[source:1:3] 1 │ 'ab · ┬ · ╰── expected closing ' ╰──── > ./target/debug/nu -c "r#'ab" Error: nu::parser::unexpected_eof × Unexpected end of code. ╭─[source:1:5] 1 │ r#'ab · ┬ · ╰── expected closing '# ╰──── ``` # Tests + Formatting Added some tests for incomplete string. --------- Co-authored-by: Ian Manske <ian.manske@pm.me>
This commit is contained in:
parent
9bf4d3ece6
commit
155934f783
@ -129,7 +129,7 @@ pub fn lex_item(
|
||||
},
|
||||
Some(ParseError::UnexpectedEof(
|
||||
(start as char).to_string(),
|
||||
Span::new(span.end, span.end),
|
||||
Span::new(span.end - 1, span.end),
|
||||
)),
|
||||
);
|
||||
}
|
||||
@ -247,21 +247,6 @@ pub fn lex_item(
|
||||
|
||||
let span = Span::new(span_offset + token_start, span_offset + *curr_offset);
|
||||
|
||||
// If there is still unclosed opening delimiters, remember they were missing
|
||||
if let Some(block) = block_level.last() {
|
||||
let delim = block.closing();
|
||||
let cause =
|
||||
ParseError::UnexpectedEof((delim as char).to_string(), Span::new(span.end, span.end));
|
||||
|
||||
return (
|
||||
Token {
|
||||
contents: TokenContents::Item,
|
||||
span,
|
||||
},
|
||||
Some(cause),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(delim) = quote_start {
|
||||
// The non-lite parse trims quotes on both sides, so we add the expected quote so that
|
||||
// anyone wanting to consume this partial parse (e.g., completions) will be able to get
|
||||
@ -273,11 +258,28 @@ pub fn lex_item(
|
||||
},
|
||||
Some(ParseError::UnexpectedEof(
|
||||
(delim as char).to_string(),
|
||||
Span::new(span.end, span.end),
|
||||
Span::new(span.end - 1, span.end),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
// If there is still unclosed opening delimiters, remember they were missing
|
||||
if let Some(block) = block_level.last() {
|
||||
let delim = block.closing();
|
||||
let cause = ParseError::UnexpectedEof(
|
||||
(delim as char).to_string(),
|
||||
Span::new(span.end - 1, span.end),
|
||||
);
|
||||
|
||||
return (
|
||||
Token {
|
||||
contents: TokenContents::Item,
|
||||
span,
|
||||
},
|
||||
Some(cause),
|
||||
);
|
||||
}
|
||||
|
||||
// If we didn't accumulate any characters, it's an unexpected error.
|
||||
if *curr_offset - token_start == 0 {
|
||||
return (
|
||||
@ -395,9 +397,11 @@ fn lex_raw_string(
|
||||
*curr_offset += 1
|
||||
}
|
||||
if !matches {
|
||||
let mut expected = '\''.to_string();
|
||||
expected.push_str(&"#".repeat(prefix_sharp_cnt));
|
||||
return Err(ParseError::UnexpectedEof(
|
||||
"#".to_string(),
|
||||
Span::new(span_offset + *curr_offset, span_offset + *curr_offset),
|
||||
expected,
|
||||
Span::new(span_offset + *curr_offset - 1, span_offset + *curr_offset),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
|
@ -154,6 +154,18 @@ fn raw_string_inside_closure() -> TestResult {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incomplete_raw_string() -> TestResult {
|
||||
fail_test("r#abc", "expected '")
|
||||
fn incomplete_string() -> TestResult {
|
||||
fail_test("r#abc", "expected '")?;
|
||||
fail_test("r#'bc", "expected closing '#")?;
|
||||
fail_test("'ab\"", "expected closing '")?;
|
||||
fail_test("\"ab'", "expected closing \"")?;
|
||||
fail_test(
|
||||
r#"def func [] {
|
||||
{
|
||||
"A": ""B" # <- the quote is bad
|
||||
}
|
||||
}
|
||||
"#,
|
||||
"expected closing \"",
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user