diff options
author | Aleksey Kladov <[email protected]> | 2018-08-31 12:52:29 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-31 12:52:29 +0100 |
commit | 05a9d42f542c8eb876d06791579d948b2f571e04 (patch) | |
tree | 33b5962641f57d65b8545b477885fcfadbbe801c | |
parent | 8fc7f438c4347e027deda5cda4bcd5e560610bb7 (diff) |
tweak extend selection
-rw-r--r-- | crates/libeditor/src/extend_selection.rs | 21 | ||||
-rw-r--r-- | crates/libeditor/src/scope/fn_scope.rs | 37 | ||||
-rw-r--r-- | crates/libsyntax2/src/yellow/syntax_text.rs | 12 |
3 files changed, 54 insertions, 16 deletions
diff --git a/crates/libeditor/src/extend_selection.rs b/crates/libeditor/src/extend_selection.rs index 30cff6558..3adb1e45e 100644 --- a/crates/libeditor/src/extend_selection.rs +++ b/crates/libeditor/src/extend_selection.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use libsyntax2::{ | 1 | use libsyntax2::{ |
2 | File, TextRange, SyntaxNodeRef, | 2 | File, TextRange, SyntaxNodeRef, TextUnit, |
3 | SyntaxKind::*, | 3 | SyntaxKind::*, |
4 | algo::{find_leaf_at_offset, find_covering_node, ancestors, Direction, siblings}, | 4 | algo::{find_leaf_at_offset, find_covering_node, ancestors, Direction, siblings}, |
5 | }; | 5 | }; |
@@ -18,11 +18,22 @@ pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> | |||
18 | } | 18 | } |
19 | let ws = leaves.next()?; | 19 | let ws = leaves.next()?; |
20 | let ws_text = ws.leaf_text().unwrap(); | 20 | let ws_text = ws.leaf_text().unwrap(); |
21 | let range = TextRange::from_to(offset, ws.range().end()) - ws.range().start(); | 21 | let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start(); |
22 | let ws_suffix = &ws_text.as_str()[range]; | 22 | let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start(); |
23 | let ws_suffix = &ws_text.as_str()[suffix]; | ||
24 | let ws_prefix = &ws_text.as_str()[prefix]; | ||
23 | if ws_text.contains("\n") && !ws_suffix.contains("\n") { | 25 | if ws_text.contains("\n") && !ws_suffix.contains("\n") { |
24 | if let Some(node) = ws.next_sibling() { | 26 | if let Some(node) = ws.next_sibling() { |
25 | return Some(node.range()); | 27 | let start = match ws_prefix.rfind('\n') { |
28 | Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), | ||
29 | None => node.range().start() | ||
30 | }; | ||
31 | let end = if root.text().char_at(node.range().end()) == Some('\n') { | ||
32 | node.range().end() + TextUnit::of_char('\n') | ||
33 | } else { | ||
34 | node.range().end() | ||
35 | }; | ||
36 | return Some(TextRange::from_to(start, end)); | ||
26 | } | 37 | } |
27 | } | 38 | } |
28 | return Some(ws.range()); | 39 | return Some(ws.range()); |
@@ -99,7 +110,7 @@ impl S { | |||
99 | 110 | ||
100 | } | 111 | } |
101 | }"#, | 112 | }"#, |
102 | &["fn foo() {\n\n }"] | 113 | &[" fn foo() {\n\n }\n"] |
103 | ); | 114 | ); |
104 | } | 115 | } |
105 | 116 | ||
diff --git a/crates/libeditor/src/scope/fn_scope.rs b/crates/libeditor/src/scope/fn_scope.rs index 4b643237f..5c04e2f9b 100644 --- a/crates/libeditor/src/scope/fn_scope.rs +++ b/crates/libeditor/src/scope/fn_scope.rs | |||
@@ -140,6 +140,16 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
140 | compute_block_scopes(block, scopes, scope); | 140 | compute_block_scopes(block, scopes, scope); |
141 | } | 141 | } |
142 | }, | 142 | }, |
143 | ast::Expr::BlockExpr(e) => { | ||
144 | if let Some(block) = e.block() { | ||
145 | compute_block_scopes(block, scopes, scope); | ||
146 | } | ||
147 | } | ||
148 | ast::Expr::LoopExpr(e) => { | ||
149 | if let Some(block) = e.loop_body() { | ||
150 | compute_block_scopes(block, scopes, scope); | ||
151 | } | ||
152 | } | ||
143 | ast::Expr::WhileExpr(e) => { | 153 | ast::Expr::WhileExpr(e) => { |
144 | let cond_scope = e.condition().and_then(|cond| { | 154 | let cond_scope = e.condition().and_then(|cond| { |
145 | compute_cond_scopes(cond, scopes, scope) | 155 | compute_cond_scopes(cond, scopes, scope) |
@@ -147,11 +157,6 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
147 | if let Some(block) = e.loop_body() { | 157 | if let Some(block) = e.loop_body() { |
148 | compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); | 158 | compute_block_scopes(block, scopes, cond_scope.unwrap_or(scope)); |
149 | } | 159 | } |
150 | }, | ||
151 | ast::Expr::BlockExpr(e) => { | ||
152 | if let Some(block) = e.block() { | ||
153 | compute_block_scopes(block, scopes, scope); | ||
154 | } | ||
155 | } | 160 | } |
156 | ast::Expr::ForExpr(e) => { | 161 | ast::Expr::ForExpr(e) => { |
157 | if let Some(expr) = e.iterable() { | 162 | if let Some(expr) = e.iterable() { |
@@ -165,7 +170,7 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
165 | if let Some(block) = e.loop_body() { | 170 | if let Some(block) = e.loop_body() { |
166 | compute_block_scopes(block, scopes, scope); | 171 | compute_block_scopes(block, scopes, scope); |
167 | } | 172 | } |
168 | }, | 173 | } |
169 | ast::Expr::LambdaExpr(e) => { | 174 | ast::Expr::LambdaExpr(e) => { |
170 | let mut scope = scopes.new_scope(scope); | 175 | let mut scope = scopes.new_scope(scope); |
171 | scopes.add_params_bindings(scope, e.param_list()); | 176 | scopes.add_params_bindings(scope, e.param_list()); |
@@ -180,11 +185,7 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
180 | .chain(e.expr()) | 185 | .chain(e.expr()) |
181 | .for_each(|expr| compute_expr_scopes(expr, scopes, scope)); | 186 | .for_each(|expr| compute_expr_scopes(expr, scopes, scope)); |
182 | } | 187 | } |
183 | ast::Expr::LoopExpr(e) => { | 188 | |
184 | if let Some(block) = e.loop_body() { | ||
185 | compute_block_scopes(block, scopes, scope); | ||
186 | } | ||
187 | } | ||
188 | _ => { | 189 | _ => { |
189 | expr.syntax().children() | 190 | expr.syntax().children() |
190 | .filter_map(ast::Expr::cast) | 191 | .filter_map(ast::Expr::cast) |
@@ -273,4 +274,18 @@ mod tests { | |||
273 | &["x"], | 274 | &["x"], |
274 | ); | 275 | ); |
275 | } | 276 | } |
277 | |||
278 | // #[test] | ||
279 | // fn test_match() { | ||
280 | // do_check(r" | ||
281 | // fn quux() { | ||
282 | // match () { | ||
283 | // Some(x) => { | ||
284 | // <|> | ||
285 | // } | ||
286 | // }; | ||
287 | // }", | ||
288 | // &["x"], | ||
289 | // ); | ||
290 | // } | ||
276 | } | 291 | } |
diff --git a/crates/libsyntax2/src/yellow/syntax_text.rs b/crates/libsyntax2/src/yellow/syntax_text.rs index b855687c4..280bedd78 100644 --- a/crates/libsyntax2/src/yellow/syntax_text.rs +++ b/crates/libsyntax2/src/yellow/syntax_text.rs | |||
@@ -61,6 +61,18 @@ impl<'a> SyntaxText<'a> { | |||
61 | }); | 61 | }); |
62 | SyntaxText { node: self.node, range } | 62 | SyntaxText { node: self.node, range } |
63 | } | 63 | } |
64 | pub fn char_at(&self, offset: TextUnit) -> Option<char> { | ||
65 | let mut start: TextUnit = 0.into(); | ||
66 | for chunk in self.chunks() { | ||
67 | let end = start + TextUnit::of_str(chunk); | ||
68 | if start <= offset && offset < end { | ||
69 | let off: usize = u32::from(offset - start) as usize; | ||
70 | return Some(chunk[off..].chars().next().unwrap()); | ||
71 | } | ||
72 | start = end; | ||
73 | } | ||
74 | None | ||
75 | } | ||
64 | } | 76 | } |
65 | 77 | ||
66 | impl<'a> fmt::Debug for SyntaxText<'a> { | 78 | impl<'a> fmt::Debug for SyntaxText<'a> { |