diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/utils/insert_use.rs | 73 | ||||
-rw-r--r-- | crates/syntax/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/syntax/src/parsing/lexer.rs | 8 |
3 files changed, 57 insertions, 26 deletions
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index 5719b06af..8dd4fe607 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs | |||
@@ -174,7 +174,7 @@ pub(crate) fn try_merge_trees( | |||
174 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; | 174 | let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; |
175 | let lhs = lhs.split_prefix(&lhs_prefix); | 175 | let lhs = lhs.split_prefix(&lhs_prefix); |
176 | let rhs = rhs.split_prefix(&rhs_prefix); | 176 | let rhs = rhs.split_prefix(&rhs_prefix); |
177 | recursive_merge(&lhs, &rhs, merge).map(|(merged, _)| merged) | 177 | recursive_merge(&lhs, &rhs, merge) |
178 | } | 178 | } |
179 | 179 | ||
180 | /// Recursively "zips" together lhs and rhs. | 180 | /// Recursively "zips" together lhs and rhs. |
@@ -182,20 +182,22 @@ fn recursive_merge( | |||
182 | lhs: &ast::UseTree, | 182 | lhs: &ast::UseTree, |
183 | rhs: &ast::UseTree, | 183 | rhs: &ast::UseTree, |
184 | merge: MergeBehaviour, | 184 | merge: MergeBehaviour, |
185 | ) -> Option<(ast::UseTree, bool)> { | 185 | ) -> Option<ast::UseTree> { |
186 | let mut use_trees = lhs | 186 | let mut use_trees = lhs |
187 | .use_tree_list() | 187 | .use_tree_list() |
188 | .into_iter() | 188 | .into_iter() |
189 | .flat_map(|list| list.use_trees()) | 189 | .flat_map(|list| list.use_trees()) |
190 | // check if any of the use trees are nested, if they are and the behaviour is `last` we are not allowed to merge this | 190 | // we use Option here to early return from this function(this is not the same as a `filter` op) |
191 | // so early exit the iterator by using Option's Intoiterator impl | 191 | .map(|tree| match merge.is_tree_allowed(&tree) { |
192 | .map(|tree| match merge == MergeBehaviour::Last && tree.use_tree_list().is_some() { | 192 | true => Some(tree), |
193 | true => None, | 193 | false => None, |
194 | false => Some(tree), | ||
195 | }) | 194 | }) |
196 | .collect::<Option<Vec<_>>>()?; | 195 | .collect::<Option<Vec<_>>>()?; |
197 | use_trees.sort_unstable_by(|a, b| path_cmp_opt(a.path(), b.path())); | 196 | use_trees.sort_unstable_by(|a, b| path_cmp_opt(a.path(), b.path())); |
198 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { | 197 | for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { |
198 | if !merge.is_tree_allowed(&rhs_t) { | ||
199 | return None; | ||
200 | } | ||
199 | let rhs_path = rhs_t.path(); | 201 | let rhs_path = rhs_t.path(); |
200 | match use_trees.binary_search_by(|p| path_cmp_opt(p.path(), rhs_path.clone())) { | 202 | match use_trees.binary_search_by(|p| path_cmp_opt(p.path(), rhs_path.clone())) { |
201 | Ok(idx) => { | 203 | Ok(idx) => { |
@@ -239,17 +241,9 @@ fn recursive_merge( | |||
239 | } | 241 | } |
240 | let lhs = lhs_t.split_prefix(&lhs_prefix); | 242 | let lhs = lhs_t.split_prefix(&lhs_prefix); |
241 | let rhs = rhs_t.split_prefix(&rhs_prefix); | 243 | let rhs = rhs_t.split_prefix(&rhs_prefix); |
242 | let this_has_children = use_trees.len() > 0; | ||
243 | match recursive_merge(&lhs, &rhs, merge) { | 244 | match recursive_merge(&lhs, &rhs, merge) { |
244 | Some((_, has_multiple_children)) | 245 | Some(use_tree) => use_trees[idx] = use_tree, |
245 | if merge == MergeBehaviour::Last | 246 | None => return None, |
246 | && this_has_children | ||
247 | && has_multiple_children => | ||
248 | { | ||
249 | return None | ||
250 | } | ||
251 | Some((use_tree, _)) => use_trees[idx] = use_tree, | ||
252 | None => use_trees.insert(idx, rhs_t), | ||
253 | } | 247 | } |
254 | } | 248 | } |
255 | Err(_) | 249 | Err(_) |
@@ -264,8 +258,7 @@ fn recursive_merge( | |||
264 | } | 258 | } |
265 | } | 259 | } |
266 | } | 260 | } |
267 | let has_multiple_children = use_trees.len() > 1; | 261 | Some(lhs.with_use_tree_list(make::use_tree_list(use_trees))) |
268 | Some((lhs.with_use_tree_list(make::use_tree_list(use_trees)), has_multiple_children)) | ||
269 | } | 262 | } |
270 | 263 | ||
271 | /// Traverses both paths until they differ, returning the common prefix of both. | 264 | /// Traverses both paths until they differ, returning the common prefix of both. |
@@ -308,6 +301,10 @@ fn segment_iter(path: &ast::Path) -> impl Iterator<Item = ast::PathSegment> + Cl | |||
308 | successors(first_segment(path), |p| p.parent_path().parent_path().and_then(|p| p.segment())) | 301 | successors(first_segment(path), |p| p.parent_path().parent_path().and_then(|p| p.segment())) |
309 | } | 302 | } |
310 | 303 | ||
304 | fn path_len(path: ast::Path) -> usize { | ||
305 | segment_iter(&path).count() | ||
306 | } | ||
307 | |||
311 | /// Orders paths in the following way: | 308 | /// Orders paths in the following way: |
312 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers | 309 | /// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers |
313 | // FIXME: rustfmt sort lowercase idents before uppercase, in general we want to have the same ordering rustfmt has | 310 | // FIXME: rustfmt sort lowercase idents before uppercase, in general we want to have the same ordering rustfmt has |
@@ -352,6 +349,19 @@ pub enum MergeBehaviour { | |||
352 | Last, | 349 | Last, |
353 | } | 350 | } |
354 | 351 | ||
352 | impl MergeBehaviour { | ||
353 | #[inline] | ||
354 | fn is_tree_allowed(&self, tree: &ast::UseTree) -> bool { | ||
355 | match self { | ||
356 | MergeBehaviour::Full => true, | ||
357 | // only simple single segment paths are allowed | ||
358 | MergeBehaviour::Last => { | ||
359 | tree.use_tree_list().is_none() && tree.path().map(path_len) <= Some(1) | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | |||
355 | #[derive(Eq, PartialEq, PartialOrd, Ord)] | 365 | #[derive(Eq, PartialEq, PartialOrd, Ord)] |
356 | enum ImportGroup { | 366 | enum ImportGroup { |
357 | // the order here defines the order of new group inserts | 367 | // the order here defines the order of new group inserts |
@@ -676,6 +686,11 @@ use std::io;", | |||
676 | } | 686 | } |
677 | 687 | ||
678 | #[test] | 688 | #[test] |
689 | fn merge_last_into_self() { | ||
690 | check_last("foo::bar::baz", r"use foo::bar;", r"use foo::bar::{self, baz};"); | ||
691 | } | ||
692 | |||
693 | #[test] | ||
679 | fn merge_groups_full() { | 694 | fn merge_groups_full() { |
680 | check_full( | 695 | check_full( |
681 | "std::io", | 696 | "std::io", |
@@ -819,8 +834,24 @@ use std::io;", | |||
819 | } | 834 | } |
820 | 835 | ||
821 | #[test] | 836 | #[test] |
822 | fn merge_last_too_long() { | 837 | fn skip_merge_last_too_long() { |
823 | check_last("foo::bar", r"use foo::bar::baz::Qux;", r"use foo::bar::{self, baz::Qux};"); | 838 | check_last( |
839 | "foo::bar", | ||
840 | r"use foo::bar::baz::Qux;", | ||
841 | r"use foo::bar; | ||
842 | use foo::bar::baz::Qux;", | ||
843 | ); | ||
844 | } | ||
845 | |||
846 | #[test] | ||
847 | #[ignore] // FIXME: Order changes when switching lhs and rhs | ||
848 | fn skip_merge_last_too_long2() { | ||
849 | check_last( | ||
850 | "foo::bar::baz::Qux", | ||
851 | r"use foo::bar;", | ||
852 | r"use foo::bar; | ||
853 | use foo::bar::baz::Qux;", | ||
854 | ); | ||
824 | } | 855 | } |
825 | 856 | ||
826 | #[test] | 857 | #[test] |
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index af61bb658..0b15f10e9 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -13,7 +13,7 @@ doctest = false | |||
13 | [dependencies] | 13 | [dependencies] |
14 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
15 | rowan = "0.10.0" | 15 | rowan = "0.10.0" |
16 | rustc_lexer = { version = "673.0.0", package = "rustc-ap-rustc_lexer" } | 16 | rustc_lexer = { version = "681.0.0", package = "rustc-ap-rustc_lexer" } |
17 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
18 | arrayvec = "0.5.1" | 18 | arrayvec = "0.5.1" |
19 | once_cell = "1.3.1" | 19 | once_cell = "1.3.1" |
diff --git a/crates/syntax/src/parsing/lexer.rs b/crates/syntax/src/parsing/lexer.rs index fa3be1016..f1202113b 100644 --- a/crates/syntax/src/parsing/lexer.rs +++ b/crates/syntax/src/parsing/lexer.rs | |||
@@ -120,10 +120,10 @@ fn rustc_token_kind_to_syntax_kind( | |||
120 | 120 | ||
121 | let syntax_kind = { | 121 | let syntax_kind = { |
122 | match rustc_token_kind { | 122 | match rustc_token_kind { |
123 | rustc_lexer::TokenKind::LineComment => COMMENT, | 123 | rustc_lexer::TokenKind::LineComment { doc_style: _ } => COMMENT, |
124 | 124 | ||
125 | rustc_lexer::TokenKind::BlockComment { terminated: true } => COMMENT, | 125 | rustc_lexer::TokenKind::BlockComment { doc_style: _, terminated: true } => COMMENT, |
126 | rustc_lexer::TokenKind::BlockComment { terminated: false } => { | 126 | rustc_lexer::TokenKind::BlockComment { doc_style: _, terminated: false } => { |
127 | return ( | 127 | return ( |
128 | COMMENT, | 128 | COMMENT, |
129 | Some("Missing trailing `*/` symbols to terminate the block comment"), | 129 | Some("Missing trailing `*/` symbols to terminate the block comment"), |
@@ -164,7 +164,7 @@ fn rustc_token_kind_to_syntax_kind( | |||
164 | rustc_lexer::TokenKind::Colon => T![:], | 164 | rustc_lexer::TokenKind::Colon => T![:], |
165 | rustc_lexer::TokenKind::Dollar => T![$], | 165 | rustc_lexer::TokenKind::Dollar => T![$], |
166 | rustc_lexer::TokenKind::Eq => T![=], | 166 | rustc_lexer::TokenKind::Eq => T![=], |
167 | rustc_lexer::TokenKind::Not => T![!], | 167 | rustc_lexer::TokenKind::Bang => T![!], |
168 | rustc_lexer::TokenKind::Lt => T![<], | 168 | rustc_lexer::TokenKind::Lt => T![<], |
169 | rustc_lexer::TokenKind::Gt => T![>], | 169 | rustc_lexer::TokenKind::Gt => T![>], |
170 | rustc_lexer::TokenKind::Minus => T![-], | 170 | rustc_lexer::TokenKind::Minus => T![-], |