aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-02-08 11:49:43 +0000
committerAleksey Kladov <[email protected]>2019-02-08 11:49:43 +0000
commit12e3b4c70b5ef23b2fdfc197296d483680e125f9 (patch)
tree71baa0e0a62f9f6b61450501c5f821f67badf9e4 /crates/ra_ide_api_light/src
parent5cb1d41a30d25cbe136402644bf5434dd667f1e5 (diff)
reformat the world
Diffstat (limited to 'crates/ra_ide_api_light/src')
-rw-r--r--crates/ra_ide_api_light/src/diagnostics.rs32
-rw-r--r--crates/ra_ide_api_light/src/extend_selection.rs57
-rw-r--r--crates/ra_ide_api_light/src/folding_ranges.rs47
-rw-r--r--crates/ra_ide_api_light/src/formatting.rs5
-rw-r--r--crates/ra_ide_api_light/src/join_lines.rs27
-rw-r--r--crates/ra_ide_api_light/src/lib.rs14
-rw-r--r--crates/ra_ide_api_light/src/line_index.rs165
-rw-r--r--crates/ra_ide_api_light/src/line_index_utils.rs51
-rw-r--r--crates/ra_ide_api_light/src/structure.rs13
-rw-r--r--crates/ra_ide_api_light/src/typing.rs17
10 files changed, 77 insertions, 351 deletions
diff --git a/crates/ra_ide_api_light/src/diagnostics.rs b/crates/ra_ide_api_light/src/diagnostics.rs
index 2b695dfdf..7c383ca2a 100644
--- a/crates/ra_ide_api_light/src/diagnostics.rs
+++ b/crates/ra_ide_api_light/src/diagnostics.rs
@@ -72,14 +72,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
72 single_use_tree: &ast::UseTree, 72 single_use_tree: &ast::UseTree,
73) -> Option<TextEdit> { 73) -> Option<TextEdit> {
74 let use_tree_list_node = single_use_tree.syntax().parent()?; 74 let use_tree_list_node = single_use_tree.syntax().parent()?;
75 if single_use_tree 75 if single_use_tree.path()?.segment()?.syntax().first_child()?.kind() == SyntaxKind::SELF_KW {
76 .path()?
77 .segment()?
78 .syntax()
79 .first_child()?
80 .kind()
81 == SyntaxKind::SELF_KW
82 {
83 let start = use_tree_list_node.prev_sibling()?.range().start(); 76 let start = use_tree_list_node.prev_sibling()?.range().start();
84 let end = use_tree_list_node.range().end(); 77 let end = use_tree_list_node.range().end();
85 let range = TextRange::from_to(start, end); 78 let range = TextRange::from_to(start, end);
@@ -145,9 +138,8 @@ mod tests {
145 for node in file.syntax().descendants() { 138 for node in file.syntax().descendants() {
146 func(&mut diagnostics, node); 139 func(&mut diagnostics, node);
147 } 140 }
148 let diagnostic = diagnostics 141 let diagnostic =
149 .pop() 142 diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before));
150 .unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before));
151 let fix = diagnostic.fix.unwrap(); 143 let fix = diagnostic.fix.unwrap();
152 let actual = fix.edit.apply(&before); 144 let actual = fix.edit.apply(&before);
153 assert_eq_text!(after, &actual); 145 assert_eq_text!(after, &actual);
@@ -162,21 +154,9 @@ mod tests {
162 ", 154 ",
163 check_unnecessary_braces_in_use_statement, 155 check_unnecessary_braces_in_use_statement,
164 ); 156 );
165 check_apply( 157 check_apply("use {b};", "use b;", check_unnecessary_braces_in_use_statement);
166 "use {b};", 158 check_apply("use a::{c};", "use a::c;", check_unnecessary_braces_in_use_statement);
167 "use b;", 159 check_apply("use a::{self};", "use a;", check_unnecessary_braces_in_use_statement);
168 check_unnecessary_braces_in_use_statement,
169 );
170 check_apply(
171 "use a::{c};",
172 "use a::c;",
173 check_unnecessary_braces_in_use_statement,
174 );
175 check_apply(
176 "use a::{self};",
177 "use a;",
178 check_unnecessary_braces_in_use_statement,
179 );
180 check_apply( 160 check_apply(
181 "use a::{c, d::{e}};", 161 "use a::{c, d::{e}};",
182 "use a::{c, d::e};", 162 "use a::{c, d::e};",
diff --git a/crates/ra_ide_api_light/src/extend_selection.rs b/crates/ra_ide_api_light/src/extend_selection.rs
index f396dfe3f..28d62f290 100644
--- a/crates/ra_ide_api_light/src/extend_selection.rs
+++ b/crates/ra_ide_api_light/src/extend_selection.rs
@@ -43,11 +43,7 @@ pub fn extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
43 let node = find_covering_node(root, range); 43 let node = find_covering_node(root, range);
44 44
45 // Using shallowest node with same range allows us to traverse siblings. 45 // Using shallowest node with same range allows us to traverse siblings.
46 let node = node 46 let node = node.ancestors().take_while(|n| n.range() == node.range()).last().unwrap();
47 .ancestors()
48 .take_while(|n| n.range() == node.range())
49 .last()
50 .unwrap();
51 47
52 if range == node.range() { 48 if range == node.range() {
53 if string_kinds.contains(&node.kind()) { 49 if string_kinds.contains(&node.kind()) {
@@ -145,10 +141,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
145 } 141 }
146 142
147 if let Some(comma_node) = nearby_comma(node, Direction::Prev) { 143 if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
148 return Some(TextRange::from_to( 144 return Some(TextRange::from_to(comma_node.range().start(), node.range().end()));
149 comma_node.range().start(),
150 node.range().end(),
151 ));
152 } 145 }
153 146
154 if let Some(comma_node) = nearby_comma(node, Direction::Next) { 147 if let Some(comma_node) = nearby_comma(node, Direction::Next) {
@@ -160,10 +153,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
160 .filter(|node| is_single_line_ws(node)) 153 .filter(|node| is_single_line_ws(node))
161 .unwrap_or(comma_node); 154 .unwrap_or(comma_node);
162 155
163 return Some(TextRange::from_to( 156 return Some(TextRange::from_to(node.range().start(), final_node.range().end()));
164 node.range().start(),
165 final_node.range().end(),
166 ));
167 } 157 }
168 158
169 return None; 159 return None;
@@ -217,36 +207,15 @@ mod tests {
217 #[test] 207 #[test]
218 fn test_extend_selection_list() { 208 fn test_extend_selection_list() {
219 do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]); 209 do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]);
220 do_check( 210 do_check(r#"fn foo(<|>x: i32, y: i32) {}"#, &["x", "x: i32", "x: i32, "]);
221 r#"fn foo(<|>x: i32, y: i32) {}"#, 211 do_check(r#"fn foo(<|>x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,"]);
222 &["x", "x: i32", "x: i32, "], 212 do_check(r#"fn foo(x: i32, <|>y: i32) {}"#, &["y", "y: i32", ", y: i32"]);
223 ); 213 do_check(r#"fn foo(x: i32, <|>y: i32, ) {}"#, &["y", "y: i32", ", y: i32"]);
224 do_check( 214 do_check(r#"fn foo(x: i32,<|>y: i32) {}"#, &["y", "y: i32", ",y: i32"]);
225 r#"fn foo(<|>x: i32,y: i32) {}"#,
226 &["x", "x: i32", "x: i32,"],
227 );
228 do_check(
229 r#"fn foo(x: i32, <|>y: i32) {}"#,
230 &["y", "y: i32", ", y: i32"],
231 );
232 do_check(
233 r#"fn foo(x: i32, <|>y: i32, ) {}"#,
234 &["y", "y: i32", ", y: i32"],
235 );
236 do_check(
237 r#"fn foo(x: i32,<|>y: i32) {}"#,
238 &["y", "y: i32", ",y: i32"],
239 );
240 215
241 do_check( 216 do_check(r#"const FOO: [usize; 2] = [ 22<|> , 33];"#, &["22", "22 , "]);
242 r#"const FOO: [usize; 2] = [ 22<|> , 33];"#,
243 &["22", "22 , "],
244 );
245 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]); 217 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]);
246 do_check( 218 do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#, &["33", ", 33"]);
247 r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#,
248 &["33", ", 33"],
249 );
250 219
251 do_check( 220 do_check(
252 r#" 221 r#"
@@ -292,11 +261,7 @@ struct B {
292 <|> 261 <|>
293} 262}
294 "#, 263 "#,
295 &[ 264 &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"],
296 "\n \n",
297 "{\n \n}",
298 "/// bla\n/// bla\nstruct B {\n \n}",
299 ],
300 ) 265 )
301 } 266 }
302 267
diff --git a/crates/ra_ide_api_light/src/folding_ranges.rs b/crates/ra_ide_api_light/src/folding_ranges.rs
index c73637323..357a7dee1 100644
--- a/crates/ra_ide_api_light/src/folding_ranges.rs
+++ b/crates/ra_ide_api_light/src/folding_ranges.rs
@@ -30,30 +30,21 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
30 // Fold items that span multiple lines 30 // Fold items that span multiple lines
31 if let Some(kind) = fold_kind(node.kind()) { 31 if let Some(kind) = fold_kind(node.kind()) {
32 if node.text().contains('\n') { 32 if node.text().contains('\n') {
33 res.push(Fold { 33 res.push(Fold { range: node.range(), kind });
34 range: node.range(),
35 kind,
36 });
37 } 34 }
38 } 35 }
39 36
40 // Fold groups of comments 37 // Fold groups of comments
41 if node.kind() == COMMENT && !visited_comments.contains(&node) { 38 if node.kind() == COMMENT && !visited_comments.contains(&node) {
42 if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) { 39 if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) {
43 res.push(Fold { 40 res.push(Fold { range, kind: FoldKind::Comment })
44 range,
45 kind: FoldKind::Comment,
46 })
47 } 41 }
48 } 42 }
49 43
50 // Fold groups of imports 44 // Fold groups of imports
51 if node.kind() == USE_ITEM && !visited_imports.contains(&node) { 45 if node.kind() == USE_ITEM && !visited_imports.contains(&node) {
52 if let Some(range) = contiguous_range_for_group(node, &mut visited_imports) { 46 if let Some(range) = contiguous_range_for_group(node, &mut visited_imports) {
53 res.push(Fold { 47 res.push(Fold { range, kind: FoldKind::Imports })
54 range,
55 kind: FoldKind::Imports,
56 })
57 } 48 }
58 } 49 }
59 50
@@ -62,10 +53,7 @@ pub fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
62 if let Some(range) = 53 if let Some(range) =
63 contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods) 54 contiguous_range_for_group_unless(node, has_visibility, &mut visited_mods)
64 { 55 {
65 res.push(Fold { 56 res.push(Fold { range, kind: FoldKind::Mods })
66 range,
67 kind: FoldKind::Mods,
68 })
69 } 57 }
70 } 58 }
71 } 59 }
@@ -84,9 +72,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
84} 72}
85 73
86fn has_visibility(node: &SyntaxNode) -> bool { 74fn has_visibility(node: &SyntaxNode) -> bool {
87 ast::Module::cast(node) 75 ast::Module::cast(node).and_then(|m| m.visibility()).is_some()
88 .and_then(|m| m.visibility())
89 .is_some()
90} 76}
91 77
92fn contiguous_range_for_group<'a>( 78fn contiguous_range_for_group<'a>(
@@ -125,10 +111,7 @@ fn contiguous_range_for_group_unless<'a>(
125 } 111 }
126 112
127 if first != last { 113 if first != last {
128 Some(TextRange::from_to( 114 Some(TextRange::from_to(first.range().start(), last.range().end()))
129 first.range().start(),
130 last.range().end(),
131 ))
132 } else { 115 } else {
133 // The group consists of only one element, therefore it cannot be folded 116 // The group consists of only one element, therefore it cannot be folded
134 None 117 None
@@ -169,10 +152,7 @@ fn contiguous_range_for_comment<'a>(
169 } 152 }
170 153
171 if first != last { 154 if first != last {
172 Some(TextRange::from_to( 155 Some(TextRange::from_to(first.range().start(), last.range().end()))
173 first.range().start(),
174 last.range().end(),
175 ))
176 } else { 156 } else {
177 // The group consists of only one element, therefore it cannot be folded 157 // The group consists of only one element, therefore it cannot be folded
178 None 158 None
@@ -199,10 +179,8 @@ mod tests {
199 fold_kinds.len(), 179 fold_kinds.len(),
200 "The amount of fold kinds is different than the expected amount" 180 "The amount of fold kinds is different than the expected amount"
201 ); 181 );
202 for ((fold, range), fold_kind) in folds 182 for ((fold, range), fold_kind) in
203 .into_iter() 183 folds.into_iter().zip(ranges.into_iter()).zip(fold_kinds.into_iter())
204 .zip(ranges.into_iter())
205 .zip(fold_kinds.into_iter())
206 { 184 {
207 assert_eq!(fold.range.start(), range.start()); 185 assert_eq!(fold.range.start(), range.start());
208 assert_eq!(fold.range.end(), range.end()); 186 assert_eq!(fold.range.end(), range.end());
@@ -280,12 +258,7 @@ mod with_attribute_next;</fold>
280fn main() <fold>{ 258fn main() <fold>{
281}</fold>"#; 259}</fold>"#;
282 260
283 let folds = &[ 261 let folds = &[FoldKind::Mods, FoldKind::Mods, FoldKind::Mods, FoldKind::Block];
284 FoldKind::Mods,
285 FoldKind::Mods,
286 FoldKind::Mods,
287 FoldKind::Block,
288 ];
289 do_check(text, folds); 262 do_check(text, folds);
290 } 263 }
291 264
diff --git a/crates/ra_ide_api_light/src/formatting.rs b/crates/ra_ide_api_light/src/formatting.rs
index 46ffa7d96..8bc03f974 100644
--- a/crates/ra_ide_api_light/src/formatting.rs
+++ b/crates/ra_ide_api_light/src/formatting.rs
@@ -32,10 +32,7 @@ fn prev_leaves(node: &SyntaxNode) -> impl Iterator<Item = &SyntaxNode> {
32} 32}
33 33
34fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> { 34fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> {
35 generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| { 35 generate(node.ancestors().find_map(SyntaxNode::prev_sibling), |it| it.last_child()).last()
36 it.last_child()
37 })
38 .last()
39} 36}
40 37
41pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> { 38pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> {
diff --git a/crates/ra_ide_api_light/src/join_lines.rs b/crates/ra_ide_api_light/src/join_lines.rs
index ab7c5b4b5..03770c52e 100644
--- a/crates/ra_ide_api_light/src/join_lines.rs
+++ b/crates/ra_ide_api_light/src/join_lines.rs
@@ -50,11 +50,7 @@ pub fn join_lines(file: &SourceFile, range: TextRange) -> LocalEdit {
50 } 50 }
51 } 51 }
52 52
53 LocalEdit { 53 LocalEdit { label: "join lines".to_string(), edit: edit.finish(), cursor_position: None }
54 label: "join lines".to_string(),
55 edit: edit.finish(),
56 cursor_position: None,
57 }
58} 54}
59 55
60fn remove_newline( 56fn remove_newline(
@@ -71,10 +67,7 @@ fn remove_newline(
71 )]; 67 )];
72 let spaces = suff.bytes().take_while(|&b| b == b' ').count(); 68 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
73 69
74 edit.replace( 70 edit.replace(TextRange::offset_len(offset, ((spaces + 1) as u32).into()), " ".to_string());
75 TextRange::offset_len(offset, ((spaces + 1) as u32).into()),
76 " ".to_string(),
77 );
78 return; 71 return;
79 } 72 }
80 73
@@ -109,11 +102,7 @@ fn remove_newline(
109 edit.delete(TextRange::from_to(prev.range().start(), node.range().end())); 102 edit.delete(TextRange::from_to(prev.range().start(), node.range().end()));
110 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 103 } else if prev.kind() == COMMA && next.kind() == R_CURLY {
111 // Removes: comma, newline (incl. surrounding whitespace) 104 // Removes: comma, newline (incl. surrounding whitespace)
112 let space = if let Some(left) = prev.prev_sibling() { 105 let space = if let Some(left) = prev.prev_sibling() { compute_ws(left, next) } else { " " };
113 compute_ws(left, next)
114 } else {
115 " "
116 };
117 edit.replace( 106 edit.replace(
118 TextRange::from_to(prev.range().start(), node.range().end()), 107 TextRange::from_to(prev.range().start(), node.range().end()),
119 space.to_string(), 108 space.to_string(),
@@ -134,20 +123,14 @@ fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Opti
134 let block = ast::Block::cast(node.parent()?)?; 123 let block = ast::Block::cast(node.parent()?)?;
135 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 124 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
136 let expr = extract_trivial_expression(block)?; 125 let expr = extract_trivial_expression(block)?;
137 edit.replace( 126 edit.replace(block_expr.syntax().range(), expr.syntax().text().to_string());
138 block_expr.syntax().range(),
139 expr.syntax().text().to_string(),
140 );
141 Some(()) 127 Some(())
142} 128}
143 129
144fn join_single_use_tree(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> { 130fn join_single_use_tree(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> {
145 let use_tree_list = ast::UseTreeList::cast(node.parent()?)?; 131 let use_tree_list = ast::UseTreeList::cast(node.parent()?)?;
146 let (tree,) = use_tree_list.use_trees().collect_tuple()?; 132 let (tree,) = use_tree_list.use_trees().collect_tuple()?;
147 edit.replace( 133 edit.replace(use_tree_list.syntax().range(), tree.syntax().text().to_string());
148 use_tree_list.syntax().range(),
149 tree.syntax().text().to_string(),
150 );
151 Some(()) 134 Some(())
152} 135}
153 136
diff --git a/crates/ra_ide_api_light/src/lib.rs b/crates/ra_ide_api_light/src/lib.rs
index 17044270c..f3078f51e 100644
--- a/crates/ra_ide_api_light/src/lib.rs
+++ b/crates/ra_ide_api_light/src/lib.rs
@@ -63,9 +63,8 @@ pub struct Diagnostic {
63} 63}
64 64
65pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 65pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
66 const BRACES: &[SyntaxKind] = &[ 66 const BRACES: &[SyntaxKind] =
67 L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE, 67 &[L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE];
68 ];
69 let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset) 68 let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset)
70 .filter_map(|node| { 69 .filter_map(|node| {
71 let idx = BRACES.iter().position(|&brace| brace == node.kind())?; 70 let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
@@ -74,9 +73,7 @@ pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
74 .next()?; 73 .next()?;
75 let parent = brace_node.parent()?; 74 let parent = brace_node.parent()?;
76 let matching_kind = BRACES[brace_idx ^ 1]; 75 let matching_kind = BRACES[brace_idx ^ 1];
77 let matching_node = parent 76 let matching_node = parent.children().find(|node| node.kind() == matching_kind)?;
78 .children()
79 .find(|node| node.kind() == matching_kind)?;
80 Some(matching_node.range().start()) 77 Some(matching_node.range().start())
81} 78}
82 79
@@ -122,10 +119,7 @@ pub fn highlight(root: &SyntaxNode) -> Vec<HighlightedRange> {
122 continue; 119 continue;
123 } 120 }
124 }; 121 };
125 res.push(HighlightedRange { 122 res.push(HighlightedRange { range: node.range(), tag })
126 range: node.range(),
127 tag,
128 })
129 } 123 }
130 res 124 res
131} 125}
diff --git a/crates/ra_ide_api_light/src/line_index.rs b/crates/ra_ide_api_light/src/line_index.rs
index 131737743..bf004c33a 100644
--- a/crates/ra_ide_api_light/src/line_index.rs
+++ b/crates/ra_ide_api_light/src/line_index.rs
@@ -54,10 +54,7 @@ impl LineIndex {
54 54
55 let char_len = TextUnit::of_char(c); 55 let char_len = TextUnit::of_char(c);
56 if char_len.to_usize() > 1 { 56 if char_len.to_usize() > 1 {
57 utf16_chars.push(Utf16Char { 57 utf16_chars.push(Utf16Char { start: curr_col, end: curr_col + char_len });
58 start: curr_col,
59 end: curr_col + char_len,
60 });
61 } 58 }
62 59
63 curr_col += char_len; 60 curr_col += char_len;
@@ -68,10 +65,7 @@ impl LineIndex {
68 utf16_lines.insert(line, utf16_chars); 65 utf16_lines.insert(line, utf16_chars);
69 } 66 }
70 67
71 LineIndex { 68 LineIndex { newlines, utf16_lines }
72 newlines,
73 utf16_lines,
74 }
75 } 69 }
76 70
77 pub fn line_col(&self, offset: TextUnit) -> LineCol { 71 pub fn line_col(&self, offset: TextUnit) -> LineCol {
@@ -79,10 +73,7 @@ impl LineIndex {
79 let line_start_offset = self.newlines[line]; 73 let line_start_offset = self.newlines[line];
80 let col = offset - line_start_offset; 74 let col = offset - line_start_offset;
81 75
82 LineCol { 76 LineCol { line: line as u32, col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32 }
83 line: line as u32,
84 col_utf16: self.utf8_to_utf16_col(line as u32, col) as u32,
85 }
86 } 77 }
87 78
88 pub fn offset(&self, line_col: LineCol) -> TextUnit { 79 pub fn offset(&self, line_col: LineCol) -> TextUnit {
@@ -131,10 +122,7 @@ impl LineIndex {
131#[cfg(test)] 122#[cfg(test)]
132/// Simple reference implementation to use in proptests 123/// Simple reference implementation to use in proptests
133pub fn to_line_col(text: &str, offset: TextUnit) -> LineCol { 124pub fn to_line_col(text: &str, offset: TextUnit) -> LineCol {
134 let mut res = LineCol { 125 let mut res = LineCol { line: 0, col_utf16: 0 };
135 line: 0,
136 col_utf16: 0,
137 };
138 for (i, c) in text.char_indices() { 126 for (i, c) in text.char_indices() {
139 if i + c.len_utf8() > offset.to_usize() { 127 if i + c.len_utf8() > offset.to_usize() {
140 // if it's an invalid offset, inside a multibyte char 128 // if it's an invalid offset, inside a multibyte char
@@ -161,120 +149,31 @@ mod test_line_index {
161 fn test_line_index() { 149 fn test_line_index() {
162 let text = "hello\nworld"; 150 let text = "hello\nworld";
163 let index = LineIndex::new(text); 151 let index = LineIndex::new(text);
164 assert_eq!( 152 assert_eq!(index.line_col(0.into()), LineCol { line: 0, col_utf16: 0 });
165 index.line_col(0.into()), 153 assert_eq!(index.line_col(1.into()), LineCol { line: 0, col_utf16: 1 });
166 LineCol { 154 assert_eq!(index.line_col(5.into()), LineCol { line: 0, col_utf16: 5 });
167 line: 0, 155 assert_eq!(index.line_col(6.into()), LineCol { line: 1, col_utf16: 0 });
168 col_utf16: 0 156 assert_eq!(index.line_col(7.into()), LineCol { line: 1, col_utf16: 1 });
169 } 157 assert_eq!(index.line_col(8.into()), LineCol { line: 1, col_utf16: 2 });
170 ); 158 assert_eq!(index.line_col(10.into()), LineCol { line: 1, col_utf16: 4 });
171 assert_eq!( 159 assert_eq!(index.line_col(11.into()), LineCol { line: 1, col_utf16: 5 });
172 index.line_col(1.into()), 160 assert_eq!(index.line_col(12.into()), LineCol { line: 1, col_utf16: 6 });
173 LineCol {
174 line: 0,
175 col_utf16: 1
176 }
177 );
178 assert_eq!(
179 index.line_col(5.into()),
180 LineCol {
181 line: 0,
182 col_utf16: 5
183 }
184 );
185 assert_eq!(
186 index.line_col(6.into()),
187 LineCol {
188 line: 1,
189 col_utf16: 0
190 }
191 );
192 assert_eq!(
193 index.line_col(7.into()),
194 LineCol {
195 line: 1,
196 col_utf16: 1
197 }
198 );
199 assert_eq!(
200 index.line_col(8.into()),
201 LineCol {
202 line: 1,
203 col_utf16: 2
204 }
205 );
206 assert_eq!(
207 index.line_col(10.into()),
208 LineCol {
209 line: 1,
210 col_utf16: 4
211 }
212 );
213 assert_eq!(
214 index.line_col(11.into()),
215 LineCol {
216 line: 1,
217 col_utf16: 5
218 }
219 );
220 assert_eq!(
221 index.line_col(12.into()),
222 LineCol {
223 line: 1,
224 col_utf16: 6
225 }
226 );
227 161
228 let text = "\nhello\nworld"; 162 let text = "\nhello\nworld";
229 let index = LineIndex::new(text); 163 let index = LineIndex::new(text);
230 assert_eq!( 164 assert_eq!(index.line_col(0.into()), LineCol { line: 0, col_utf16: 0 });
231 index.line_col(0.into()), 165 assert_eq!(index.line_col(1.into()), LineCol { line: 1, col_utf16: 0 });
232 LineCol { 166 assert_eq!(index.line_col(2.into()), LineCol { line: 1, col_utf16: 1 });
233 line: 0, 167 assert_eq!(index.line_col(6.into()), LineCol { line: 1, col_utf16: 5 });
234 col_utf16: 0 168 assert_eq!(index.line_col(7.into()), LineCol { line: 2, col_utf16: 0 });
235 }
236 );
237 assert_eq!(
238 index.line_col(1.into()),
239 LineCol {
240 line: 1,
241 col_utf16: 0
242 }
243 );
244 assert_eq!(
245 index.line_col(2.into()),
246 LineCol {
247 line: 1,
248 col_utf16: 1
249 }
250 );
251 assert_eq!(
252 index.line_col(6.into()),
253 LineCol {
254 line: 1,
255 col_utf16: 5
256 }
257 );
258 assert_eq!(
259 index.line_col(7.into()),
260 LineCol {
261 line: 2,
262 col_utf16: 0
263 }
264 );
265 } 169 }
266 170
267 fn arb_text_with_offset() -> BoxedStrategy<(TextUnit, String)> { 171 fn arb_text_with_offset() -> BoxedStrategy<(TextUnit, String)> {
268 arb_text() 172 arb_text().prop_flat_map(|text| (arb_offset(&text), Just(text))).boxed()
269 .prop_flat_map(|text| (arb_offset(&text), Just(text)))
270 .boxed()
271 } 173 }
272 174
273 fn to_line_col(text: &str, offset: TextUnit) -> LineCol { 175 fn to_line_col(text: &str, offset: TextUnit) -> LineCol {
274 let mut res = LineCol { 176 let mut res = LineCol { line: 0, col_utf16: 0 };
275 line: 0,
276 col_utf16: 0,
277 };
278 for (i, c) in text.char_indices() { 177 for (i, c) in text.char_indices() {
279 if i + c.len_utf8() > offset.to_usize() { 178 if i + c.len_utf8() > offset.to_usize() {
280 // if it's an invalid offset, inside a multibyte char 179 // if it's an invalid offset, inside a multibyte char
@@ -333,13 +232,7 @@ const C: char = 'メ';
333 232
334 assert_eq!(col_index.utf16_lines.len(), 1); 233 assert_eq!(col_index.utf16_lines.len(), 1);
335 assert_eq!(col_index.utf16_lines[&1].len(), 1); 234 assert_eq!(col_index.utf16_lines[&1].len(), 1);
336 assert_eq!( 235 assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
337 col_index.utf16_lines[&1][0],
338 Utf16Char {
339 start: 17.into(),
340 end: 20.into()
341 }
342 );
343 236
344 // UTF-8 to UTF-16, no changes 237 // UTF-8 to UTF-16, no changes
345 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15); 238 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
@@ -364,20 +257,8 @@ const C: char = \"メ メ\";
364 257
365 assert_eq!(col_index.utf16_lines.len(), 1); 258 assert_eq!(col_index.utf16_lines.len(), 1);
366 assert_eq!(col_index.utf16_lines[&1].len(), 2); 259 assert_eq!(col_index.utf16_lines[&1].len(), 2);
367 assert_eq!( 260 assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
368 col_index.utf16_lines[&1][0], 261 assert_eq!(col_index.utf16_lines[&1][1], Utf16Char { start: 21.into(), end: 24.into() });
369 Utf16Char {
370 start: 17.into(),
371 end: 20.into()
372 }
373 );
374 assert_eq!(
375 col_index.utf16_lines[&1][1],
376 Utf16Char {
377 start: 21.into(),
378 end: 24.into()
379 }
380 );
381 262
382 // UTF-8 to UTF-16 263 // UTF-8 to UTF-16
383 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15); 264 assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
diff --git a/crates/ra_ide_api_light/src/line_index_utils.rs b/crates/ra_ide_api_light/src/line_index_utils.rs
index 5d9ab6fd2..799a920ad 100644
--- a/crates/ra_ide_api_light/src/line_index_utils.rs
+++ b/crates/ra_ide_api_light/src/line_index_utils.rs
@@ -17,11 +17,7 @@ struct LineIndexStepIter<'a> {
17 17
18impl<'a> LineIndexStepIter<'a> { 18impl<'a> LineIndexStepIter<'a> {
19 fn from(line_index: &LineIndex) -> LineIndexStepIter { 19 fn from(line_index: &LineIndex) -> LineIndexStepIter {
20 let mut x = LineIndexStepIter { 20 let mut x = LineIndexStepIter { line_index, next_newline_idx: 0, utf16_chars: None };
21 line_index,
22 next_newline_idx: 0,
23 utf16_chars: None,
24 };
25 // skip first newline since it's not real 21 // skip first newline since it's not real
26 x.next(); 22 x.next();
27 x 23 x
@@ -35,10 +31,7 @@ impl<'a> Iterator for LineIndexStepIter<'a> {
35 .as_mut() 31 .as_mut()
36 .and_then(|(newline, x)| { 32 .and_then(|(newline, x)| {
37 let x = x.next()?; 33 let x = x.next()?;
38 Some(Step::Utf16Char(TextRange::from_to( 34 Some(Step::Utf16Char(TextRange::from_to(*newline + x.start, *newline + x.end)))
39 *newline + x.start,
40 *newline + x.end,
41 )))
42 }) 35 })
43 .or_else(|| { 36 .or_else(|| {
44 let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?; 37 let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?;
@@ -113,11 +106,7 @@ struct Edits<'a> {
113 106
114impl<'a> Edits<'a> { 107impl<'a> Edits<'a> {
115 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> { 108 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> {
116 let mut x = Edits { 109 let mut x = Edits { edits: text_edit.as_atoms(), current: None, acc_diff: 0 };
117 edits: text_edit.as_atoms(),
118 current: None,
119 acc_diff: 0,
120 };
121 x.advance_edit(); 110 x.advance_edit();
122 x 111 x
123 } 112 }
@@ -127,11 +116,7 @@ impl<'a> Edits<'a> {
127 Some((next, rest)) => { 116 Some((next, rest)) => {
128 let delete = self.translate_range(next.delete); 117 let delete = self.translate_range(next.delete);
129 let diff = next.insert.len() as i64 - next.delete.len().to_usize() as i64; 118 let diff = next.insert.len() as i64 - next.delete.len().to_usize() as i64;
130 self.current = Some(TranslatedEdit { 119 self.current = Some(TranslatedEdit { delete, insert: &next.insert, diff });
131 delete,
132 insert: &next.insert,
133 diff,
134 });
135 self.edits = rest; 120 self.edits = rest;
136 } 121 }
137 None => { 122 None => {
@@ -142,10 +127,7 @@ impl<'a> Edits<'a> {
142 127
143 fn next_inserted_steps(&mut self) -> Option<OffsetStepIter<'a>> { 128 fn next_inserted_steps(&mut self) -> Option<OffsetStepIter<'a>> {
144 let cur = self.current.as_ref()?; 129 let cur = self.current.as_ref()?;
145 let res = Some(OffsetStepIter { 130 let res = Some(OffsetStepIter { offset: cur.delete.start(), text: &cur.insert });
146 offset: cur.delete.start(),
147 text: &cur.insert,
148 });
149 self.advance_edit(); 131 self.advance_edit();
150 res 132 res
151 } 133 }
@@ -160,18 +142,12 @@ impl<'a> Edits<'a> {
160 if step_pos <= edit.delete.start() { 142 if step_pos <= edit.delete.start() {
161 NextSteps::Use 143 NextSteps::Use
162 } else if step_pos <= edit.delete.end() { 144 } else if step_pos <= edit.delete.end() {
163 let iter = OffsetStepIter { 145 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
164 offset: edit.delete.start(),
165 text: &edit.insert,
166 };
167 // empty slice to avoid returning steps again 146 // empty slice to avoid returning steps again
168 edit.insert = &edit.insert[edit.insert.len()..]; 147 edit.insert = &edit.insert[edit.insert.len()..];
169 NextSteps::ReplaceMany(iter) 148 NextSteps::ReplaceMany(iter)
170 } else { 149 } else {
171 let iter = OffsetStepIter { 150 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
172 offset: edit.delete.start(),
173 text: &edit.insert,
174 };
175 // empty slice to avoid returning steps again 151 // empty slice to avoid returning steps again
176 edit.insert = &edit.insert[edit.insert.len()..]; 152 edit.insert = &edit.insert[edit.insert.len()..];
177 self.advance_edit(); 153 self.advance_edit();
@@ -222,11 +198,7 @@ struct RunningLineCol {
222 198
223impl RunningLineCol { 199impl RunningLineCol {
224 fn new() -> RunningLineCol { 200 fn new() -> RunningLineCol {
225 RunningLineCol { 201 RunningLineCol { line: 0, last_newline: TextUnit::from(0), col_adjust: TextUnit::from(0) }
226 line: 0,
227 last_newline: TextUnit::from(0),
228 col_adjust: TextUnit::from(0),
229 }
230 } 202 }
231 203
232 fn to_line_col(&self, offset: TextUnit) -> LineCol { 204 fn to_line_col(&self, offset: TextUnit) -> LineCol {
@@ -339,12 +311,7 @@ mod test {
339 let edited_text = x.edit.apply(&x.text); 311 let edited_text = x.edit.apply(&x.text);
340 let arb_offset = arb_offset(&edited_text); 312 let arb_offset = arb_offset(&edited_text);
341 (Just(x), Just(edited_text), arb_offset).prop_map(|(x, edited_text, offset)| { 313 (Just(x), Just(edited_text), arb_offset).prop_map(|(x, edited_text, offset)| {
342 ArbTextWithEditAndOffset { 314 ArbTextWithEditAndOffset { text: x.text, edit: x.edit, edited_text, offset }
343 text: x.text,
344 edit: x.edit,
345 edited_text,
346 offset,
347 }
348 }) 315 })
349 }) 316 })
350 .boxed() 317 .boxed()
diff --git a/crates/ra_ide_api_light/src/structure.rs b/crates/ra_ide_api_light/src/structure.rs
index 330a3694c..75afd1181 100644
--- a/crates/ra_ide_api_light/src/structure.rs
+++ b/crates/ra_ide_api_light/src/structure.rs
@@ -70,10 +70,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
70 node_range: node.syntax().range(), 70 node_range: node.syntax().range(),
71 kind: node.syntax().kind(), 71 kind: node.syntax().kind(),
72 detail, 72 detail,
73 deprecated: node 73 deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
74 .attrs()
75 .filter_map(|x| x.as_named())
76 .any(|x| x == "deprecated"),
77 }) 74 })
78 } 75 }
79 76
@@ -123,11 +120,9 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
123 let target_trait = im.target_trait(); 120 let target_trait = im.target_trait();
124 let label = match target_trait { 121 let label = match target_trait {
125 None => format!("impl {}", target_type.syntax().text()), 122 None => format!("impl {}", target_type.syntax().text()),
126 Some(t) => format!( 123 Some(t) => {
127 "impl {} for {}", 124 format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
128 t.syntax().text(), 125 }
129 target_type.syntax().text(),
130 ),
131 }; 126 };
132 127
133 let node = StructureNode { 128 let node = StructureNode {
diff --git a/crates/ra_ide_api_light/src/typing.rs b/crates/ra_ide_api_light/src/typing.rs
index 861027b9f..a08a5a8c5 100644
--- a/crates/ra_ide_api_light/src/typing.rs
+++ b/crates/ra_ide_api_light/src/typing.rs
@@ -8,9 +8,8 @@ use ra_syntax::{
8use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent}; 8use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent};
9 9
10pub fn on_enter(file: &SourceFile, offset: TextUnit) -> Option<LocalEdit> { 10pub fn on_enter(file: &SourceFile, offset: TextUnit) -> Option<LocalEdit> {
11 let comment = find_leaf_at_offset(file.syntax(), offset) 11 let comment =
12 .left_biased() 12 find_leaf_at_offset(file.syntax(), offset).left_biased().and_then(ast::Comment::cast)?;
13 .and_then(ast::Comment::cast)?;
14 13
15 if let ast::CommentFlavor::Multiline = comment.flavor() { 14 if let ast::CommentFlavor::Multiline = comment.flavor() {
16 return None; 15 return None;
@@ -64,12 +63,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<LocalEdit>
64 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() { 63 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() {
65 return None; 64 return None;
66 } 65 }
67 if file 66 if file.syntax().text().slice(eq_offset..expr_range.start()).contains('\n') {
68 .syntax()
69 .text()
70 .slice(eq_offset..expr_range.start())
71 .contains('\n')
72 {
73 return None; 67 return None;
74 } 68 }
75 } else { 69 } else {
@@ -100,10 +94,7 @@ pub fn on_dot_typed(file: &SourceFile, dot_offset: TextUnit) -> Option<LocalEdit
100 let current_indent_len = TextUnit::of_str(current_indent); 94 let current_indent_len = TextUnit::of_str(current_indent);
101 95
102 // Make sure dot is a part of call chain 96 // Make sure dot is a part of call chain
103 let field_expr = whitespace 97 let field_expr = whitespace.syntax().parent().and_then(ast::FieldExpr::cast)?;
104 .syntax()
105 .parent()
106 .and_then(ast::FieldExpr::cast)?;
107 let prev_indent = leading_indent(field_expr.syntax())?; 98 let prev_indent = leading_indent(field_expr.syntax())?;
108 let target_indent = format!(" {}", prev_indent); 99 let target_indent = format!(" {}", prev_indent);
109 let target_indent_len = TextUnit::of_str(&target_indent); 100 let target_indent_len = TextUnit::of_str(&target_indent);