diff options
66 files changed, 288 insertions, 486 deletions
diff --git a/.cargo/config b/.cargo/config index 560ab3075..f6b0b66bf 100644 --- a/.cargo/config +++ b/.cargo/config | |||
@@ -3,3 +3,6 @@ xtask = "run --package xtask --bin xtask --" | |||
3 | install-ra = "run --package xtask --bin xtask -- install" # for backwards compat | 3 | install-ra = "run --package xtask --bin xtask -- install" # for backwards compat |
4 | tq = "test -- -q" | 4 | tq = "test -- -q" |
5 | qt = "tq" | 5 | qt = "tq" |
6 | |||
7 | [target.x86_64-pc-windows-msvc] | ||
8 | linker = "rust-lld" | ||
diff --git a/Cargo.lock b/Cargo.lock index 5e0dc061f..46d9469c0 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -76,9 +76,9 @@ dependencies = [ | |||
76 | 76 | ||
77 | [[package]] | 77 | [[package]] |
78 | name = "autocfg" | 78 | name = "autocfg" |
79 | version = "1.0.0" | 79 | version = "1.0.1" |
80 | source = "registry+https://github.com/rust-lang/crates.io-index" | 80 | source = "registry+https://github.com/rust-lang/crates.io-index" |
81 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" | 81 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" |
82 | 82 | ||
83 | [[package]] | 83 | [[package]] |
84 | name = "backtrace" | 84 | name = "backtrace" |
@@ -140,9 +140,9 @@ dependencies = [ | |||
140 | 140 | ||
141 | [[package]] | 141 | [[package]] |
142 | name = "cc" | 142 | name = "cc" |
143 | version = "1.0.58" | 143 | version = "1.0.59" |
144 | source = "registry+https://github.com/rust-lang/crates.io-index" | 144 | source = "registry+https://github.com/rust-lang/crates.io-index" |
145 | checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" | 145 | checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" |
146 | 146 | ||
147 | [[package]] | 147 | [[package]] |
148 | name = "cfg" | 148 | name = "cfg" |
@@ -345,12 +345,13 @@ dependencies = [ | |||
345 | ] | 345 | ] |
346 | 346 | ||
347 | [[package]] | 347 | [[package]] |
348 | name = "expect" | 348 | name = "expect-test" |
349 | version = "0.0.0" | 349 | version = "0.1.0" |
350 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
351 | checksum = "a3e383741ea1982866572109d1a8c807bd36aad91fca701489fdca56ef92b3b8" | ||
350 | dependencies = [ | 352 | dependencies = [ |
351 | "difference", | 353 | "difference", |
352 | "once_cell", | 354 | "once_cell", |
353 | "stdx", | ||
354 | ] | 355 | ] |
355 | 356 | ||
356 | [[package]] | 357 | [[package]] |
@@ -373,9 +374,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" | |||
373 | 374 | ||
374 | [[package]] | 375 | [[package]] |
375 | name = "flate2" | 376 | name = "flate2" |
376 | version = "1.0.16" | 377 | version = "1.0.17" |
377 | source = "registry+https://github.com/rust-lang/crates.io-index" | 378 | source = "registry+https://github.com/rust-lang/crates.io-index" |
378 | checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" | 379 | checksum = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" |
379 | dependencies = [ | 380 | dependencies = [ |
380 | "cfg-if", | 381 | "cfg-if", |
381 | "crc32fast", | 382 | "crc32fast", |
@@ -508,7 +509,7 @@ dependencies = [ | |||
508 | "cfg", | 509 | "cfg", |
509 | "drop_bomb", | 510 | "drop_bomb", |
510 | "either", | 511 | "either", |
511 | "expect", | 512 | "expect-test", |
512 | "fst", | 513 | "fst", |
513 | "hir_expand", | 514 | "hir_expand", |
514 | "indexmap", | 515 | "indexmap", |
@@ -553,7 +554,7 @@ dependencies = [ | |||
553 | "chalk-recursive", | 554 | "chalk-recursive", |
554 | "chalk-solve", | 555 | "chalk-solve", |
555 | "ena", | 556 | "ena", |
556 | "expect", | 557 | "expect-test", |
557 | "hir_def", | 558 | "hir_def", |
558 | "hir_expand", | 559 | "hir_expand", |
559 | "itertools", | 560 | "itertools", |
@@ -587,7 +588,7 @@ dependencies = [ | |||
587 | "base_db", | 588 | "base_db", |
588 | "cfg", | 589 | "cfg", |
589 | "either", | 590 | "either", |
590 | "expect", | 591 | "expect-test", |
591 | "hir", | 592 | "hir", |
592 | "ide_db", | 593 | "ide_db", |
593 | "indexmap", | 594 | "indexmap", |
@@ -723,9 +724,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" | |||
723 | 724 | ||
724 | [[package]] | 725 | [[package]] |
725 | name = "libc" | 726 | name = "libc" |
726 | version = "0.2.74" | 727 | version = "0.2.76" |
727 | source = "registry+https://github.com/rust-lang/crates.io-index" | 728 | source = "registry+https://github.com/rust-lang/crates.io-index" |
728 | checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" | 729 | checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" |
729 | 730 | ||
730 | [[package]] | 731 | [[package]] |
731 | name = "libloading" | 732 | name = "libloading" |
@@ -738,9 +739,9 @@ dependencies = [ | |||
738 | 739 | ||
739 | [[package]] | 740 | [[package]] |
740 | name = "libmimalloc-sys" | 741 | name = "libmimalloc-sys" |
741 | version = "0.1.15" | 742 | version = "0.1.16" |
742 | source = "registry+https://github.com/rust-lang/crates.io-index" | 743 | source = "registry+https://github.com/rust-lang/crates.io-index" |
743 | checksum = "a27252ec1d0c4e0dd6142cbc572da50b363ab56fc334f7aa8fadf295b2e24e74" | 744 | checksum = "677c4be79b14bd72496b87789b702ba02cd1a9f16a59369fe847082fd03efd88" |
744 | dependencies = [ | 745 | dependencies = [ |
745 | "cmake", | 746 | "cmake", |
746 | ] | 747 | ] |
@@ -844,9 +845,9 @@ dependencies = [ | |||
844 | 845 | ||
845 | [[package]] | 846 | [[package]] |
846 | name = "mimalloc" | 847 | name = "mimalloc" |
847 | version = "0.1.19" | 848 | version = "0.1.20" |
848 | source = "registry+https://github.com/rust-lang/crates.io-index" | 849 | source = "registry+https://github.com/rust-lang/crates.io-index" |
849 | checksum = "6c52de2069999f01bd26436564dbe7de3a87898feeb7a0d0ff9eb20a05bb7ca0" | 850 | checksum = "00759bcf69082fa629ae8823fcc72f7454a90c6476110297a1ae5fb3a559e474" |
850 | dependencies = [ | 851 | dependencies = [ |
851 | "libmimalloc-sys", | 852 | "libmimalloc-sys", |
852 | ] | 853 | ] |
@@ -1225,7 +1226,7 @@ dependencies = [ | |||
1225 | "cfg", | 1226 | "cfg", |
1226 | "crossbeam-channel", | 1227 | "crossbeam-channel", |
1227 | "env_logger", | 1228 | "env_logger", |
1228 | "expect", | 1229 | "expect-test", |
1229 | "flycheck", | 1230 | "flycheck", |
1230 | "hir", | 1231 | "hir", |
1231 | "hir_def", | 1232 | "hir_def", |
@@ -1452,7 +1453,7 @@ name = "ssr" | |||
1452 | version = "0.0.0" | 1453 | version = "0.0.0" |
1453 | dependencies = [ | 1454 | dependencies = [ |
1454 | "base_db", | 1455 | "base_db", |
1455 | "expect", | 1456 | "expect-test", |
1456 | "hir", | 1457 | "hir", |
1457 | "ide_db", | 1458 | "ide_db", |
1458 | "itertools", | 1459 | "itertools", |
@@ -1494,7 +1495,7 @@ name = "syntax" | |||
1494 | version = "0.0.0" | 1495 | version = "0.0.0" |
1495 | dependencies = [ | 1496 | dependencies = [ |
1496 | "arrayvec", | 1497 | "arrayvec", |
1497 | "expect", | 1498 | "expect-test", |
1498 | "itertools", | 1499 | "itertools", |
1499 | "once_cell", | 1500 | "once_cell", |
1500 | "parser", | 1501 | "parser", |
@@ -1687,9 +1688,9 @@ dependencies = [ | |||
1687 | 1688 | ||
1688 | [[package]] | 1689 | [[package]] |
1689 | name = "ungrammar" | 1690 | name = "ungrammar" |
1690 | version = "1.1.1" | 1691 | version = "1.1.2" |
1691 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1692 | checksum = "c4e20e58a08ee1bcf8a4695cf74550cf054d6c489105f594beacb2c684210aad" | 1693 | checksum = "bab6142ac77be714b1ea78faca6efaed5478c50724786b0fe80d8528d10692b3" |
1693 | 1694 | ||
1694 | [[package]] | 1695 | [[package]] |
1695 | name = "unicode-bidi" | 1696 | name = "unicode-bidi" |
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index b9ec3f10b..c4770f336 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -239,7 +239,7 @@ impl ImportCandidate { | |||
239 | return None; | 239 | return None; |
240 | } | 240 | } |
241 | Some(Self::TraitMethod( | 241 | Some(Self::TraitMethod( |
242 | sema.type_of_expr(&method_call.expr()?)?, | 242 | sema.type_of_expr(&method_call.receiver()?)?, |
243 | method_call.name_ref()?.syntax().to_string(), | 243 | method_call.name_ref()?.syntax().to_string(), |
244 | )) | 244 | )) |
245 | } | 245 | } |
diff --git a/crates/assists/src/handlers/merge_imports.rs b/crates/assists/src/handlers/merge_imports.rs index 47d465404..35b884206 100644 --- a/crates/assists/src/handlers/merge_imports.rs +++ b/crates/assists/src/handlers/merge_imports.rs | |||
@@ -8,6 +8,7 @@ use syntax::{ | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | assist_context::{AssistContext, Assists}, | 10 | assist_context::{AssistContext, Assists}, |
11 | utils::next_prev, | ||
11 | AssistId, AssistKind, | 12 | AssistId, AssistKind, |
12 | }; | 13 | }; |
13 | 14 | ||
@@ -66,10 +67,6 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() | |||
66 | ) | 67 | ) |
67 | } | 68 | } |
68 | 69 | ||
69 | fn next_prev() -> impl Iterator<Item = Direction> { | ||
70 | [Direction::Next, Direction::Prev].iter().copied() | ||
71 | } | ||
72 | |||
73 | fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTree> { | 70 | fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTree> { |
74 | let lhs_path = old.path()?; | 71 | let lhs_path = old.path()?; |
75 | let rhs_path = new.path()?; | 72 | let rhs_path = new.path()?; |
diff --git a/crates/assists/src/handlers/remove_dbg.rs b/crates/assists/src/handlers/remove_dbg.rs index f3dcca534..4e252edf0 100644 --- a/crates/assists/src/handlers/remove_dbg.rs +++ b/crates/assists/src/handlers/remove_dbg.rs | |||
@@ -82,9 +82,10 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b | |||
82 | 82 | ||
83 | #[cfg(test)] | 83 | #[cfg(test)] |
84 | mod tests { | 84 | mod tests { |
85 | use super::*; | ||
86 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | 85 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; |
87 | 86 | ||
87 | use super::*; | ||
88 | |||
88 | #[test] | 89 | #[test] |
89 | fn test_remove_dbg() { | 90 | fn test_remove_dbg() { |
90 | check_assist(remove_dbg, "<|>dbg!(1 + 1)", "1 + 1"); | 91 | check_assist(remove_dbg, "<|>dbg!(1 + 1)", "1 + 1"); |
diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs new file mode 100644 index 000000000..5fccca54b --- /dev/null +++ b/crates/assists/src/handlers/remove_unused_param.rs | |||
@@ -0,0 +1,131 @@ | |||
1 | use ide_db::{defs::Definition, search::Reference}; | ||
2 | use syntax::{ | ||
3 | algo::find_node_at_range, | ||
4 | ast::{self, ArgListOwner}, | ||
5 | AstNode, SyntaxNode, TextRange, T, | ||
6 | }; | ||
7 | use test_utils::mark; | ||
8 | |||
9 | use crate::{ | ||
10 | assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists, | ||
11 | }; | ||
12 | |||
13 | // Assist: remove_unused_param | ||
14 | // | ||
15 | // Removes unused function parameter. | ||
16 | // | ||
17 | // ``` | ||
18 | // fn frobnicate(x: i32<|>) {} | ||
19 | // | ||
20 | // fn main() { | ||
21 | // frobnicate(92); | ||
22 | // } | ||
23 | // ``` | ||
24 | // -> | ||
25 | // ``` | ||
26 | // fn frobnicate() {} | ||
27 | // | ||
28 | // fn main() { | ||
29 | // frobnicate(); | ||
30 | // } | ||
31 | // ``` | ||
32 | pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
33 | let param: ast::Param = ctx.find_node_at_offset()?; | ||
34 | let ident_pat = match param.pat()? { | ||
35 | ast::Pat::IdentPat(it) => it, | ||
36 | _ => return None, | ||
37 | }; | ||
38 | let func = param.syntax().ancestors().find_map(ast::Fn::cast)?; | ||
39 | let param_position = func.param_list()?.params().position(|it| it == param)?; | ||
40 | |||
41 | let fn_def = { | ||
42 | let func = ctx.sema.to_def(&func)?; | ||
43 | Definition::ModuleDef(func.into()) | ||
44 | }; | ||
45 | |||
46 | let param_def = { | ||
47 | let local = ctx.sema.to_def(&ident_pat)?; | ||
48 | Definition::Local(local) | ||
49 | }; | ||
50 | if param_def.usages(&ctx.sema).at_least_one() { | ||
51 | mark::hit!(keep_used); | ||
52 | return None; | ||
53 | } | ||
54 | acc.add( | ||
55 | AssistId("remove_unused_param", AssistKind::Refactor), | ||
56 | "Remove unused parameter", | ||
57 | param.syntax().text_range(), | ||
58 | |builder| { | ||
59 | builder.delete(range_with_coma(param.syntax())); | ||
60 | for usage in fn_def.usages(&ctx.sema).all() { | ||
61 | process_usage(ctx, builder, usage, param_position); | ||
62 | } | ||
63 | }, | ||
64 | ) | ||
65 | } | ||
66 | |||
67 | fn process_usage( | ||
68 | ctx: &AssistContext, | ||
69 | builder: &mut AssistBuilder, | ||
70 | usage: Reference, | ||
71 | arg_to_remove: usize, | ||
72 | ) -> Option<()> { | ||
73 | let source_file = ctx.sema.parse(usage.file_range.file_id); | ||
74 | let call_expr: ast::CallExpr = | ||
75 | find_node_at_range(source_file.syntax(), usage.file_range.range)?; | ||
76 | if call_expr.expr()?.syntax().text_range() != usage.file_range.range { | ||
77 | return None; | ||
78 | } | ||
79 | let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?; | ||
80 | |||
81 | builder.edit_file(usage.file_range.file_id); | ||
82 | builder.delete(range_with_coma(arg.syntax())); | ||
83 | |||
84 | Some(()) | ||
85 | } | ||
86 | |||
87 | fn range_with_coma(node: &SyntaxNode) -> TextRange { | ||
88 | let up_to = next_prev().find_map(|dir| { | ||
89 | node.siblings_with_tokens(dir) | ||
90 | .filter_map(|it| it.into_token()) | ||
91 | .find(|it| it.kind() == T![,]) | ||
92 | }); | ||
93 | let up_to = up_to.map_or(node.text_range(), |it| it.text_range()); | ||
94 | node.text_range().cover(up_to) | ||
95 | } | ||
96 | |||
97 | #[cfg(test)] | ||
98 | mod tests { | ||
99 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
100 | |||
101 | use super::*; | ||
102 | |||
103 | #[test] | ||
104 | fn remove_unused() { | ||
105 | check_assist( | ||
106 | remove_unused_param, | ||
107 | r#" | ||
108 | fn a() { foo(9, 2) } | ||
109 | fn foo(x: i32, <|>y: i32) { x; } | ||
110 | fn b() { foo(9, 2,) } | ||
111 | "#, | ||
112 | r#" | ||
113 | fn a() { foo(9) } | ||
114 | fn foo(x: i32) { x; } | ||
115 | fn b() { foo(9, ) } | ||
116 | "#, | ||
117 | ); | ||
118 | } | ||
119 | |||
120 | #[test] | ||
121 | fn keep_used() { | ||
122 | mark::check!(keep_used); | ||
123 | check_assist_not_applicable( | ||
124 | remove_unused_param, | ||
125 | r#" | ||
126 | fn foo(x: i32, <|>y: i32) { y; } | ||
127 | fn main() { foo(9, 2) } | ||
128 | "#, | ||
129 | ); | ||
130 | } | ||
131 | } | ||
diff --git a/crates/assists/src/handlers/replace_unwrap_with_match.rs b/crates/assists/src/handlers/replace_unwrap_with_match.rs index 9705f11b7..4043c219c 100644 --- a/crates/assists/src/handlers/replace_unwrap_with_match.rs +++ b/crates/assists/src/handlers/replace_unwrap_with_match.rs | |||
@@ -42,7 +42,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) | |||
42 | if name.text() != "unwrap" { | 42 | if name.text() != "unwrap" { |
43 | return None; | 43 | return None; |
44 | } | 44 | } |
45 | let caller = method_call.expr()?; | 45 | let caller = method_call.receiver()?; |
46 | let ty = ctx.sema.type_of_expr(&caller)?; | 46 | let ty = ctx.sema.type_of_expr(&caller)?; |
47 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case(); | 47 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case(); |
48 | let target = method_call.syntax().text_range(); | 48 | let target = method_call.syntax().text_range(); |
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 14834480a..2e0d191a6 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs | |||
@@ -152,6 +152,7 @@ mod handlers { | |||
152 | mod raw_string; | 152 | mod raw_string; |
153 | mod remove_dbg; | 153 | mod remove_dbg; |
154 | mod remove_mut; | 154 | mod remove_mut; |
155 | mod remove_unused_param; | ||
155 | mod reorder_fields; | 156 | mod reorder_fields; |
156 | mod replace_if_let_with_match; | 157 | mod replace_if_let_with_match; |
157 | mod replace_let_with_if_let; | 158 | mod replace_let_with_if_let; |
@@ -198,6 +199,7 @@ mod handlers { | |||
198 | raw_string::remove_hash, | 199 | raw_string::remove_hash, |
199 | remove_dbg::remove_dbg, | 200 | remove_dbg::remove_dbg, |
200 | remove_mut::remove_mut, | 201 | remove_mut::remove_mut, |
202 | remove_unused_param::remove_unused_param, | ||
201 | reorder_fields::reorder_fields, | 203 | reorder_fields::reorder_fields, |
202 | replace_if_let_with_match::replace_if_let_with_match, | 204 | replace_if_let_with_match::replace_if_let_with_match, |
203 | replace_let_with_if_let::replace_let_with_if_let, | 205 | replace_let_with_if_let::replace_let_with_if_let, |
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index 173567003..04c8fd1f9 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs | |||
@@ -751,6 +751,27 @@ impl Walrus { | |||
751 | } | 751 | } |
752 | 752 | ||
753 | #[test] | 753 | #[test] |
754 | fn doctest_remove_unused_param() { | ||
755 | check_doc_test( | ||
756 | "remove_unused_param", | ||
757 | r#####" | ||
758 | fn frobnicate(x: i32<|>) {} | ||
759 | |||
760 | fn main() { | ||
761 | frobnicate(92); | ||
762 | } | ||
763 | "#####, | ||
764 | r#####" | ||
765 | fn frobnicate() {} | ||
766 | |||
767 | fn main() { | ||
768 | frobnicate(); | ||
769 | } | ||
770 | "#####, | ||
771 | ) | ||
772 | } | ||
773 | |||
774 | #[test] | ||
754 | fn doctest_reorder_fields() { | 775 | fn doctest_reorder_fields() { |
755 | check_doc_test( | 776 | check_doc_test( |
756 | "reorder_fields", | 777 | "reorder_fields", |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 84ccacafe..d071d6502 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -9,7 +9,7 @@ use itertools::Itertools; | |||
9 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
10 | use syntax::{ | 10 | use syntax::{ |
11 | ast::{self, make, NameOwner}, | 11 | ast::{self, make, NameOwner}, |
12 | AstNode, | 12 | AstNode, Direction, |
13 | SyntaxKind::*, | 13 | SyntaxKind::*, |
14 | SyntaxNode, TextSize, T, | 14 | SyntaxNode, TextSize, T, |
15 | }; | 15 | }; |
@@ -311,3 +311,7 @@ pub use prelude::*; | |||
311 | Some(def) | 311 | Some(def) |
312 | } | 312 | } |
313 | } | 313 | } |
314 | |||
315 | pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { | ||
316 | [Direction::Next, Direction::Prev].iter().copied() | ||
317 | } | ||
diff --git a/crates/expect/Cargo.toml b/crates/expect/Cargo.toml deleted file mode 100644 index b54d3a60e..000000000 --- a/crates/expect/Cargo.toml +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | [package] | ||
2 | name = "expect" | ||
3 | version = "0.0.0" | ||
4 | license = "MIT OR Apache-2.0" | ||
5 | authors = ["rust-analyzer developers"] | ||
6 | edition = "2018" | ||
7 | |||
8 | [lib] | ||
9 | doctest = false | ||
10 | |||
11 | [dependencies] | ||
12 | once_cell = "1" | ||
13 | difference = "2" | ||
14 | |||
15 | stdx = { path = "../stdx" } | ||
diff --git a/crates/expect/src/lib.rs b/crates/expect/src/lib.rs deleted file mode 100644 index bd83895f7..000000000 --- a/crates/expect/src/lib.rs +++ /dev/null | |||
@@ -1,356 +0,0 @@ | |||
1 | //! Snapshot testing library, see | ||
2 | //! https://github.com/rust-analyzer/rust-analyzer/pull/5101 | ||
3 | use std::{ | ||
4 | collections::HashMap, | ||
5 | env, fmt, fs, mem, | ||
6 | ops::Range, | ||
7 | panic, | ||
8 | path::{Path, PathBuf}, | ||
9 | sync::Mutex, | ||
10 | }; | ||
11 | |||
12 | use difference::Changeset; | ||
13 | use once_cell::sync::Lazy; | ||
14 | use stdx::{lines_with_ends, trim_indent}; | ||
15 | |||
16 | const HELP: &str = " | ||
17 | You can update all `expect![[]]` tests by running: | ||
18 | |||
19 | env UPDATE_EXPECT=1 cargo test | ||
20 | |||
21 | To update a single test, place the cursor on `expect` token and use `run` feature of rust-analyzer. | ||
22 | "; | ||
23 | |||
24 | fn update_expect() -> bool { | ||
25 | env::var("UPDATE_EXPECT").is_ok() | ||
26 | } | ||
27 | |||
28 | /// expect![[r#"inline snapshot"#]] | ||
29 | #[macro_export] | ||
30 | macro_rules! expect { | ||
31 | [[$data:literal]] => {$crate::Expect { | ||
32 | position: $crate::Position { | ||
33 | file: file!(), | ||
34 | line: line!(), | ||
35 | column: column!(), | ||
36 | }, | ||
37 | data: $data, | ||
38 | }}; | ||
39 | [[]] => { $crate::expect![[""]] }; | ||
40 | } | ||
41 | |||
42 | /// expect_file!["/crates/foo/test_data/bar.html"] | ||
43 | #[macro_export] | ||
44 | macro_rules! expect_file { | ||
45 | [$path:expr] => {$crate::ExpectFile { | ||
46 | path: std::path::PathBuf::from($path) | ||
47 | }}; | ||
48 | } | ||
49 | |||
50 | #[derive(Debug)] | ||
51 | pub struct Expect { | ||
52 | pub position: Position, | ||
53 | pub data: &'static str, | ||
54 | } | ||
55 | |||
56 | #[derive(Debug)] | ||
57 | pub struct ExpectFile { | ||
58 | pub path: PathBuf, | ||
59 | } | ||
60 | |||
61 | #[derive(Debug)] | ||
62 | pub struct Position { | ||
63 | pub file: &'static str, | ||
64 | pub line: u32, | ||
65 | pub column: u32, | ||
66 | } | ||
67 | |||
68 | impl fmt::Display for Position { | ||
69 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
70 | write!(f, "{}:{}:{}", self.file, self.line, self.column) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl Expect { | ||
75 | pub fn assert_eq(&self, actual: &str) { | ||
76 | let trimmed = self.trimmed(); | ||
77 | if trimmed == actual { | ||
78 | return; | ||
79 | } | ||
80 | Runtime::fail_expect(self, &trimmed, actual); | ||
81 | } | ||
82 | pub fn assert_debug_eq(&self, actual: &impl fmt::Debug) { | ||
83 | let actual = format!("{:#?}\n", actual); | ||
84 | self.assert_eq(&actual) | ||
85 | } | ||
86 | |||
87 | fn trimmed(&self) -> String { | ||
88 | if !self.data.contains('\n') { | ||
89 | return self.data.to_string(); | ||
90 | } | ||
91 | trim_indent(self.data) | ||
92 | } | ||
93 | |||
94 | fn locate(&self, file: &str) -> Location { | ||
95 | let mut target_line = None; | ||
96 | let mut line_start = 0; | ||
97 | for (i, line) in lines_with_ends(file).enumerate() { | ||
98 | if i == self.position.line as usize - 1 { | ||
99 | let pat = "expect![["; | ||
100 | let offset = line.find(pat).unwrap(); | ||
101 | let literal_start = line_start + offset + pat.len(); | ||
102 | let indent = line.chars().take_while(|&it| it == ' ').count(); | ||
103 | target_line = Some((literal_start, indent)); | ||
104 | break; | ||
105 | } | ||
106 | line_start += line.len(); | ||
107 | } | ||
108 | let (literal_start, line_indent) = target_line.unwrap(); | ||
109 | let literal_length = | ||
110 | file[literal_start..].find("]]").expect("Couldn't find matching `]]` for `expect![[`."); | ||
111 | let literal_range = literal_start..literal_start + literal_length; | ||
112 | Location { line_indent, literal_range } | ||
113 | } | ||
114 | } | ||
115 | |||
116 | impl ExpectFile { | ||
117 | pub fn assert_eq(&self, actual: &str) { | ||
118 | let expected = self.read(); | ||
119 | if actual == expected { | ||
120 | return; | ||
121 | } | ||
122 | Runtime::fail_file(self, &expected, actual); | ||
123 | } | ||
124 | pub fn assert_debug_eq(&self, actual: &impl fmt::Debug) { | ||
125 | let actual = format!("{:#?}\n", actual); | ||
126 | self.assert_eq(&actual) | ||
127 | } | ||
128 | fn read(&self) -> String { | ||
129 | fs::read_to_string(self.abs_path()).unwrap_or_default().replace("\r\n", "\n") | ||
130 | } | ||
131 | fn write(&self, contents: &str) { | ||
132 | fs::write(self.abs_path(), contents).unwrap() | ||
133 | } | ||
134 | fn abs_path(&self) -> PathBuf { | ||
135 | WORKSPACE_ROOT.join(&self.path) | ||
136 | } | ||
137 | } | ||
138 | |||
139 | #[derive(Default)] | ||
140 | struct Runtime { | ||
141 | help_printed: bool, | ||
142 | per_file: HashMap<&'static str, FileRuntime>, | ||
143 | } | ||
144 | static RT: Lazy<Mutex<Runtime>> = Lazy::new(Default::default); | ||
145 | |||
146 | impl Runtime { | ||
147 | fn fail_expect(expect: &Expect, expected: &str, actual: &str) { | ||
148 | let mut rt = RT.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); | ||
149 | if update_expect() { | ||
150 | println!("\x1b[1m\x1b[92mupdating\x1b[0m: {}", expect.position); | ||
151 | rt.per_file | ||
152 | .entry(expect.position.file) | ||
153 | .or_insert_with(|| FileRuntime::new(expect)) | ||
154 | .update(expect, actual); | ||
155 | return; | ||
156 | } | ||
157 | rt.panic(expect.position.to_string(), expected, actual); | ||
158 | } | ||
159 | |||
160 | fn fail_file(expect: &ExpectFile, expected: &str, actual: &str) { | ||
161 | let mut rt = RT.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); | ||
162 | if update_expect() { | ||
163 | println!("\x1b[1m\x1b[92mupdating\x1b[0m: {}", expect.path.display()); | ||
164 | expect.write(actual); | ||
165 | return; | ||
166 | } | ||
167 | rt.panic(expect.path.display().to_string(), expected, actual); | ||
168 | } | ||
169 | |||
170 | fn panic(&mut self, position: String, expected: &str, actual: &str) { | ||
171 | let print_help = !mem::replace(&mut self.help_printed, true); | ||
172 | let help = if print_help { HELP } else { "" }; | ||
173 | |||
174 | let diff = Changeset::new(actual, expected, "\n"); | ||
175 | |||
176 | println!( | ||
177 | "\n | ||
178 | \x1b[1m\x1b[91merror\x1b[97m: expect test failed\x1b[0m | ||
179 | \x1b[1m\x1b[34m-->\x1b[0m {} | ||
180 | {} | ||
181 | \x1b[1mExpect\x1b[0m: | ||
182 | ---- | ||
183 | {} | ||
184 | ---- | ||
185 | |||
186 | \x1b[1mActual\x1b[0m: | ||
187 | ---- | ||
188 | {} | ||
189 | ---- | ||
190 | |||
191 | \x1b[1mDiff\x1b[0m: | ||
192 | ---- | ||
193 | {} | ||
194 | ---- | ||
195 | ", | ||
196 | position, help, expected, actual, diff | ||
197 | ); | ||
198 | // Use resume_unwind instead of panic!() to prevent a backtrace, which is unnecessary noise. | ||
199 | panic::resume_unwind(Box::new(())); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | struct FileRuntime { | ||
204 | path: PathBuf, | ||
205 | original_text: String, | ||
206 | patchwork: Patchwork, | ||
207 | } | ||
208 | |||
209 | impl FileRuntime { | ||
210 | fn new(expect: &Expect) -> FileRuntime { | ||
211 | let path = WORKSPACE_ROOT.join(expect.position.file); | ||
212 | let original_text = fs::read_to_string(&path).unwrap(); | ||
213 | let patchwork = Patchwork::new(original_text.clone()); | ||
214 | FileRuntime { path, original_text, patchwork } | ||
215 | } | ||
216 | fn update(&mut self, expect: &Expect, actual: &str) { | ||
217 | let loc = expect.locate(&self.original_text); | ||
218 | let patch = format_patch(loc.line_indent.clone(), actual); | ||
219 | self.patchwork.patch(loc.literal_range, &patch); | ||
220 | fs::write(&self.path, &self.patchwork.text).unwrap() | ||
221 | } | ||
222 | } | ||
223 | |||
224 | #[derive(Debug)] | ||
225 | struct Location { | ||
226 | line_indent: usize, | ||
227 | literal_range: Range<usize>, | ||
228 | } | ||
229 | |||
230 | #[derive(Debug)] | ||
231 | struct Patchwork { | ||
232 | text: String, | ||
233 | indels: Vec<(Range<usize>, usize)>, | ||
234 | } | ||
235 | |||
236 | impl Patchwork { | ||
237 | fn new(text: String) -> Patchwork { | ||
238 | Patchwork { text, indels: Vec::new() } | ||
239 | } | ||
240 | fn patch(&mut self, mut range: Range<usize>, patch: &str) { | ||
241 | self.indels.push((range.clone(), patch.len())); | ||
242 | self.indels.sort_by_key(|(delete, _insert)| delete.start); | ||
243 | |||
244 | let (delete, insert) = self | ||
245 | .indels | ||
246 | .iter() | ||
247 | .take_while(|(delete, _)| delete.start < range.start) | ||
248 | .map(|(delete, insert)| (delete.end - delete.start, insert)) | ||
249 | .fold((0usize, 0usize), |(x1, y1), (x2, y2)| (x1 + x2, y1 + y2)); | ||
250 | |||
251 | for pos in &mut [&mut range.start, &mut range.end] { | ||
252 | **pos -= delete; | ||
253 | **pos += insert; | ||
254 | } | ||
255 | |||
256 | self.text.replace_range(range, &patch); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | fn format_patch(line_indent: usize, patch: &str) -> String { | ||
261 | let mut max_hashes = 0; | ||
262 | let mut cur_hashes = 0; | ||
263 | for byte in patch.bytes() { | ||
264 | if byte != b'#' { | ||
265 | cur_hashes = 0; | ||
266 | continue; | ||
267 | } | ||
268 | cur_hashes += 1; | ||
269 | max_hashes = max_hashes.max(cur_hashes); | ||
270 | } | ||
271 | let hashes = &"#".repeat(max_hashes + 1); | ||
272 | let indent = &" ".repeat(line_indent); | ||
273 | let is_multiline = patch.contains('\n'); | ||
274 | |||
275 | let mut buf = String::new(); | ||
276 | buf.push('r'); | ||
277 | buf.push_str(hashes); | ||
278 | buf.push('"'); | ||
279 | if is_multiline { | ||
280 | buf.push('\n'); | ||
281 | } | ||
282 | let mut final_newline = false; | ||
283 | for line in lines_with_ends(patch) { | ||
284 | if is_multiline && !line.trim().is_empty() { | ||
285 | buf.push_str(indent); | ||
286 | buf.push_str(" "); | ||
287 | } | ||
288 | buf.push_str(line); | ||
289 | final_newline = line.ends_with('\n'); | ||
290 | } | ||
291 | if final_newline { | ||
292 | buf.push_str(indent); | ||
293 | } | ||
294 | buf.push('"'); | ||
295 | buf.push_str(hashes); | ||
296 | buf | ||
297 | } | ||
298 | |||
299 | static WORKSPACE_ROOT: Lazy<PathBuf> = Lazy::new(|| { | ||
300 | let my_manifest = | ||
301 | env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()); | ||
302 | // Heuristic, see https://github.com/rust-lang/cargo/issues/3946 | ||
303 | Path::new(&my_manifest) | ||
304 | .ancestors() | ||
305 | .filter(|it| it.join("Cargo.toml").exists()) | ||
306 | .last() | ||
307 | .unwrap() | ||
308 | .to_path_buf() | ||
309 | }); | ||
310 | |||
311 | #[cfg(test)] | ||
312 | mod tests { | ||
313 | use super::*; | ||
314 | |||
315 | #[test] | ||
316 | fn test_format_patch() { | ||
317 | let patch = format_patch(0, "hello\nworld\n"); | ||
318 | expect![[r##" | ||
319 | r#" | ||
320 | hello | ||
321 | world | ||
322 | "#"##]] | ||
323 | .assert_eq(&patch); | ||
324 | |||
325 | let patch = format_patch(4, "single line"); | ||
326 | expect![[r##"r#"single line"#"##]].assert_eq(&patch); | ||
327 | } | ||
328 | |||
329 | #[test] | ||
330 | fn test_patchwork() { | ||
331 | let mut patchwork = Patchwork::new("one two three".to_string()); | ||
332 | patchwork.patch(4..7, "zwei"); | ||
333 | patchwork.patch(0..3, "один"); | ||
334 | patchwork.patch(8..13, "3"); | ||
335 | expect![[r#" | ||
336 | Patchwork { | ||
337 | text: "один zwei 3", | ||
338 | indels: [ | ||
339 | ( | ||
340 | 0..3, | ||
341 | 8, | ||
342 | ), | ||
343 | ( | ||
344 | 4..7, | ||
345 | 4, | ||
346 | ), | ||
347 | ( | ||
348 | 8..13, | ||
349 | 1, | ||
350 | ), | ||
351 | ], | ||
352 | } | ||
353 | "#]] | ||
354 | .assert_debug_eq(&patchwork); | ||
355 | } | ||
356 | } | ||
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 8c5f2ff98..1594d4f0f 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -573,7 +573,7 @@ impl<'db> SemanticsImpl<'db> { | |||
573 | 573 | ||
574 | fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { | 574 | fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { |
575 | method_call_expr | 575 | method_call_expr |
576 | .expr() | 576 | .receiver() |
577 | .and_then(|expr| { | 577 | .and_then(|expr| { |
578 | let field_expr = match expr { | 578 | let field_expr = match expr { |
579 | ast::Expr::FieldExpr(field_expr) => field_expr, | 579 | ast::Expr::FieldExpr(field_expr) => field_expr, |
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 403bc2aff..57745322f 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -32,4 +32,4 @@ cfg = { path = "../cfg" } | |||
32 | tt = { path = "../tt" } | 32 | tt = { path = "../tt" } |
33 | 33 | ||
34 | [dev-dependencies] | 34 | [dev-dependencies] |
35 | expect = { path = "../expect" } | 35 | expect-test = "0.1" |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index a26251cde..30ac12a12 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -329,7 +329,7 @@ impl ExprCollector<'_> { | |||
329 | self.alloc_expr(Expr::Call { callee, args }, syntax_ptr) | 329 | self.alloc_expr(Expr::Call { callee, args }, syntax_ptr) |
330 | } | 330 | } |
331 | ast::Expr::MethodCallExpr(e) => { | 331 | ast::Expr::MethodCallExpr(e) => { |
332 | let receiver = self.collect_expr_opt(e.expr()); | 332 | let receiver = self.collect_expr_opt(e.receiver()); |
333 | let args = if let Some(arg_list) = e.arg_list() { | 333 | let args = if let Some(arg_list) = e.arg_list() { |
334 | arg_list.args().map(|e| self.collect_expr(e)).collect() | 334 | arg_list.args().map(|e| self.collect_expr(e)).collect() |
335 | } else { | 335 | } else { |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index d32a0bdaf..a442fb63a 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -328,7 +328,7 @@ pub fn search_dependencies<'a>( | |||
328 | #[cfg(test)] | 328 | #[cfg(test)] |
329 | mod tests { | 329 | mod tests { |
330 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; | 330 | use base_db::{fixture::WithFixture, SourceDatabase, Upcast}; |
331 | use expect::{expect, Expect}; | 331 | use expect_test::{expect, Expect}; |
332 | 332 | ||
333 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; | 333 | use crate::{test_db::TestDB, AssocContainerId, Lookup}; |
334 | 334 | ||
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index 9c5bf72bd..620e697d4 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use base_db::fixture::WithFixture; | 1 | use base_db::fixture::WithFixture; |
2 | use expect::{expect, Expect}; | 2 | use expect_test::{expect, Expect}; |
3 | use hir_expand::{db::AstDatabase, HirFileId, InFile}; | 3 | use hir_expand::{db::AstDatabase, HirFileId, InFile}; |
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index b105d56b2..8aaf7a158 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -7,7 +7,7 @@ mod primitives; | |||
7 | use std::sync::Arc; | 7 | use std::sync::Arc; |
8 | 8 | ||
9 | use base_db::{fixture::WithFixture, SourceDatabase}; | 9 | use base_db::{fixture::WithFixture, SourceDatabase}; |
10 | use expect::{expect, Expect}; | 10 | use expect_test::{expect, Expect}; |
11 | use test_utils::mark; | 11 | use test_utils::mark; |
12 | 12 | ||
13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index a319b0ce8..06da0d0ec 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -30,8 +30,7 @@ syntax = { path = "../syntax" } | |||
30 | test_utils = { path = "../test_utils" } | 30 | test_utils = { path = "../test_utils" } |
31 | 31 | ||
32 | [dev-dependencies] | 32 | [dev-dependencies] |
33 | expect-test = "0.1" | ||
33 | tracing = "0.1" | 34 | tracing = "0.1" |
34 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } | 35 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } |
35 | tracing-tree = { version = "0.1.4" } | 36 | tracing-tree = { version = "0.1.4" } |
36 | |||
37 | expect = { path = "../expect" } | ||
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 91c9d38c5..0445efc9e 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -11,7 +11,7 @@ mod display_source_code; | |||
11 | use std::{env, sync::Arc}; | 11 | use std::{env, sync::Arc}; |
12 | 12 | ||
13 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; | 13 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; |
14 | use expect::Expect; | 14 | use expect_test::Expect; |
15 | use hir_def::{ | 15 | use hir_def::{ |
16 | body::{BodySourceMap, SyntheticSyntax}, | 16 | body::{BodySourceMap, SyntheticSyntax}, |
17 | child_by_source::ChildBySource, | 17 | child_by_source::ChildBySource, |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index 17efd75cb..7bc6c79f3 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_infer, check_infer_with_mismatches}; | 4 | use super::{check_infer, check_infer_with_mismatches}; |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index d887c7a79..597a195d0 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::fs; | 1 | use std::fs; |
2 | 2 | ||
3 | use expect::expect; | 3 | use expect_test::expect; |
4 | use test_utils::project_dir; | 4 | use test_utils::project_dir; |
5 | 5 | ||
6 | use super::{check_infer, check_types}; | 6 | use super::{check_infer, check_types}; |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index fa68355aa..23b2601e6 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_types}; | 3 | use super::{check_infer, check_types}; |
4 | 4 | ||
diff --git a/crates/hir_ty/src/tests/never_type.rs b/crates/hir_ty/src/tests/never_type.rs index 49538b572..335c474df 100644 --- a/crates/hir_ty/src/tests/never_type.rs +++ b/crates/hir_ty/src/tests/never_type.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer_with_mismatches, check_types}; | 3 | use super::{check_infer_with_mismatches, check_types}; |
4 | 4 | ||
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 39fabf7eb..aeb191c79 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_infer, check_infer_with_mismatches}; | 4 | use super::{check_infer, check_infer_with_mismatches}; |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index b9ab0f357..94d86b0d1 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_infer, check_types}; | 4 | use super::{check_infer, check_types}; |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 59eb59d5f..48db23a34 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_types}; | 3 | use super::{check_infer, check_types}; |
4 | 4 | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 526e61caf..1f1056962 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use expect::expect; | 1 | use expect_test::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_infer, check_infer_with_mismatches, check_types}; | 4 | use super::{check_infer, check_infer_with_mismatches, check_types}; |
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index e4b970c73..700944430 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml | |||
@@ -32,4 +32,4 @@ ssr = { path = "../ssr" } | |||
32 | hir = { path = "../hir" } | 32 | hir = { path = "../hir" } |
33 | 33 | ||
34 | [dev-dependencies] | 34 | [dev-dependencies] |
35 | expect = { path = "../expect" } | 35 | expect-test = "0.1" |
diff --git a/crates/ide/src/call_info.rs b/crates/ide/src/call_info.rs index 86abd2d8c..7e83a2381 100644 --- a/crates/ide/src/call_info.rs +++ b/crates/ide/src/call_info.rs | |||
@@ -229,7 +229,7 @@ impl FnCallNode { | |||
229 | 229 | ||
230 | #[cfg(test)] | 230 | #[cfg(test)] |
231 | mod tests { | 231 | mod tests { |
232 | use expect::{expect, Expect}; | 232 | use expect_test::{expect, Expect}; |
233 | use test_utils::mark; | 233 | use test_utils::mark; |
234 | 234 | ||
235 | use crate::mock_analysis::analysis_and_position; | 235 | use crate::mock_analysis::analysis_and_position; |
diff --git a/crates/ide/src/completion/complete_attribute.rs b/crates/ide/src/completion/complete_attribute.rs index 042c3ecef..0abfaebcb 100644 --- a/crates/ide/src/completion/complete_attribute.rs +++ b/crates/ide/src/completion/complete_attribute.rs | |||
@@ -383,7 +383,7 @@ const DEFAULT_LINT_COMPLETIONS: &[LintCompletion] = &[ | |||
383 | 383 | ||
384 | #[cfg(test)] | 384 | #[cfg(test)] |
385 | mod tests { | 385 | mod tests { |
386 | use expect::{expect, Expect}; | 386 | use expect_test::{expect, Expect}; |
387 | 387 | ||
388 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 388 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
389 | 389 | ||
diff --git a/crates/ide/src/completion/complete_dot.rs b/crates/ide/src/completion/complete_dot.rs index 5488db43f..0b9f1798a 100644 --- a/crates/ide/src/completion/complete_dot.rs +++ b/crates/ide/src/completion/complete_dot.rs | |||
@@ -61,7 +61,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
61 | 61 | ||
62 | #[cfg(test)] | 62 | #[cfg(test)] |
63 | mod tests { | 63 | mod tests { |
64 | use expect::{expect, Expect}; | 64 | use expect_test::{expect, Expect}; |
65 | use test_utils::mark; | 65 | use test_utils::mark; |
66 | 66 | ||
67 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 67 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
diff --git a/crates/ide/src/completion/complete_fn_param.rs b/crates/ide/src/completion/complete_fn_param.rs index 7c63ce58f..9efe25461 100644 --- a/crates/ide/src/completion/complete_fn_param.rs +++ b/crates/ide/src/completion/complete_fn_param.rs | |||
@@ -66,7 +66,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
66 | 66 | ||
67 | #[cfg(test)] | 67 | #[cfg(test)] |
68 | mod tests { | 68 | mod tests { |
69 | use expect::{expect, Expect}; | 69 | use expect_test::{expect, Expect}; |
70 | 70 | ||
71 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 71 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
72 | 72 | ||
diff --git a/crates/ide/src/completion/complete_keyword.rs b/crates/ide/src/completion/complete_keyword.rs index 22ada3cf2..95e4ff1ac 100644 --- a/crates/ide/src/completion/complete_keyword.rs +++ b/crates/ide/src/completion/complete_keyword.rs | |||
@@ -174,7 +174,7 @@ fn complete_return( | |||
174 | 174 | ||
175 | #[cfg(test)] | 175 | #[cfg(test)] |
176 | mod tests { | 176 | mod tests { |
177 | use expect::{expect, Expect}; | 177 | use expect_test::{expect, Expect}; |
178 | 178 | ||
179 | use crate::completion::{ | 179 | use crate::completion::{ |
180 | test_utils::{check_edit, completion_list}, | 180 | test_utils::{check_edit, completion_list}, |
diff --git a/crates/ide/src/completion/complete_macro_in_item_position.rs b/crates/ide/src/completion/complete_macro_in_item_position.rs index 0447f0511..fc8625d8e 100644 --- a/crates/ide/src/completion/complete_macro_in_item_position.rs +++ b/crates/ide/src/completion/complete_macro_in_item_position.rs | |||
@@ -15,7 +15,7 @@ pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &Compl | |||
15 | 15 | ||
16 | #[cfg(test)] | 16 | #[cfg(test)] |
17 | mod tests { | 17 | mod tests { |
18 | use expect::{expect, Expect}; | 18 | use expect_test::{expect, Expect}; |
19 | 19 | ||
20 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 20 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
21 | 21 | ||
diff --git a/crates/ide/src/completion/complete_pattern.rs b/crates/ide/src/completion/complete_pattern.rs index aceb77cb5..5a13574d4 100644 --- a/crates/ide/src/completion/complete_pattern.rs +++ b/crates/ide/src/completion/complete_pattern.rs | |||
@@ -33,7 +33,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
33 | 33 | ||
34 | #[cfg(test)] | 34 | #[cfg(test)] |
35 | mod tests { | 35 | mod tests { |
36 | use expect::{expect, Expect}; | 36 | use expect_test::{expect, Expect}; |
37 | 37 | ||
38 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 38 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
39 | 39 | ||
diff --git a/crates/ide/src/completion/complete_postfix.rs b/crates/ide/src/completion/complete_postfix.rs index d50b13c52..84c4e129d 100644 --- a/crates/ide/src/completion/complete_postfix.rs +++ b/crates/ide/src/completion/complete_postfix.rs | |||
@@ -238,7 +238,7 @@ fn postfix_snippet( | |||
238 | 238 | ||
239 | #[cfg(test)] | 239 | #[cfg(test)] |
240 | mod tests { | 240 | mod tests { |
241 | use expect::{expect, Expect}; | 241 | use expect_test::{expect, Expect}; |
242 | 242 | ||
243 | use crate::completion::{ | 243 | use crate::completion::{ |
244 | test_utils::{check_edit, completion_list}, | 244 | test_utils::{check_edit, completion_list}, |
diff --git a/crates/ide/src/completion/complete_qualified_path.rs b/crates/ide/src/completion/complete_qualified_path.rs index 74794dc88..accb09f7e 100644 --- a/crates/ide/src/completion/complete_qualified_path.rs +++ b/crates/ide/src/completion/complete_qualified_path.rs | |||
@@ -146,7 +146,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
146 | 146 | ||
147 | #[cfg(test)] | 147 | #[cfg(test)] |
148 | mod tests { | 148 | mod tests { |
149 | use expect::{expect, Expect}; | 149 | use expect_test::{expect, Expect}; |
150 | use test_utils::mark; | 150 | use test_utils::mark; |
151 | 151 | ||
152 | use crate::completion::{ | 152 | use crate::completion::{ |
diff --git a/crates/ide/src/completion/complete_record.rs b/crates/ide/src/completion/complete_record.rs index 74b94594d..ceb8d16c1 100644 --- a/crates/ide/src/completion/complete_record.rs +++ b/crates/ide/src/completion/complete_record.rs | |||
@@ -18,7 +18,7 @@ pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> | |||
18 | 18 | ||
19 | #[cfg(test)] | 19 | #[cfg(test)] |
20 | mod tests { | 20 | mod tests { |
21 | use expect::{expect, Expect}; | 21 | use expect_test::{expect, Expect}; |
22 | 22 | ||
23 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 23 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
24 | 24 | ||
diff --git a/crates/ide/src/completion/complete_snippet.rs b/crates/ide/src/completion/complete_snippet.rs index 4368e4eec..c3b03b199 100644 --- a/crates/ide/src/completion/complete_snippet.rs +++ b/crates/ide/src/completion/complete_snippet.rs | |||
@@ -70,7 +70,7 @@ fn ${1:feature}() { | |||
70 | 70 | ||
71 | #[cfg(test)] | 71 | #[cfg(test)] |
72 | mod tests { | 72 | mod tests { |
73 | use expect::{expect, Expect}; | 73 | use expect_test::{expect, Expect}; |
74 | 74 | ||
75 | use crate::completion::{test_utils::completion_list, CompletionKind}; | 75 | use crate::completion::{test_utils::completion_list, CompletionKind}; |
76 | 76 | ||
diff --git a/crates/ide/src/completion/complete_trait_impl.rs b/crates/ide/src/completion/complete_trait_impl.rs index d0d3a9f34..1a2b1e8a5 100644 --- a/crates/ide/src/completion/complete_trait_impl.rs +++ b/crates/ide/src/completion/complete_trait_impl.rs | |||
@@ -225,7 +225,7 @@ fn make_const_compl_syntax(const_: &ast::Const) -> String { | |||
225 | 225 | ||
226 | #[cfg(test)] | 226 | #[cfg(test)] |
227 | mod tests { | 227 | mod tests { |
228 | use expect::{expect, Expect}; | 228 | use expect_test::{expect, Expect}; |
229 | 229 | ||
230 | use crate::completion::{ | 230 | use crate::completion::{ |
231 | test_utils::{check_edit, completion_list}, | 231 | test_utils::{check_edit, completion_list}, |
diff --git a/crates/ide/src/completion/complete_unqualified_path.rs b/crates/ide/src/completion/complete_unqualified_path.rs index 824227f31..1f1b682a7 100644 --- a/crates/ide/src/completion/complete_unqualified_path.rs +++ b/crates/ide/src/completion/complete_unqualified_path.rs | |||
@@ -64,7 +64,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T | |||
64 | 64 | ||
65 | #[cfg(test)] | 65 | #[cfg(test)] |
66 | mod tests { | 66 | mod tests { |
67 | use expect::{expect, Expect}; | 67 | use expect_test::{expect, Expect}; |
68 | use test_utils::mark; | 68 | use test_utils::mark; |
69 | 69 | ||
70 | use crate::completion::{ | 70 | use crate::completion::{ |
diff --git a/crates/ide/src/completion/completion_context.rs b/crates/ide/src/completion/completion_context.rs index 85456a66f..5adac7ebc 100644 --- a/crates/ide/src/completion/completion_context.rs +++ b/crates/ide/src/completion/completion_context.rs | |||
@@ -457,7 +457,7 @@ impl<'a> CompletionContext<'a> { | |||
457 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { | 457 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { |
458 | // As above | 458 | // As above |
459 | self.dot_receiver = method_call_expr | 459 | self.dot_receiver = method_call_expr |
460 | .expr() | 460 | .receiver() |
461 | .map(|e| e.syntax().text_range()) | 461 | .map(|e| e.syntax().text_range()) |
462 | .and_then(|r| find_node_with_range(original_file, r)); | 462 | .and_then(|r| find_node_with_range(original_file, r)); |
463 | self.is_call = true; | 463 | self.is_call = true; |
diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index a73f8ab0b..3371aed2d 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs | |||
@@ -464,7 +464,7 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s | |||
464 | mod tests { | 464 | mod tests { |
465 | use std::cmp::Reverse; | 465 | use std::cmp::Reverse; |
466 | 466 | ||
467 | use expect::{expect, Expect}; | 467 | use expect_test::{expect, Expect}; |
468 | use test_utils::mark; | 468 | use test_utils::mark; |
469 | 469 | ||
470 | use crate::{ | 470 | use crate::{ |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 92b5adaa2..b2b972b02 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -214,7 +214,7 @@ fn check_struct_shorthand_initialization( | |||
214 | 214 | ||
215 | #[cfg(test)] | 215 | #[cfg(test)] |
216 | mod tests { | 216 | mod tests { |
217 | use expect::{expect, Expect}; | 217 | use expect_test::{expect, Expect}; |
218 | use stdx::trim_indent; | 218 | use stdx::trim_indent; |
219 | use test_utils::assert_eq_text; | 219 | use test_utils::assert_eq_text; |
220 | 220 | ||
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index e77106177..1ee80c2dd 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -421,7 +421,7 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> | |||
421 | 421 | ||
422 | #[cfg(test)] | 422 | #[cfg(test)] |
423 | mod tests { | 423 | mod tests { |
424 | use expect::expect; | 424 | use expect_test::expect; |
425 | 425 | ||
426 | use crate::{mock_analysis::single_file, Query}; | 426 | use crate::{mock_analysis::single_file, Query}; |
427 | 427 | ||
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 31455709d..8a285bcf7 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs | |||
@@ -120,7 +120,7 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
120 | 120 | ||
121 | #[cfg(test)] | 121 | #[cfg(test)] |
122 | mod tests { | 122 | mod tests { |
123 | use expect::{expect, Expect}; | 123 | use expect_test::{expect, Expect}; |
124 | 124 | ||
125 | use crate::mock_analysis::analysis_and_position; | 125 | use crate::mock_analysis::analysis_and_position; |
126 | 126 | ||
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs index c90247ba6..6168fb837 100644 --- a/crates/ide/src/file_structure.rs +++ b/crates/ide/src/file_structure.rs | |||
@@ -164,7 +164,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | |||
164 | 164 | ||
165 | #[cfg(test)] | 165 | #[cfg(test)] |
166 | mod tests { | 166 | mod tests { |
167 | use expect::{expect, Expect}; | 167 | use expect_test::{expect, Expect}; |
168 | 168 | ||
169 | use super::*; | 169 | use super::*; |
170 | 170 | ||
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 300c00edc..c75b2a510 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -353,7 +353,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
353 | #[cfg(test)] | 353 | #[cfg(test)] |
354 | mod tests { | 354 | mod tests { |
355 | use base_db::FileLoader; | 355 | use base_db::FileLoader; |
356 | use expect::{expect, Expect}; | 356 | use expect_test::{expect, Expect}; |
357 | 357 | ||
358 | use crate::mock_analysis::analysis_and_position; | 358 | use crate::mock_analysis::analysis_and_position; |
359 | 359 | ||
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 596bc872d..583f39d85 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -336,7 +336,7 @@ fn get_callable(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<Call | |||
336 | 336 | ||
337 | #[cfg(test)] | 337 | #[cfg(test)] |
338 | mod tests { | 338 | mod tests { |
339 | use expect::{expect, Expect}; | 339 | use expect_test::{expect, Expect}; |
340 | use test_utils::extract_annotations; | 340 | use test_utils::extract_annotations; |
341 | 341 | ||
342 | use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; | 342 | use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index d73dc9cd0..301629763 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -270,7 +270,7 @@ fn rename_reference( | |||
270 | 270 | ||
271 | #[cfg(test)] | 271 | #[cfg(test)] |
272 | mod tests { | 272 | mod tests { |
273 | use expect::{expect, Expect}; | 273 | use expect_test::{expect, Expect}; |
274 | use stdx::trim_indent; | 274 | use stdx::trim_indent; |
275 | use test_utils::{assert_eq_text, mark}; | 275 | use test_utils::{assert_eq_text, mark}; |
276 | use text_edit::TextEdit; | 276 | use text_edit::TextEdit; |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index c3e07c8de..4139f329e 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -268,7 +268,7 @@ fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool { | |||
268 | 268 | ||
269 | #[cfg(test)] | 269 | #[cfg(test)] |
270 | mod tests { | 270 | mod tests { |
271 | use expect::{expect, Expect}; | 271 | use expect_test::{expect, Expect}; |
272 | 272 | ||
273 | use crate::mock_analysis::analysis_and_position; | 273 | use crate::mock_analysis::analysis_and_position; |
274 | 274 | ||
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index be88b2f9c..25d6f7abd 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -724,7 +724,8 @@ fn highlight_method_call( | |||
724 | hir::Access::Shared => (), | 724 | hir::Access::Shared => (), |
725 | hir::Access::Exclusive => h |= HighlightModifier::Mutable, | 725 | hir::Access::Exclusive => h |= HighlightModifier::Mutable, |
726 | hir::Access::Owned => { | 726 | hir::Access::Owned => { |
727 | if let Some(receiver_ty) = method_call.expr().and_then(|it| sema.type_of_expr(&it)) | 727 | if let Some(receiver_ty) = |
728 | method_call.receiver().and_then(|it| sema.type_of_expr(&it)) | ||
728 | { | 729 | { |
729 | if !receiver_ty.is_copy(sema.db) { | 730 | if !receiver_ty.is_copy(sema.db) { |
730 | h |= HighlightModifier::Consuming | 731 | h |= HighlightModifier::Consuming |
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index ccb76f552..1c3fea058 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::fs; | 1 | use std::fs; |
2 | 2 | ||
3 | use expect::{expect_file, ExpectFile}; | 3 | use expect_test::{expect_file, ExpectFile}; |
4 | use test_utils::project_dir; | 4 | use test_utils::project_dir; |
5 | 5 | ||
6 | use crate::{mock_analysis::single_file, FileRange, TextRange}; | 6 | use crate::{mock_analysis::single_file, FileRange, TextRange}; |
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index ce7631c69..edab1d644 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -203,11 +203,25 @@ impl<'a> FindUsages<'a> { | |||
203 | } | 203 | } |
204 | 204 | ||
205 | pub fn at_least_one(self) -> bool { | 205 | pub fn at_least_one(self) -> bool { |
206 | self.all().is_empty() | 206 | let mut found = false; |
207 | self.search(&mut |_reference| { | ||
208 | found = true; | ||
209 | true | ||
210 | }); | ||
211 | found | ||
207 | } | 212 | } |
208 | 213 | ||
209 | pub fn all(self) -> Vec<Reference> { | 214 | pub fn all(self) -> Vec<Reference> { |
210 | let _p = profile::span("Definition::find_usages"); | 215 | let mut res = Vec::new(); |
216 | self.search(&mut |reference| { | ||
217 | res.push(reference); | ||
218 | false | ||
219 | }); | ||
220 | res | ||
221 | } | ||
222 | |||
223 | fn search(self, sink: &mut dyn FnMut(Reference) -> bool) { | ||
224 | let _p = profile::span("FindUsages:search"); | ||
211 | let sema = self.sema; | 225 | let sema = self.sema; |
212 | 226 | ||
213 | let search_scope = { | 227 | let search_scope = { |
@@ -219,13 +233,11 @@ impl<'a> FindUsages<'a> { | |||
219 | }; | 233 | }; |
220 | 234 | ||
221 | let name = match self.def.name(sema.db) { | 235 | let name = match self.def.name(sema.db) { |
222 | None => return Vec::new(), | ||
223 | Some(it) => it.to_string(), | 236 | Some(it) => it.to_string(), |
237 | None => return, | ||
224 | }; | 238 | }; |
225 | 239 | ||
226 | let pat = name.as_str(); | 240 | let pat = name.as_str(); |
227 | let mut refs = vec![]; | ||
228 | |||
229 | for (file_id, search_range) in search_scope { | 241 | for (file_id, search_range) in search_scope { |
230 | let text = sema.db.file_text(file_id); | 242 | let text = sema.db.file_text(file_id); |
231 | let search_range = | 243 | let search_range = |
@@ -240,10 +252,9 @@ impl<'a> FindUsages<'a> { | |||
240 | } | 252 | } |
241 | 253 | ||
242 | let name_ref: ast::NameRef = | 254 | let name_ref: ast::NameRef = |
243 | if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) { | 255 | match sema.find_node_at_offset_with_descend(&tree, offset) { |
244 | name_ref | 256 | Some(it) => it, |
245 | } else { | 257 | None => continue, |
246 | continue; | ||
247 | }; | 258 | }; |
248 | 259 | ||
249 | match classify_name_ref(&sema, &name_ref) { | 260 | match classify_name_ref(&sema, &name_ref) { |
@@ -256,43 +267,45 @@ impl<'a> FindUsages<'a> { | |||
256 | ReferenceKind::Other | 267 | ReferenceKind::Other |
257 | }; | 268 | }; |
258 | 269 | ||
259 | let file_range = sema.original_range(name_ref.syntax()); | 270 | let reference = Reference { |
260 | refs.push(Reference { | 271 | file_range: sema.original_range(name_ref.syntax()), |
261 | file_range, | ||
262 | kind, | 272 | kind, |
263 | access: reference_access(&def, &name_ref), | 273 | access: reference_access(&def, &name_ref), |
264 | }); | 274 | }; |
275 | if sink(reference) { | ||
276 | return; | ||
277 | } | ||
265 | } | 278 | } |
266 | Some(NameRefClass::FieldShorthand { local, field }) => { | 279 | Some(NameRefClass::FieldShorthand { local, field }) => { |
267 | match self.def { | 280 | let reference = match self.def { |
268 | Definition::Field(_) if &field == self.def => refs.push(Reference { | 281 | Definition::Field(_) if &field == self.def => Reference { |
269 | file_range: self.sema.original_range(name_ref.syntax()), | 282 | file_range: self.sema.original_range(name_ref.syntax()), |
270 | kind: ReferenceKind::FieldShorthandForField, | 283 | kind: ReferenceKind::FieldShorthandForField, |
271 | access: reference_access(&field, &name_ref), | 284 | access: reference_access(&field, &name_ref), |
272 | }), | 285 | }, |
273 | Definition::Local(l) if &local == l => refs.push(Reference { | 286 | Definition::Local(l) if &local == l => Reference { |
274 | file_range: self.sema.original_range(name_ref.syntax()), | 287 | file_range: self.sema.original_range(name_ref.syntax()), |
275 | kind: ReferenceKind::FieldShorthandForLocal, | 288 | kind: ReferenceKind::FieldShorthandForLocal, |
276 | access: reference_access(&Definition::Local(local), &name_ref), | 289 | access: reference_access(&Definition::Local(local), &name_ref), |
277 | }), | 290 | }, |
278 | 291 | _ => continue, // not a usage | |
279 | _ => {} // not a usage | ||
280 | }; | 292 | }; |
293 | if sink(reference) { | ||
294 | return; | ||
295 | } | ||
281 | } | 296 | } |
282 | _ => {} // not a usage | 297 | _ => {} // not a usage |
283 | } | 298 | } |
284 | } | 299 | } |
285 | } | 300 | } |
286 | refs | ||
287 | } | 301 | } |
288 | } | 302 | } |
289 | 303 | ||
290 | fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { | 304 | fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { |
291 | // Only Locals and Fields have accesses for now. | 305 | // Only Locals and Fields have accesses for now. |
292 | match def { | 306 | if !matches!(def, Definition::Local(_) | Definition::Field(_)) { |
293 | Definition::Local(_) | Definition::Field(_) => {} | 307 | return None; |
294 | _ => return None, | 308 | } |
295 | }; | ||
296 | 309 | ||
297 | let mode = name_ref.syntax().ancestors().find_map(|node| { | 310 | let mode = name_ref.syntax().ancestors().find_map(|node| { |
298 | match_ast! { | 311 | match_ast! { |
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index c7c1eda0f..068a961dc 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -57,7 +57,7 @@ proc_macro_srv = { path = "../proc_macro_srv" } | |||
57 | winapi = "0.3.8" | 57 | winapi = "0.3.8" |
58 | 58 | ||
59 | [dev-dependencies] | 59 | [dev-dependencies] |
60 | expect = { path = "../expect" } | 60 | expect-test = "0.1" |
61 | test_utils = { path = "../test_utils" } | 61 | test_utils = { path = "../test_utils" } |
62 | mbe = { path = "../mbe" } | 62 | mbe = { path = "../mbe" } |
63 | tt = { path = "../tt" } | 63 | tt = { path = "../tt" } |
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index df5583897..e52b97913 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs | |||
@@ -256,7 +256,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( | |||
256 | mod tests { | 256 | mod tests { |
257 | use super::*; | 257 | use super::*; |
258 | 258 | ||
259 | use expect::{expect_file, ExpectFile}; | 259 | use expect_test::{expect_file, ExpectFile}; |
260 | 260 | ||
261 | fn check(diagnostics_json: &str, expect: ExpectFile) { | 261 | fn check(diagnostics_json: &str, expect: ExpectFile) { |
262 | check_with_config(DiagnosticsMapConfig::default(), diagnostics_json, expect) | 262 | check_with_config(DiagnosticsMapConfig::default(), diagnostics_json, expect) |
diff --git a/crates/ssr/Cargo.toml b/crates/ssr/Cargo.toml index 7c2090de3..22b6af0fa 100644 --- a/crates/ssr/Cargo.toml +++ b/crates/ssr/Cargo.toml | |||
@@ -22,4 +22,4 @@ hir = { path = "../hir" } | |||
22 | test_utils = { path = "../test_utils" } | 22 | test_utils = { path = "../test_utils" } |
23 | 23 | ||
24 | [dev-dependencies] | 24 | [dev-dependencies] |
25 | expect = { path = "../expect" } | 25 | expect-test = "0.1" |
diff --git a/crates/ssr/src/matching.rs b/crates/ssr/src/matching.rs index 26968c474..948862a77 100644 --- a/crates/ssr/src/matching.rs +++ b/crates/ssr/src/matching.rs | |||
@@ -546,10 +546,12 @@ impl<'db, 'sema> Matcher<'db, 'sema> { | |||
546 | // information on the placeholder match about autoderef and autoref. This allows us to use | 546 | // information on the placeholder match about autoderef and autoref. This allows us to use |
547 | // the placeholder in a context where autoderef and autoref don't apply. | 547 | // the placeholder in a context where autoderef and autoref don't apply. |
548 | if code_resolved_function.self_param(self.sema.db).is_some() { | 548 | if code_resolved_function.self_param(self.sema.db).is_some() { |
549 | if let (Some(pattern_type), Some(expr)) = (&pattern_ufcs.qualifier_type, &code.expr()) { | 549 | if let (Some(pattern_type), Some(expr)) = |
550 | (&pattern_ufcs.qualifier_type, &code.receiver()) | ||
551 | { | ||
550 | let deref_count = self.check_expr_type(pattern_type, expr)?; | 552 | let deref_count = self.check_expr_type(pattern_type, expr)?; |
551 | let pattern_receiver = pattern_args.next(); | 553 | let pattern_receiver = pattern_args.next(); |
552 | self.attempt_match_opt(phase, pattern_receiver.clone(), code.expr())?; | 554 | self.attempt_match_opt(phase, pattern_receiver.clone(), code.receiver())?; |
553 | if let Phase::Second(match_out) = phase { | 555 | if let Phase::Second(match_out) = phase { |
554 | if let Some(placeholder_value) = pattern_receiver | 556 | if let Some(placeholder_value) = pattern_receiver |
555 | .and_then(|n| self.get_placeholder_for_node(n.syntax())) | 557 | .and_then(|n| self.get_placeholder_for_node(n.syntax())) |
@@ -568,7 +570,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { | |||
568 | } | 570 | } |
569 | } | 571 | } |
570 | } else { | 572 | } else { |
571 | self.attempt_match_opt(phase, pattern_args.next(), code.expr())?; | 573 | self.attempt_match_opt(phase, pattern_args.next(), code.receiver())?; |
572 | } | 574 | } |
573 | let mut code_args = | 575 | let mut code_args = |
574 | code.arg_list().ok_or_else(|| match_error!("Code method call has no args"))?.args(); | 576 | code.arg_list().ok_or_else(|| match_error!("Code method call has no args"))?.args(); |
diff --git a/crates/ssr/src/replacing.rs b/crates/ssr/src/replacing.rs index 29284e3f1..7e7ce37bd 100644 --- a/crates/ssr/src/replacing.rs +++ b/crates/ssr/src/replacing.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use crate::{resolving::ResolvedRule, Match, SsrMatches}; | 3 | use crate::{resolving::ResolvedRule, Match, SsrMatches}; |
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use rustc_hash::{FxHashMap, FxHashSet}; | 5 | use rustc_hash::{FxHashMap, FxHashSet}; |
6 | use syntax::ast::{self, AstToken}; | 6 | use syntax::ast::{self, AstNode, AstToken}; |
7 | use syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize}; | 7 | use syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize}; |
8 | use test_utils::mark; | 8 | use test_utils::mark; |
9 | use text_edit::TextEdit; | 9 | use text_edit::TextEdit; |
@@ -93,7 +93,6 @@ impl ReplacementRenderer<'_> { | |||
93 | } | 93 | } |
94 | 94 | ||
95 | fn render_node(&mut self, node: &SyntaxNode) { | 95 | fn render_node(&mut self, node: &SyntaxNode) { |
96 | use syntax::ast::AstNode; | ||
97 | if let Some(mod_path) = self.match_info.rendered_template_paths.get(&node) { | 96 | if let Some(mod_path) = self.match_info.rendered_template_paths.get(&node) { |
98 | self.out.push_str(&mod_path.to_string()); | 97 | self.out.push_str(&mod_path.to_string()); |
99 | // Emit everything except for the segment's name-ref, since we already effectively | 98 | // Emit everything except for the segment's name-ref, since we already effectively |
@@ -206,11 +205,10 @@ impl ReplacementRenderer<'_> { | |||
206 | /// method call doesn't count. e.g. if the token is `$a`, then `$a.foo()` will return true, while | 205 | /// method call doesn't count. e.g. if the token is `$a`, then `$a.foo()` will return true, while |
207 | /// `($a + $b).foo()` or `x.foo($a)` will return false. | 206 | /// `($a + $b).foo()` or `x.foo($a)` will return false. |
208 | fn token_is_method_call_receiver(token: &SyntaxToken) -> bool { | 207 | fn token_is_method_call_receiver(token: &SyntaxToken) -> bool { |
209 | use syntax::ast::AstNode; | ||
210 | // Find the first method call among the ancestors of `token`, then check if the only token | 208 | // Find the first method call among the ancestors of `token`, then check if the only token |
211 | // within the receiver is `token`. | 209 | // within the receiver is `token`. |
212 | if let Some(receiver) = | 210 | if let Some(receiver) = |
213 | token.ancestors().find_map(ast::MethodCallExpr::cast).and_then(|call| call.expr()) | 211 | token.ancestors().find_map(ast::MethodCallExpr::cast).and_then(|call| call.receiver()) |
214 | { | 212 | { |
215 | let tokens = receiver.syntax().descendants_with_tokens().filter_map(|node_or_token| { | 213 | let tokens = receiver.syntax().descendants_with_tokens().filter_map(|node_or_token| { |
216 | match node_or_token { | 214 | match node_or_token { |
@@ -226,7 +224,6 @@ fn token_is_method_call_receiver(token: &SyntaxToken) -> bool { | |||
226 | } | 224 | } |
227 | 225 | ||
228 | fn parse_as_kind(code: &str, kind: SyntaxKind) -> Option<SyntaxNode> { | 226 | fn parse_as_kind(code: &str, kind: SyntaxKind) -> Option<SyntaxNode> { |
229 | use syntax::ast::AstNode; | ||
230 | if ast::Expr::can_cast(kind) { | 227 | if ast::Expr::can_cast(kind) { |
231 | if let Ok(expr) = ast::Expr::parse(code) { | 228 | if let Ok(expr) = ast::Expr::parse(code) { |
232 | return Some(expr.syntax().clone()); | 229 | return Some(expr.syntax().clone()); |
diff --git a/crates/ssr/src/tests.rs b/crates/ssr/src/tests.rs index e45c88864..20231a9bc 100644 --- a/crates/ssr/src/tests.rs +++ b/crates/ssr/src/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use crate::{MatchFinder, SsrRule}; | 1 | use crate::{MatchFinder, SsrRule}; |
2 | use base_db::{salsa::Durability, FileId, FilePosition, FileRange, SourceDatabaseExt}; | 2 | use base_db::{salsa::Durability, FileId, FilePosition, FileRange, SourceDatabaseExt}; |
3 | use expect::{expect, Expect}; | 3 | use expect_test::{expect, Expect}; |
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | use test_utils::{mark, RangeOrOffset}; | 6 | use test_utils::{mark, RangeOrOffset}; |
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index ec3132da8..6818f3ad8 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -30,6 +30,6 @@ parser = { path = "../parser" } | |||
30 | [dev-dependencies] | 30 | [dev-dependencies] |
31 | walkdir = "2.3.1" | 31 | walkdir = "2.3.1" |
32 | rayon = "1" | 32 | rayon = "1" |
33 | expect-test = "0.1" | ||
33 | 34 | ||
34 | test_utils = { path = "../test_utils" } | 35 | test_utils = { path = "../test_utils" } |
35 | expect = { path = "../expect" } | ||
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 3d49309d1..6317407c6 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs | |||
@@ -66,6 +66,7 @@ impl ParamList { | |||
66 | pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) } | 66 | pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) } |
67 | pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } | 67 | pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } |
68 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | 68 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } |
69 | pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) } | ||
69 | } | 70 | } |
70 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 71 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
71 | pub struct RetType { | 72 | pub struct RetType { |
@@ -809,7 +810,7 @@ pub struct MethodCallExpr { | |||
809 | impl ast::AttrsOwner for MethodCallExpr {} | 810 | impl ast::AttrsOwner for MethodCallExpr {} |
810 | impl ast::ArgListOwner for MethodCallExpr {} | 811 | impl ast::ArgListOwner for MethodCallExpr {} |
811 | impl MethodCallExpr { | 812 | impl MethodCallExpr { |
812 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | 813 | pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) } |
813 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | 814 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } |
814 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | 815 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } |
815 | pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) } | 816 | pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) } |
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index ddc718369..8c217dfe0 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs | |||
@@ -4,7 +4,7 @@ use std::{ | |||
4 | path::{Path, PathBuf}, | 4 | path::{Path, PathBuf}, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use expect::expect_file; | 7 | use expect_test::expect_file; |
8 | use rayon::prelude::*; | 8 | use rayon::prelude::*; |
9 | use test_utils::project_dir; | 9 | use test_utils::project_dir; |
10 | 10 | ||
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 49d2d1c6f..ec2087502 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts | |||
@@ -25,7 +25,6 @@ export const log = new class { | |||
25 | debug(...msg: [unknown, ...unknown[]]): void { | 25 | debug(...msg: [unknown, ...unknown[]]): void { |
26 | if (!log.enabled) return; | 26 | if (!log.enabled) return; |
27 | log.write("DEBUG", ...msg); | 27 | log.write("DEBUG", ...msg); |
28 | log.output.toString(); | ||
29 | } | 28 | } |
30 | 29 | ||
31 | info(...msg: [unknown, ...unknown[]]): void { | 30 | info(...msg: [unknown, ...unknown[]]): void { |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 53ae9f11c..200e8aa50 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -477,6 +477,7 @@ impl Field { | |||
477 | "#" => "pound", | 477 | "#" => "pound", |
478 | "?" => "question_mark", | 478 | "?" => "question_mark", |
479 | "," => "comma", | 479 | "," => "comma", |
480 | "|" => "pipe", | ||
480 | _ => name, | 481 | _ => name, |
481 | }; | 482 | }; |
482 | format_ident!("{}_token", name) | 483 | format_ident!("{}_token", name) |