aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-31 12:52:29 +0100
committerAleksey Kladov <[email protected]>2018-08-31 12:52:29 +0100
commit05a9d42f542c8eb876d06791579d948b2f571e04 (patch)
tree33b5962641f57d65b8545b477885fcfadbbe801c
parent8fc7f438c4347e027deda5cda4bcd5e560610bb7 (diff)
tweak extend selection
-rw-r--r--crates/libeditor/src/extend_selection.rs21
-rw-r--r--crates/libeditor/src/scope/fn_scope.rs37
-rw-r--r--crates/libsyntax2/src/yellow/syntax_text.rs12
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 @@
1use libsyntax2::{ 1use 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
66impl<'a> fmt::Debug for SyntaxText<'a> { 78impl<'a> fmt::Debug for SyntaxText<'a> {