diff options
Diffstat (limited to 'crates/ra_syntax/src/parsing/reparsing.rs')
-rw-r--r-- | crates/ra_syntax/src/parsing/reparsing.rs | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs index f2d218ab9..19d8adcfb 100644 --- a/crates/ra_syntax/src/parsing/reparsing.rs +++ b/crates/ra_syntax/src/parsing/reparsing.rs | |||
@@ -1,18 +1,25 @@ | |||
1 | //! Implementation of incremental re-parsing. | ||
2 | //! | ||
3 | //! We use two simple strategies for this: | ||
4 | //! - if the edit modifies only a single token (like changing an identifier's | ||
5 | //! letter), we replace only this token. | ||
6 | //! - otherwise, we search for the nearest `{}` block which contains the edit | ||
7 | //! and try to parse only this block. | ||
8 | |||
9 | use ra_text_edit::AtomTextEdit; | ||
10 | use ra_parser::Reparser; | ||
11 | |||
1 | use crate::{ | 12 | use crate::{ |
2 | SyntaxKind::*, TextRange, TextUnit, | 13 | SyntaxKind::*, TextRange, TextUnit, SyntaxError, |
3 | algo, | 14 | algo, |
4 | syntax_node::{GreenNode, SyntaxNode}, | 15 | syntax_node::{GreenNode, SyntaxNode}, |
5 | syntax_error::SyntaxError, | ||
6 | parsing::{ | 16 | parsing::{ |
7 | grammar, parse_with, | 17 | input::ParserInput, |
8 | builder::GreenBuilder, | 18 | builder::TreeBuilder, |
9 | parser::Parser, | ||
10 | lexer::{tokenize, Token}, | 19 | lexer::{tokenize, Token}, |
11 | } | 20 | } |
12 | }; | 21 | }; |
13 | 22 | ||
14 | use ra_text_edit::AtomTextEdit; | ||
15 | |||
16 | pub(crate) fn incremental_reparse( | 23 | pub(crate) fn incremental_reparse( |
17 | node: &SyntaxNode, | 24 | node: &SyntaxNode, |
18 | edit: &AtomTextEdit, | 25 | edit: &AtomTextEdit, |
@@ -61,7 +68,10 @@ fn reparse_block<'node>( | |||
61 | if !is_balanced(&tokens) { | 68 | if !is_balanced(&tokens) { |
62 | return None; | 69 | return None; |
63 | } | 70 | } |
64 | let (green, new_errors) = parse_with(GreenBuilder::default(), &text, &tokens, reparser); | 71 | let token_source = ParserInput::new(&text, &tokens); |
72 | let mut tree_sink = TreeBuilder::new(&text, &tokens); | ||
73 | reparser.parse(&token_source, &mut tree_sink); | ||
74 | let (green, new_errors) = tree_sink.finish(); | ||
65 | Some((node, green, new_errors)) | 75 | Some((node, green, new_errors)) |
66 | } | 76 | } |
67 | 77 | ||
@@ -77,12 +87,13 @@ fn is_contextual_kw(text: &str) -> bool { | |||
77 | } | 87 | } |
78 | } | 88 | } |
79 | 89 | ||
80 | fn find_reparsable_node( | 90 | fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(&SyntaxNode, Reparser)> { |
81 | node: &SyntaxNode, | ||
82 | range: TextRange, | ||
83 | ) -> Option<(&SyntaxNode, fn(&mut Parser))> { | ||
84 | let node = algo::find_covering_node(node, range); | 91 | let node = algo::find_covering_node(node, range); |
85 | node.ancestors().find_map(|node| grammar::reparser(node).map(|r| (node, r))) | 92 | node.ancestors().find_map(|node| { |
93 | let first_child = node.first_child().map(|it| it.kind()); | ||
94 | let parent = node.parent().map(|it| it.kind()); | ||
95 | Reparser::for_node(node.kind(), first_child, parent).map(|r| (node, r)) | ||
96 | }) | ||
86 | } | 97 | } |
87 | 98 | ||
88 | fn is_balanced(tokens: &[Token]) -> bool { | 99 | fn is_balanced(tokens: &[Token]) -> bool { |
@@ -132,7 +143,7 @@ fn merge_errors( | |||
132 | mod tests { | 143 | mod tests { |
133 | use test_utils::{extract_range, assert_eq_text}; | 144 | use test_utils::{extract_range, assert_eq_text}; |
134 | 145 | ||
135 | use crate::{SourceFile, AstNode, utils::dump_tree}; | 146 | use crate::{SourceFile, AstNode}; |
136 | use super::*; | 147 | use super::*; |
137 | 148 | ||
138 | fn do_check<F>(before: &str, replace_with: &str, reparser: F) | 149 | fn do_check<F>(before: &str, replace_with: &str, reparser: F) |
@@ -158,8 +169,8 @@ mod tests { | |||
158 | }; | 169 | }; |
159 | 170 | ||
160 | assert_eq_text!( | 171 | assert_eq_text!( |
161 | &dump_tree(fully_reparsed.syntax()), | 172 | &fully_reparsed.syntax().debug_dump(), |
162 | &dump_tree(incrementally_reparsed.syntax()), | 173 | &incrementally_reparsed.syntax().debug_dump(), |
163 | ) | 174 | ) |
164 | } | 175 | } |
165 | 176 | ||