mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
ra_syntax: fix reparsing merging errors, also now reparse_token() reports errors
This commit is contained in:
parent
fc5e7b8807
commit
053ccf4121
1 changed files with 50 additions and 7 deletions
|
@ -27,8 +27,8 @@ pub(crate) fn incremental_reparse(
|
||||||
edit: &AtomTextEdit,
|
edit: &AtomTextEdit,
|
||||||
errors: Vec<SyntaxError>,
|
errors: Vec<SyntaxError>,
|
||||||
) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
|
) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
|
||||||
if let Some((green, old_range)) = reparse_token(node, &edit) {
|
if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) {
|
||||||
return Some((green, merge_errors(errors, Vec::new(), old_range, edit), old_range));
|
return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((green, new_errors, old_range)) = reparse_block(node, &edit) {
|
if let Some((green, new_errors, old_range)) = reparse_block(node, &edit) {
|
||||||
|
@ -40,7 +40,7 @@ pub(crate) fn incremental_reparse(
|
||||||
fn reparse_token<'node>(
|
fn reparse_token<'node>(
|
||||||
root: &'node SyntaxNode,
|
root: &'node SyntaxNode,
|
||||||
edit: &AtomTextEdit,
|
edit: &AtomTextEdit,
|
||||||
) -> Option<(GreenNode, TextRange)> {
|
) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
|
||||||
let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
|
let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
|
||||||
let prev_token_kind = prev_token.kind();
|
let prev_token_kind = prev_token.kind();
|
||||||
match prev_token_kind {
|
match prev_token_kind {
|
||||||
|
@ -54,7 +54,7 @@ fn reparse_token<'node>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_text = get_text_after_edit(prev_token.clone().into(), &edit);
|
let mut new_text = get_text_after_edit(prev_token.clone().into(), &edit);
|
||||||
let (new_token_kind, _error) = lex_single_syntax_kind(&new_text)?;
|
let (new_token_kind, new_err) = lex_single_syntax_kind(&new_text)?;
|
||||||
|
|
||||||
if new_token_kind != prev_token_kind
|
if new_token_kind != prev_token_kind
|
||||||
|| (new_token_kind == IDENT && is_contextual_kw(&new_text))
|
|| (new_token_kind == IDENT && is_contextual_kw(&new_text))
|
||||||
|
@ -76,7 +76,11 @@ fn reparse_token<'node>(
|
||||||
|
|
||||||
let new_token =
|
let new_token =
|
||||||
GreenToken::new(rowan::SyntaxKind(prev_token_kind.into()), new_text.into());
|
GreenToken::new(rowan::SyntaxKind(prev_token_kind.into()), new_text.into());
|
||||||
Some((prev_token.replace_with(new_token), prev_token.text_range()))
|
Some((
|
||||||
|
prev_token.replace_with(new_token),
|
||||||
|
new_err.into_iter().collect(),
|
||||||
|
prev_token.text_range(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -200,9 +204,9 @@ mod tests {
|
||||||
|
|
||||||
let fully_reparsed = SourceFile::parse(&after);
|
let fully_reparsed = SourceFile::parse(&after);
|
||||||
let incrementally_reparsed: Parse<SourceFile> = {
|
let incrementally_reparsed: Parse<SourceFile> = {
|
||||||
let f = SourceFile::parse(&before);
|
let before = SourceFile::parse(&before);
|
||||||
let (green, new_errors, range) =
|
let (green, new_errors, range) =
|
||||||
incremental_reparse(f.tree().syntax(), &edit, f.errors.to_vec()).unwrap();
|
incremental_reparse(before.tree().syntax(), &edit, before.errors.to_vec()).unwrap();
|
||||||
assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
|
assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
|
||||||
Parse::new(green, new_errors)
|
Parse::new(green, new_errors)
|
||||||
};
|
};
|
||||||
|
@ -211,6 +215,7 @@ mod tests {
|
||||||
&format!("{:#?}", fully_reparsed.tree().syntax()),
|
&format!("{:#?}", fully_reparsed.tree().syntax()),
|
||||||
&format!("{:#?}", incrementally_reparsed.tree().syntax()),
|
&format!("{:#?}", incrementally_reparsed.tree().syntax()),
|
||||||
);
|
);
|
||||||
|
assert_eq!(fully_reparsed.errors(), incrementally_reparsed.errors());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test] // FIXME: some test here actually test token reparsing
|
#[test] // FIXME: some test here actually test token reparsing
|
||||||
|
@ -409,4 +414,42 @@ enum Foo {
|
||||||
4,
|
4,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reparse_str_token_with_error_unchanged() {
|
||||||
|
do_check(r#""<|>Unclosed<|> string literal"#, "Still unclosed", 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reparse_str_token_with_error_fixed() {
|
||||||
|
do_check(r#""unterinated<|><|>"#, "\"", 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reparse_block_with_error_in_middle_unchanged() {
|
||||||
|
do_check(
|
||||||
|
r#"fn main() {
|
||||||
|
if {}
|
||||||
|
32 + 4<|><|>
|
||||||
|
return
|
||||||
|
if {}
|
||||||
|
}"#,
|
||||||
|
"23",
|
||||||
|
105,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reparse_block_with_error_in_middle_fixed() {
|
||||||
|
do_check(
|
||||||
|
r#"fn main() {
|
||||||
|
if {}
|
||||||
|
32 + 4<|><|>
|
||||||
|
return
|
||||||
|
if {}
|
||||||
|
}"#,
|
||||||
|
";",
|
||||||
|
105,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue