aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/extend_selection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/extend_selection.rs')
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs48
1 files changed, 26 insertions, 22 deletions
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 292f61f4a..140820df6 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -42,19 +42,20 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
42 TokenAtOffset::None => return None, 42 TokenAtOffset::None => return None,
43 TokenAtOffset::Single(l) => { 43 TokenAtOffset::Single(l) => {
44 if string_kinds.contains(&l.kind()) { 44 if string_kinds.contains(&l.kind()) {
45 extend_single_word_in_comment_or_string(&l, offset).unwrap_or_else(|| l.range()) 45 extend_single_word_in_comment_or_string(&l, offset)
46 .unwrap_or_else(|| l.text_range())
46 } else { 47 } else {
47 l.range() 48 l.text_range()
48 } 49 }
49 } 50 }
50 TokenAtOffset::Between(l, r) => pick_best(l, r).range(), 51 TokenAtOffset::Between(l, r) => pick_best(l, r).text_range(),
51 }; 52 };
52 return Some(leaf_range); 53 return Some(leaf_range);
53 }; 54 };
54 let node = match find_covering_element(root, range) { 55 let node = match find_covering_element(root, range) {
55 SyntaxElement::Token(token) => { 56 SyntaxElement::Token(token) => {
56 if token.range() != range { 57 if token.text_range() != range {
57 return Some(token.range()); 58 return Some(token.text_range());
58 } 59 }
59 if let Some(comment) = ast::Comment::cast(token.clone()) { 60 if let Some(comment) = ast::Comment::cast(token.clone()) {
60 if let Some(range) = extend_comments(comment) { 61 if let Some(range) = extend_comments(comment) {
@@ -65,12 +66,12 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
65 } 66 }
66 SyntaxElement::Node(node) => node, 67 SyntaxElement::Node(node) => node,
67 }; 68 };
68 if node.range() != range { 69 if node.text_range() != range {
69 return Some(node.range()); 70 return Some(node.text_range());
70 } 71 }
71 72
72 // Using shallowest node with same range allows us to traverse siblings. 73 // Using shallowest node with same range allows us to traverse siblings.
73 let node = node.ancestors().take_while(|n| n.range() == node.range()).last().unwrap(); 74 let node = node.ancestors().take_while(|n| n.text_range() == node.text_range()).last().unwrap();
74 75
75 if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) { 76 if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
76 if let Some(range) = extend_list_item(&node) { 77 if let Some(range) = extend_list_item(&node) {
@@ -78,7 +79,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
78 } 79 }
79 } 80 }
80 81
81 node.parent().map(|it| it.range()) 82 node.parent().map(|it| it.text_range())
82} 83}
83 84
84fn extend_single_word_in_comment_or_string( 85fn extend_single_word_in_comment_or_string(
@@ -86,7 +87,7 @@ fn extend_single_word_in_comment_or_string(
86 offset: TextUnit, 87 offset: TextUnit,
87) -> Option<TextRange> { 88) -> Option<TextRange> {
88 let text: &str = leaf.text(); 89 let text: &str = leaf.text();
89 let cursor_position: u32 = (offset - leaf.range().start()).into(); 90 let cursor_position: u32 = (offset - leaf.text_range().start()).into();
90 91
91 let (before, after) = text.split_at(cursor_position as usize); 92 let (before, after) = text.split_at(cursor_position as usize);
92 93
@@ -104,31 +105,31 @@ fn extend_single_word_in_comment_or_string(
104 if range.is_empty() { 105 if range.is_empty() {
105 None 106 None
106 } else { 107 } else {
107 Some(range + leaf.range().start()) 108 Some(range + leaf.text_range().start())
108 } 109 }
109} 110}
110 111
111fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange { 112fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange {
112 let ws_text = ws.text(); 113 let ws_text = ws.text();
113 let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start(); 114 let suffix = TextRange::from_to(offset, ws.text_range().end()) - ws.text_range().start();
114 let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start(); 115 let prefix = TextRange::from_to(ws.text_range().start(), offset) - ws.text_range().start();
115 let ws_suffix = &ws_text.as_str()[suffix]; 116 let ws_suffix = &ws_text.as_str()[suffix];
116 let ws_prefix = &ws_text.as_str()[prefix]; 117 let ws_prefix = &ws_text.as_str()[prefix];
117 if ws_text.contains('\n') && !ws_suffix.contains('\n') { 118 if ws_text.contains('\n') && !ws_suffix.contains('\n') {
118 if let Some(node) = ws.next_sibling_or_token() { 119 if let Some(node) = ws.next_sibling_or_token() {
119 let start = match ws_prefix.rfind('\n') { 120 let start = match ws_prefix.rfind('\n') {
120 Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), 121 Some(idx) => ws.text_range().start() + TextUnit::from((idx + 1) as u32),
121 None => node.range().start(), 122 None => node.text_range().start(),
122 }; 123 };
123 let end = if root.text().char_at(node.range().end()) == Some('\n') { 124 let end = if root.text().char_at(node.text_range().end()) == Some('\n') {
124 node.range().end() + TextUnit::of_char('\n') 125 node.text_range().end() + TextUnit::of_char('\n')
125 } else { 126 } else {
126 node.range().end() 127 node.text_range().end()
127 }; 128 };
128 return TextRange::from_to(start, end); 129 return TextRange::from_to(start, end);
129 } 130 }
130 } 131 }
131 ws.range() 132 ws.text_range()
132} 133}
133 134
134fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { 135fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken {
@@ -161,7 +162,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
161 } 162 }
162 163
163 if let Some(comma_node) = nearby_comma(node, Direction::Prev) { 164 if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
164 return Some(TextRange::from_to(comma_node.range().start(), node.range().end())); 165 return Some(TextRange::from_to(comma_node.text_range().start(), node.text_range().end()));
165 } 166 }
166 if let Some(comma_node) = nearby_comma(node, Direction::Next) { 167 if let Some(comma_node) = nearby_comma(node, Direction::Next) {
167 // Include any following whitespace when comma if after list item. 168 // Include any following whitespace when comma if after list item.
@@ -171,7 +172,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
171 .filter(|node| is_single_line_ws(node)) 172 .filter(|node| is_single_line_ws(node))
172 .unwrap_or(comma_node); 173 .unwrap_or(comma_node);
173 174
174 return Some(TextRange::from_to(node.range().start(), final_node.range().end())); 175 return Some(TextRange::from_to(node.text_range().start(), final_node.text_range().end()));
175 } 176 }
176 177
177 None 178 None
@@ -181,7 +182,10 @@ fn extend_comments(comment: ast::Comment) -> Option<TextRange> {
181 let prev = adj_comments(&comment, Direction::Prev); 182 let prev = adj_comments(&comment, Direction::Prev);
182 let next = adj_comments(&comment, Direction::Next); 183 let next = adj_comments(&comment, Direction::Next);
183 if prev != next { 184 if prev != next {
184 Some(TextRange::from_to(prev.syntax().range().start(), next.syntax().range().end())) 185 Some(TextRange::from_to(
186 prev.syntax().text_range().start(),
187 next.syntax().text_range().end(),
188 ))
185 } else { 189 } else {
186 None 190 None
187 } 191 }