aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock55
-rw-r--r--crates/assists/src/utils/insert_use.rs73
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/parsing/lexer.rs8
-rw-r--r--docs/dev/style.md9
5 files changed, 92 insertions, 55 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 74e5a8273..49022502d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -82,9 +82,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
82 82
83[[package]] 83[[package]]
84name = "backtrace" 84name = "backtrace"
85version = "0.3.50" 85version = "0.3.51"
86source = "registry+https://github.com/rust-lang/crates.io-index" 86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" 87checksum = "ec1931848a574faa8f7c71a12ea00453ff5effbb5f51afe7f77d7a48cace6ac1"
88dependencies = [ 88dependencies = [
89 "addr2line", 89 "addr2line",
90 "cfg-if", 90 "cfg-if",
@@ -214,9 +214,9 @@ dependencies = [
214 214
215[[package]] 215[[package]]
216name = "chrono" 216name = "chrono"
217version = "0.4.18" 217version = "0.4.19"
218source = "registry+https://github.com/rust-lang/crates.io-index" 218source = "registry+https://github.com/rust-lang/crates.io-index"
219checksum = "d021fddb7bd3e734370acfa4a83f34095571d8570c039f1420d77540f68d5772" 219checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
220dependencies = [ 220dependencies = [
221 "libc", 221 "libc",
222 "num-integer", 222 "num-integer",
@@ -365,9 +365,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
365 365
366[[package]] 366[[package]]
367name = "flate2" 367name = "flate2"
368version = "1.0.17" 368version = "1.0.18"
369source = "registry+https://github.com/rust-lang/crates.io-index" 369source = "registry+https://github.com/rust-lang/crates.io-index"
370checksum = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" 370checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee"
371dependencies = [ 371dependencies = [
372 "cfg-if", 372 "cfg-if",
373 "crc32fast", 373 "crc32fast",
@@ -453,9 +453,9 @@ dependencies = [
453 453
454[[package]] 454[[package]]
455name = "hashbrown" 455name = "hashbrown"
456version = "0.9.0" 456version = "0.9.1"
457source = "registry+https://github.com/rust-lang/crates.io-index" 457source = "registry+https://github.com/rust-lang/crates.io-index"
458checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" 458checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
459 459
460[[package]] 460[[package]]
461name = "heck" 461name = "heck"
@@ -725,9 +725,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
725 725
726[[package]] 726[[package]]
727name = "libc" 727name = "libc"
728version = "0.2.77" 728version = "0.2.78"
729source = "registry+https://github.com/rust-lang/crates.io-index" 729source = "registry+https://github.com/rust-lang/crates.io-index"
730checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" 730checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98"
731 731
732[[package]] 732[[package]]
733name = "libloading" 733name = "libloading"
@@ -1070,6 +1070,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1070checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1" 1070checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1"
1071 1071
1072[[package]] 1072[[package]]
1073name = "pin-project-lite"
1074version = "0.1.10"
1075source = "registry+https://github.com/rust-lang/crates.io-index"
1076checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95"
1077
1078[[package]]
1073name = "plain" 1079name = "plain"
1074version = "0.2.3" 1080version = "0.2.3"
1075source = "registry+https://github.com/rust-lang/crates.io-index" 1081source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1077,9 +1083,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
1077 1083
1078[[package]] 1084[[package]]
1079name = "proc-macro2" 1085name = "proc-macro2"
1080version = "1.0.23" 1086version = "1.0.24"
1081source = "registry+https://github.com/rust-lang/crates.io-index" 1087source = "registry+https://github.com/rust-lang/crates.io-index"
1082checksum = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" 1088checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
1083dependencies = [ 1089dependencies = [
1084 "unicode-xid", 1090 "unicode-xid",
1085] 1091]
@@ -1180,9 +1186,9 @@ dependencies = [
1180 1186
1181[[package]] 1187[[package]]
1182name = "rayon" 1188name = "rayon"
1183version = "1.4.0" 1189version = "1.4.1"
1184source = "registry+https://github.com/rust-lang/crates.io-index" 1190source = "registry+https://github.com/rust-lang/crates.io-index"
1185checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" 1191checksum = "dcf6960dc9a5b4ee8d3e4c5787b4a112a8818e0290a42ff664ad60692fdf2032"
1186dependencies = [ 1192dependencies = [
1187 "autocfg", 1193 "autocfg",
1188 "crossbeam-deque", 1194 "crossbeam-deque",
@@ -1294,9 +1300,9 @@ dependencies = [
1294 1300
1295[[package]] 1301[[package]]
1296name = "rustc-ap-rustc_lexer" 1302name = "rustc-ap-rustc_lexer"
1297version = "673.0.0" 1303version = "681.0.0"
1298source = "registry+https://github.com/rust-lang/crates.io-index" 1304source = "registry+https://github.com/rust-lang/crates.io-index"
1299checksum = "f6b71fa1285bdefe5fb61e59b63d6cc246abf337f4acafdd620d721bc488e671" 1305checksum = "01e579a90506e9d9c9a098f380cad55b9ecf9e7be9fa96cb67b31f52045f41a8"
1300dependencies = [ 1306dependencies = [
1301 "unicode-xid", 1307 "unicode-xid",
1302] 1308]
@@ -1427,9 +1433,9 @@ dependencies = [
1427 1433
1428[[package]] 1434[[package]]
1429name = "serde_json" 1435name = "serde_json"
1430version = "1.0.57" 1436version = "1.0.58"
1431source = "registry+https://github.com/rust-lang/crates.io-index" 1437source = "registry+https://github.com/rust-lang/crates.io-index"
1432checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" 1438checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4"
1433dependencies = [ 1439dependencies = [
1434 "itoa", 1440 "itoa",
1435 "ryu", 1441 "ryu",
@@ -1623,11 +1629,12 @@ dependencies = [
1623 1629
1624[[package]] 1630[[package]]
1625name = "tracing" 1631name = "tracing"
1626version = "0.1.19" 1632version = "0.1.21"
1627source = "registry+https://github.com/rust-lang/crates.io-index" 1633source = "registry+https://github.com/rust-lang/crates.io-index"
1628checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" 1634checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
1629dependencies = [ 1635dependencies = [
1630 "cfg-if", 1636 "cfg-if",
1637 "pin-project-lite",
1631 "tracing-attributes", 1638 "tracing-attributes",
1632 "tracing-core", 1639 "tracing-core",
1633] 1640]
@@ -1645,9 +1652,9 @@ dependencies = [
1645 1652
1646[[package]] 1653[[package]]
1647name = "tracing-core" 1654name = "tracing-core"
1648version = "0.1.16" 1655version = "0.1.17"
1649source = "registry+https://github.com/rust-lang/crates.io-index" 1656source = "registry+https://github.com/rust-lang/crates.io-index"
1650checksum = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a" 1657checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
1651dependencies = [ 1658dependencies = [
1652 "lazy_static", 1659 "lazy_static",
1653] 1660]
@@ -1696,9 +1703,9 @@ dependencies = [
1696 1703
1697[[package]] 1704[[package]]
1698name = "tracing-tree" 1705name = "tracing-tree"
1699version = "0.1.5" 1706version = "0.1.6"
1700source = "registry+https://github.com/rust-lang/crates.io-index" 1707source = "registry+https://github.com/rust-lang/crates.io-index"
1701checksum = "e1a3dc4774db3a6b2d66a4f8d8de670e874ec3ed55615860c994927419b32c5f" 1708checksum = "43aac8afb493b08e1e1904956f7407c1e671b9c83b26a17e1bd83d6a3520e350"
1702dependencies = [ 1709dependencies = [
1703 "ansi_term", 1710 "ansi_term",
1704 "atty", 1711 "atty",
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
304fn 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
352impl 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)]
356enum ImportGroup { 366enum 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;
842use 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;
853use 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]
14itertools = "0.9.0" 14itertools = "0.9.0"
15rowan = "0.10.0" 15rowan = "0.10.0"
16rustc_lexer = { version = "673.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "681.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
19once_cell = "1.3.1" 19once_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![-],
diff --git a/docs/dev/style.md b/docs/dev/style.md
index bcd86fd3f..f0fdb5adc 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -197,7 +197,7 @@ fn frobnicate(walrus: Option<Walrus>) {
197} 197}
198``` 198```
199 199
200Avoid preconditions that spawn function boundaries: 200Avoid preconditions that span across function boundaries:
201 201
202 202
203```rust 203```rust
@@ -218,9 +218,8 @@ fn foo() {
218} 218}
219 219
220// Not as good 220// Not as good
221fn is_string_literal(s: &str) -> Option<&str> { 221fn is_string_literal(s: &str) -> bool {
222 s.starts_with('"') && s.ends_with('"') 222 s.starts_with('"') && s.ends_with('"')
223 Some()
224} 223}
225 224
226fn foo() { 225fn foo() {
@@ -231,8 +230,8 @@ fn foo() {
231} 230}
232``` 231```
233 232
234In the "Not as good" version, the precondition that `1` is a valid char boundary is checked in `is_string_literal` and utilized in `foo`. 233In the "Not as good" version, the precondition that `1` is a valid char boundary is checked in `is_string_literal` and used in `foo`.
235In the "Good" version, precondition check and usage are checked in the same block, and then encoded in the types. 234In the "Good" version, the precondition check and usage are checked in the same block, and then encoded in the types.
236 235
237# Early Returns 236# Early Returns
238 237