diff options
Diffstat (limited to 'crates/ra_ide_api_light/src')
-rw-r--r-- | crates/ra_ide_api_light/src/diagnostics.rs | 32 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/extend_selection.rs | 57 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/folding_ranges.rs | 47 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/formatting.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/join_lines.rs | 27 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/lib.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/line_index.rs | 165 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/line_index_utils.rs | 51 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/structure.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide_api_light/src/typing.rs | 17 |
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 | ||
86 | fn has_visibility(node: &SyntaxNode) -> bool { | 74 | fn 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 | ||
92 | fn contiguous_range_for_group<'a>( | 78 | fn 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> | |||
280 | fn main() <fold>{ | 258 | fn 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 | ||
34 | fn prev_leaf(node: &SyntaxNode) -> Option<&SyntaxNode> { | 34 | fn 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 | ||
41 | pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> { | 38 | pub 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 | ||
60 | fn remove_newline( | 56 | fn 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 | ||
144 | fn join_single_use_tree(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> { | 130 | fn 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 | ||
65 | pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { | 65 | pub 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 |
133 | pub fn to_line_col(text: &str, offset: TextUnit) -> LineCol { | 124 | pub 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 | ||
18 | impl<'a> LineIndexStepIter<'a> { | 18 | impl<'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 | ||
114 | impl<'a> Edits<'a> { | 107 | impl<'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 | ||
223 | impl RunningLineCol { | 199 | impl 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::{ | |||
8 | use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent}; | 8 | use crate::{LocalEdit, TextEditBuilder, formatting::leading_indent}; |
9 | 9 | ||
10 | pub fn on_enter(file: &SourceFile, offset: TextUnit) -> Option<LocalEdit> { | 10 | pub 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); |