diff options
27 files changed, 516 insertions, 145 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index c2d99280f..475d337f3 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | once_cell = "1.3.1" | 15 | once_cell = "1.3.1" |
16 | rustc-hash = "1.1.0" | 16 | rustc-hash = "1.1.0" |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index e833e032c..43de9edd6 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -191,6 +191,8 @@ pub mod known { | |||
191 | filter_map, | 191 | filter_map, |
192 | next, | 192 | next, |
193 | iter_mut, | 193 | iter_mut, |
194 | len, | ||
195 | is_empty, | ||
194 | // Builtin macros | 196 | // Builtin macros |
195 | file, | 197 | file, |
196 | column, | 198 | column, |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index b9c93f56f..0ef27cd37 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | itertools = "0.10.0" | 14 | itertools = "0.10.0" |
15 | arrayvec = "0.5.1" | 15 | arrayvec = "0.5.1" |
16 | smallvec = "1.2.0" | 16 | smallvec = "1.2.0" |
@@ -31,7 +31,7 @@ profile = { path = "../profile", version = "0.0.0" } | |||
31 | syntax = { path = "../syntax", version = "0.0.0" } | 31 | syntax = { path = "../syntax", version = "0.0.0" } |
32 | 32 | ||
33 | [dev-dependencies] | 33 | [dev-dependencies] |
34 | test_utils = { path = "../test_utils" } | 34 | test_utils = { path = "../test_utils" } |
35 | expect-test = "1.1" | 35 | expect-test = "1.1" |
36 | tracing = "0.1" | 36 | tracing = "0.1" |
37 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } | 37 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } |
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index 6ae7c9e6c..f04bcf531 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | either = "1.5.3" | 14 | either = "1.5.3" |
15 | indexmap = "1.4.0" | 15 | indexmap = "1.4.0" |
16 | itertools = "0.10.0" | 16 | itertools = "0.10.0" |
diff --git a/crates/ide_assists/Cargo.toml b/crates/ide_assists/Cargo.toml index dd9aa27c6..a83acb191 100644 --- a/crates/ide_assists/Cargo.toml +++ b/crates/ide_assists/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | itertools = "0.10.0" | 15 | itertools = "0.10.0" |
16 | either = "1.6.1" | 16 | either = "1.6.1" |
diff --git a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs new file mode 100644 index 000000000..aa7072f25 --- /dev/null +++ b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs | |||
@@ -0,0 +1,255 @@ | |||
1 | use hir::{known, HasSource, Name}; | ||
2 | use syntax::{ | ||
3 | ast::{self, NameOwner}, | ||
4 | AstNode, TextRange, | ||
5 | }; | ||
6 | |||
7 | use crate::{ | ||
8 | assist_context::{AssistContext, Assists}, | ||
9 | AssistId, AssistKind, | ||
10 | }; | ||
11 | |||
12 | // Assist: generate_is_empty_from_len | ||
13 | // | ||
14 | // Generates is_empty implementation from the len method. | ||
15 | // | ||
16 | // ``` | ||
17 | // struct MyStruct { data: Vec<String> } | ||
18 | // | ||
19 | // impl MyStruct { | ||
20 | // p$0ub fn len(&self) -> usize { | ||
21 | // self.data.len() | ||
22 | // } | ||
23 | // } | ||
24 | // ``` | ||
25 | // -> | ||
26 | // ``` | ||
27 | // struct MyStruct { data: Vec<String> } | ||
28 | // | ||
29 | // impl MyStruct { | ||
30 | // pub fn len(&self) -> usize { | ||
31 | // self.data.len() | ||
32 | // } | ||
33 | // | ||
34 | // pub fn is_empty(&self) -> bool { | ||
35 | // self.len() == 0 | ||
36 | // } | ||
37 | // } | ||
38 | // ``` | ||
39 | pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
40 | let fn_node = ctx.find_node_at_offset::<ast::Fn>()?; | ||
41 | let fn_name = fn_node.name()?; | ||
42 | |||
43 | if fn_name.text() != "len" { | ||
44 | cov_mark::hit!(len_function_not_present); | ||
45 | return None; | ||
46 | } | ||
47 | |||
48 | if fn_node.param_list()?.params().next().is_some() { | ||
49 | cov_mark::hit!(len_function_with_parameters); | ||
50 | return None; | ||
51 | } | ||
52 | |||
53 | let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; | ||
54 | if get_impl_method(ctx, &impl_, &known::is_empty).is_some() { | ||
55 | cov_mark::hit!(is_empty_already_implemented); | ||
56 | return None; | ||
57 | } | ||
58 | |||
59 | let range = get_text_range_of_len_function(ctx, &impl_)?; | ||
60 | |||
61 | acc.add( | ||
62 | AssistId("generate_is_empty_from_len", AssistKind::Generate), | ||
63 | "Generate a is_empty impl from a len function", | ||
64 | range, | ||
65 | |builder| { | ||
66 | let code = r#" | ||
67 | |||
68 | pub fn is_empty(&self) -> bool { | ||
69 | self.len() == 0 | ||
70 | }"# | ||
71 | .to_string(); | ||
72 | builder.insert(range.end(), code) | ||
73 | }, | ||
74 | ) | ||
75 | } | ||
76 | |||
77 | fn get_impl_method( | ||
78 | ctx: &AssistContext, | ||
79 | impl_: &ast::Impl, | ||
80 | fn_name: &Name, | ||
81 | ) -> Option<hir::Function> { | ||
82 | let db = ctx.sema.db; | ||
83 | let impl_def: hir::Impl = ctx.sema.to_def(impl_)?; | ||
84 | |||
85 | let scope = ctx.sema.scope(impl_.syntax()); | ||
86 | let krate = impl_def.module(db).krate(); | ||
87 | let ty = impl_def.target_ty(db); | ||
88 | let traits_in_scope = scope.traits_in_scope(); | ||
89 | ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) | ||
90 | } | ||
91 | |||
92 | fn get_text_range_of_len_function(ctx: &AssistContext, impl_: &ast::Impl) -> Option<TextRange> { | ||
93 | let db = ctx.sema.db; | ||
94 | let func = get_impl_method(ctx, impl_, &known::len)?; | ||
95 | let node = func.source(db)?; | ||
96 | Some(node.syntax().value.text_range()) | ||
97 | } | ||
98 | |||
99 | #[cfg(test)] | ||
100 | mod tests { | ||
101 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
102 | |||
103 | use super::*; | ||
104 | |||
105 | #[test] | ||
106 | fn len_function_not_present() { | ||
107 | cov_mark::check!(len_function_not_present); | ||
108 | check_assist_not_applicable( | ||
109 | generate_is_empty_from_len, | ||
110 | r#" | ||
111 | struct MyStruct { data: Vec<String> } | ||
112 | |||
113 | impl MyStruct { | ||
114 | p$0ub fn test(&self) -> usize { | ||
115 | self.data.len() | ||
116 | } | ||
117 | } | ||
118 | "#, | ||
119 | ); | ||
120 | } | ||
121 | |||
122 | #[test] | ||
123 | fn len_function_with_parameters() { | ||
124 | cov_mark::check!(len_function_with_parameters); | ||
125 | check_assist_not_applicable( | ||
126 | generate_is_empty_from_len, | ||
127 | r#" | ||
128 | struct MyStruct { data: Vec<String> } | ||
129 | |||
130 | impl MyStruct { | ||
131 | p$0ub fn len(&self, _i: bool) -> usize { | ||
132 | self.data.len() | ||
133 | } | ||
134 | } | ||
135 | "#, | ||
136 | ); | ||
137 | } | ||
138 | |||
139 | #[test] | ||
140 | fn is_empty_already_implemented() { | ||
141 | cov_mark::check!(is_empty_already_implemented); | ||
142 | check_assist_not_applicable( | ||
143 | generate_is_empty_from_len, | ||
144 | r#" | ||
145 | struct MyStruct { data: Vec<String> } | ||
146 | |||
147 | impl MyStruct { | ||
148 | p$0ub fn len(&self) -> usize { | ||
149 | self.data.len() | ||
150 | } | ||
151 | |||
152 | pub fn is_empty(&self) -> bool { | ||
153 | self.len() == 0 | ||
154 | } | ||
155 | } | ||
156 | "#, | ||
157 | ); | ||
158 | } | ||
159 | |||
160 | #[test] | ||
161 | fn generate_is_empty() { | ||
162 | check_assist( | ||
163 | generate_is_empty_from_len, | ||
164 | r#" | ||
165 | struct MyStruct { data: Vec<String> } | ||
166 | |||
167 | impl MyStruct { | ||
168 | p$0ub fn len(&self) -> usize { | ||
169 | self.data.len() | ||
170 | } | ||
171 | } | ||
172 | "#, | ||
173 | r#" | ||
174 | struct MyStruct { data: Vec<String> } | ||
175 | |||
176 | impl MyStruct { | ||
177 | pub fn len(&self) -> usize { | ||
178 | self.data.len() | ||
179 | } | ||
180 | |||
181 | pub fn is_empty(&self) -> bool { | ||
182 | self.len() == 0 | ||
183 | } | ||
184 | } | ||
185 | "#, | ||
186 | ); | ||
187 | } | ||
188 | |||
189 | #[test] | ||
190 | fn multiple_functions_in_impl() { | ||
191 | check_assist( | ||
192 | generate_is_empty_from_len, | ||
193 | r#" | ||
194 | struct MyStruct { data: Vec<String> } | ||
195 | |||
196 | impl MyStruct { | ||
197 | pub fn new() -> Self { | ||
198 | Self { data: 0 } | ||
199 | } | ||
200 | |||
201 | p$0ub fn len(&self) -> usize { | ||
202 | self.data.len() | ||
203 | } | ||
204 | |||
205 | pub fn work(&self) -> Option<usize> { | ||
206 | |||
207 | } | ||
208 | } | ||
209 | "#, | ||
210 | r#" | ||
211 | struct MyStruct { data: Vec<String> } | ||
212 | |||
213 | impl MyStruct { | ||
214 | pub fn new() -> Self { | ||
215 | Self { data: 0 } | ||
216 | } | ||
217 | |||
218 | pub fn len(&self) -> usize { | ||
219 | self.data.len() | ||
220 | } | ||
221 | |||
222 | pub fn is_empty(&self) -> bool { | ||
223 | self.len() == 0 | ||
224 | } | ||
225 | |||
226 | pub fn work(&self) -> Option<usize> { | ||
227 | |||
228 | } | ||
229 | } | ||
230 | "#, | ||
231 | ); | ||
232 | } | ||
233 | |||
234 | #[test] | ||
235 | fn multiple_impls() { | ||
236 | check_assist_not_applicable( | ||
237 | generate_is_empty_from_len, | ||
238 | r#" | ||
239 | struct MyStruct { data: Vec<String> } | ||
240 | |||
241 | impl MyStruct { | ||
242 | p$0ub fn len(&self) -> usize { | ||
243 | self.data.len() | ||
244 | } | ||
245 | } | ||
246 | |||
247 | impl MyStruct { | ||
248 | pub fn is_empty(&self) -> bool { | ||
249 | self.len() == 0 | ||
250 | } | ||
251 | } | ||
252 | "#, | ||
253 | ); | ||
254 | } | ||
255 | } | ||
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs index f1aab74d4..8c068a6c0 100644 --- a/crates/ide_assists/src/lib.rs +++ b/crates/ide_assists/src/lib.rs | |||
@@ -129,6 +129,7 @@ mod handlers { | |||
129 | mod flip_trait_bound; | 129 | mod flip_trait_bound; |
130 | mod generate_default_from_enum_variant; | 130 | mod generate_default_from_enum_variant; |
131 | mod generate_default_from_new; | 131 | mod generate_default_from_new; |
132 | mod generate_is_empty_from_len; | ||
132 | mod generate_derive; | 133 | mod generate_derive; |
133 | mod generate_enum_is_method; | 134 | mod generate_enum_is_method; |
134 | mod generate_enum_projection_method; | 135 | mod generate_enum_projection_method; |
@@ -193,6 +194,7 @@ mod handlers { | |||
193 | flip_trait_bound::flip_trait_bound, | 194 | flip_trait_bound::flip_trait_bound, |
194 | generate_default_from_enum_variant::generate_default_from_enum_variant, | 195 | generate_default_from_enum_variant::generate_default_from_enum_variant, |
195 | generate_default_from_new::generate_default_from_new, | 196 | generate_default_from_new::generate_default_from_new, |
197 | generate_is_empty_from_len::generate_is_empty_from_len, | ||
196 | generate_derive::generate_derive, | 198 | generate_derive::generate_derive, |
197 | generate_enum_is_method::generate_enum_is_method, | 199 | generate_enum_is_method::generate_enum_is_method, |
198 | generate_enum_projection_method::generate_enum_as_method, | 200 | generate_enum_projection_method::generate_enum_as_method, |
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 3f77edd8d..736027ff0 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs | |||
@@ -722,6 +722,35 @@ impl<T: Clone> Ctx<T> { | |||
722 | } | 722 | } |
723 | 723 | ||
724 | #[test] | 724 | #[test] |
725 | fn doctest_generate_is_empty_from_len() { | ||
726 | check_doc_test( | ||
727 | "generate_is_empty_from_len", | ||
728 | r#####" | ||
729 | struct MyStruct { data: Vec<String> } | ||
730 | |||
731 | impl MyStruct { | ||
732 | p$0ub fn len(&self) -> usize { | ||
733 | self.data.len() | ||
734 | } | ||
735 | } | ||
736 | "#####, | ||
737 | r#####" | ||
738 | struct MyStruct { data: Vec<String> } | ||
739 | |||
740 | impl MyStruct { | ||
741 | pub fn len(&self) -> usize { | ||
742 | self.data.len() | ||
743 | } | ||
744 | |||
745 | pub fn is_empty(&self) -> bool { | ||
746 | self.len() == 0 | ||
747 | } | ||
748 | } | ||
749 | "#####, | ||
750 | ) | ||
751 | } | ||
752 | |||
753 | #[test] | ||
725 | fn doctest_generate_new() { | 754 | fn doctest_generate_new() { |
726 | check_doc_test( | 755 | check_doc_test( |
727 | "generate_new", | 756 | "generate_new", |
diff --git a/crates/ide_completion/Cargo.toml b/crates/ide_completion/Cargo.toml index 585ecca50..6bd8a5500 100644 --- a/crates/ide_completion/Cargo.toml +++ b/crates/ide_completion/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | itertools = "0.10.0" | 14 | itertools = "0.10.0" |
15 | log = "0.4.8" | 15 | log = "0.4.8" |
16 | rustc-hash = "1.1.0" | 16 | rustc-hash = "1.1.0" |
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index 9282c3827..46cef58f0 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -11,10 +11,13 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
11 | return; | 11 | return; |
12 | } | 12 | } |
13 | 13 | ||
14 | if let Some(ty) = &ctx.expected_type { | 14 | if !ctx.is_irrefutable_pat_binding { |
15 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { | 15 | if let Some(ty) = ctx.expected_type.as_ref() { |
16 | acc.add_qualified_variant_pat(ctx, variant, path) | 16 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { |
17 | }); | 17 | acc.add_qualified_variant_pat(ctx, variant, path.clone()); |
18 | acc.add_qualified_enum_variant(ctx, variant, path); | ||
19 | }); | ||
20 | } | ||
18 | } | 21 | } |
19 | 22 | ||
20 | // FIXME: ideally, we should look at the type we are matching against and | 23 | // FIXME: ideally, we should look at the type we are matching against and |
@@ -85,7 +88,7 @@ static FOO: E = E::X; | |||
85 | struct Bar { f: u32 } | 88 | struct Bar { f: u32 } |
86 | 89 | ||
87 | fn foo() { | 90 | fn foo() { |
88 | match E::X { $0 } | 91 | match E::X { a$0 } |
89 | } | 92 | } |
90 | "#, | 93 | "#, |
91 | expect![[r#" | 94 | expect![[r#" |
@@ -106,10 +109,11 @@ macro_rules! m { ($e:expr) => { $e } } | |||
106 | enum E { X } | 109 | enum E { X } |
107 | 110 | ||
108 | fn foo() { | 111 | fn foo() { |
109 | m!(match E::X { $0 }) | 112 | m!(match E::X { a$0 }) |
110 | } | 113 | } |
111 | "#, | 114 | "#, |
112 | expect![[r#" | 115 | expect![[r#" |
116 | ev E::X () | ||
113 | en E | 117 | en E |
114 | ma m!(…) macro_rules! m | 118 | ma m!(…) macro_rules! m |
115 | "#]], | 119 | "#]], |
@@ -129,7 +133,7 @@ static FOO: E = E::X; | |||
129 | struct Bar { f: u32 } | 133 | struct Bar { f: u32 } |
130 | 134 | ||
131 | fn foo() { | 135 | fn foo() { |
132 | let $0 | 136 | let a$0 |
133 | } | 137 | } |
134 | "#, | 138 | "#, |
135 | expect![[r#" | 139 | expect![[r#" |
@@ -147,7 +151,7 @@ enum E { X } | |||
147 | static FOO: E = E::X; | 151 | static FOO: E = E::X; |
148 | struct Bar { f: u32 } | 152 | struct Bar { f: u32 } |
149 | 153 | ||
150 | fn foo($0) { | 154 | fn foo(a$0) { |
151 | } | 155 | } |
152 | "#, | 156 | "#, |
153 | expect![[r#" | 157 | expect![[r#" |
@@ -163,7 +167,7 @@ fn foo($0) { | |||
163 | struct Bar { f: u32 } | 167 | struct Bar { f: u32 } |
164 | 168 | ||
165 | fn foo() { | 169 | fn foo() { |
166 | let $0 | 170 | let a$0 |
167 | } | 171 | } |
168 | "#, | 172 | "#, |
169 | expect![[r#" | 173 | expect![[r#" |
@@ -179,7 +183,7 @@ fn foo() { | |||
179 | struct Foo { bar: String, baz: String } | 183 | struct Foo { bar: String, baz: String } |
180 | struct Bar(String, String); | 184 | struct Bar(String, String); |
181 | struct Baz; | 185 | struct Baz; |
182 | fn outer($0) {} | 186 | fn outer(a$0) {} |
183 | "#, | 187 | "#, |
184 | expect![[r#" | 188 | expect![[r#" |
185 | bn Foo Foo { bar$1, baz$2 }: Foo$0 | 189 | bn Foo Foo { bar$1, baz$2 }: Foo$0 |
@@ -196,7 +200,7 @@ struct Foo { bar: String, baz: String } | |||
196 | struct Bar(String, String); | 200 | struct Bar(String, String); |
197 | struct Baz; | 201 | struct Baz; |
198 | fn outer() { | 202 | fn outer() { |
199 | let $0 | 203 | let a$0 |
200 | } | 204 | } |
201 | "#, | 205 | "#, |
202 | expect![[r#" | 206 | expect![[r#" |
@@ -215,7 +219,7 @@ struct Bar(String, String); | |||
215 | struct Baz; | 219 | struct Baz; |
216 | fn outer() { | 220 | fn outer() { |
217 | match () { | 221 | match () { |
218 | $0 | 222 | a$0 |
219 | } | 223 | } |
220 | } | 224 | } |
221 | "#, | 225 | "#, |
@@ -239,7 +243,7 @@ use foo::*; | |||
239 | 243 | ||
240 | fn outer() { | 244 | fn outer() { |
241 | match () { | 245 | match () { |
242 | $0 | 246 | a$0 |
243 | } | 247 | } |
244 | } | 248 | } |
245 | "#, | 249 | "#, |
@@ -258,7 +262,7 @@ fn outer() { | |||
258 | struct Foo(i32); | 262 | struct Foo(i32); |
259 | fn main() { | 263 | fn main() { |
260 | match Foo(92) { | 264 | match Foo(92) { |
261 | $0(92) => (), | 265 | a$0(92) => (), |
262 | } | 266 | } |
263 | } | 267 | } |
264 | "#, | 268 | "#, |
@@ -281,7 +285,7 @@ struct Foo(i32); | |||
281 | impl Foo { | 285 | impl Foo { |
282 | fn foo() { | 286 | fn foo() { |
283 | match () { | 287 | match () { |
284 | $0 | 288 | a$0 |
285 | } | 289 | } |
286 | } | 290 | } |
287 | } | 291 | } |
@@ -314,4 +318,86 @@ impl Foo { | |||
314 | "#]], | 318 | "#]], |
315 | ) | 319 | ) |
316 | } | 320 | } |
321 | |||
322 | #[test] | ||
323 | fn completes_enum_variant_matcharm() { | ||
324 | check( | ||
325 | r#" | ||
326 | enum Foo { Bar, Baz, Quux } | ||
327 | |||
328 | fn main() { | ||
329 | let foo = Foo::Quux; | ||
330 | match foo { Qu$0 } | ||
331 | } | ||
332 | "#, | ||
333 | expect![[r#" | ||
334 | ev Foo::Bar () | ||
335 | ev Foo::Baz () | ||
336 | ev Foo::Quux () | ||
337 | en Foo | ||
338 | "#]], | ||
339 | ) | ||
340 | } | ||
341 | |||
342 | #[test] | ||
343 | fn completes_enum_variant_matcharm_ref() { | ||
344 | check( | ||
345 | r#" | ||
346 | enum Foo { Bar, Baz, Quux } | ||
347 | |||
348 | fn main() { | ||
349 | let foo = Foo::Quux; | ||
350 | match &foo { Qu$0 } | ||
351 | } | ||
352 | "#, | ||
353 | expect![[r#" | ||
354 | ev Foo::Bar () | ||
355 | ev Foo::Baz () | ||
356 | ev Foo::Quux () | ||
357 | en Foo | ||
358 | "#]], | ||
359 | ) | ||
360 | } | ||
361 | |||
362 | #[test] | ||
363 | fn completes_enum_variant_iflet() { | ||
364 | check( | ||
365 | r#" | ||
366 | enum Foo { Bar, Baz, Quux } | ||
367 | |||
368 | fn main() { | ||
369 | let foo = Foo::Quux; | ||
370 | if let Qu$0 = foo { } | ||
371 | } | ||
372 | "#, | ||
373 | expect![[r#" | ||
374 | ev Foo::Bar () | ||
375 | ev Foo::Baz () | ||
376 | ev Foo::Quux () | ||
377 | en Foo | ||
378 | "#]], | ||
379 | ) | ||
380 | } | ||
381 | |||
382 | #[test] | ||
383 | fn completes_enum_variant_impl() { | ||
384 | check( | ||
385 | r#" | ||
386 | enum Foo { Bar, Baz, Quux } | ||
387 | impl Foo { | ||
388 | fn foo() { match Foo::Bar { Q$0 } } | ||
389 | } | ||
390 | "#, | ||
391 | expect![[r#" | ||
392 | ev Self::Bar () | ||
393 | ev Self::Baz () | ||
394 | ev Self::Quux () | ||
395 | ev Foo::Bar () | ||
396 | ev Foo::Baz () | ||
397 | ev Foo::Quux () | ||
398 | sp Self | ||
399 | en Foo | ||
400 | "#]], | ||
401 | ) | ||
402 | } | ||
317 | } | 403 | } |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 044dfd160..5ef80f6a7 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -6,7 +6,7 @@ use syntax::AstNode; | |||
6 | use crate::{CompletionContext, Completions}; | 6 | use crate::{CompletionContext, Completions}; |
7 | 7 | ||
8 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | 8 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { |
9 | if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) { | 9 | if !ctx.is_trivial_path { |
10 | return; | 10 | return; |
11 | } | 11 | } |
12 | if ctx.record_lit_syntax.is_some() | 12 | if ctx.record_lit_syntax.is_some() |
@@ -23,10 +23,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
23 | }); | 23 | }); |
24 | } | 24 | } |
25 | 25 | ||
26 | if ctx.is_pat_binding_or_const { | ||
27 | return; | ||
28 | } | ||
29 | |||
30 | ctx.scope.process_all_names(&mut |name, res| { | 26 | ctx.scope.process_all_names(&mut |name, res| { |
31 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { | 27 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { |
32 | cov_mark::hit!(skip_lifetime_completion); | 28 | cov_mark::hit!(skip_lifetime_completion); |
@@ -609,66 +605,6 @@ fn main() { $0 } | |||
609 | } | 605 | } |
610 | 606 | ||
611 | #[test] | 607 | #[test] |
612 | fn completes_enum_variant_matcharm() { | ||
613 | check( | ||
614 | r#" | ||
615 | enum Foo { Bar, Baz, Quux } | ||
616 | |||
617 | fn main() { | ||
618 | let foo = Foo::Quux; | ||
619 | match foo { Qu$0 } | ||
620 | } | ||
621 | "#, | ||
622 | expect![[r#" | ||
623 | ev Foo::Bar () | ||
624 | ev Foo::Baz () | ||
625 | ev Foo::Quux () | ||
626 | en Foo | ||
627 | "#]], | ||
628 | ) | ||
629 | } | ||
630 | |||
631 | #[test] | ||
632 | fn completes_enum_variant_matcharm_ref() { | ||
633 | check( | ||
634 | r#" | ||
635 | enum Foo { Bar, Baz, Quux } | ||
636 | |||
637 | fn main() { | ||
638 | let foo = Foo::Quux; | ||
639 | match &foo { Qu$0 } | ||
640 | } | ||
641 | "#, | ||
642 | expect![[r#" | ||
643 | ev Foo::Bar () | ||
644 | ev Foo::Baz () | ||
645 | ev Foo::Quux () | ||
646 | en Foo | ||
647 | "#]], | ||
648 | ) | ||
649 | } | ||
650 | |||
651 | #[test] | ||
652 | fn completes_enum_variant_iflet() { | ||
653 | check( | ||
654 | r#" | ||
655 | enum Foo { Bar, Baz, Quux } | ||
656 | |||
657 | fn main() { | ||
658 | let foo = Foo::Quux; | ||
659 | if let Qu$0 = foo { } | ||
660 | } | ||
661 | "#, | ||
662 | expect![[r#" | ||
663 | ev Foo::Bar () | ||
664 | ev Foo::Baz () | ||
665 | ev Foo::Quux () | ||
666 | en Foo | ||
667 | "#]], | ||
668 | ) | ||
669 | } | ||
670 | |||
671 | #[test] | ||
672 | fn completes_enum_variant_basic_expr() { | 608 | fn completes_enum_variant_basic_expr() { |
673 | check( | 609 | check( |
674 | r#" | 610 | r#" |
@@ -701,28 +637,6 @@ fn f() -> m::E { V$0 } | |||
701 | } | 637 | } |
702 | 638 | ||
703 | #[test] | 639 | #[test] |
704 | fn completes_enum_variant_impl() { | ||
705 | check( | ||
706 | r#" | ||
707 | enum Foo { Bar, Baz, Quux } | ||
708 | impl Foo { | ||
709 | fn foo() { match Foo::Bar { Q$0 } } | ||
710 | } | ||
711 | "#, | ||
712 | expect![[r#" | ||
713 | ev Self::Bar () | ||
714 | ev Self::Baz () | ||
715 | ev Self::Quux () | ||
716 | ev Foo::Bar () | ||
717 | ev Foo::Baz () | ||
718 | ev Foo::Quux () | ||
719 | sp Self | ||
720 | en Foo | ||
721 | "#]], | ||
722 | ) | ||
723 | } | ||
724 | |||
725 | #[test] | ||
726 | fn dont_complete_attr() { | 640 | fn dont_complete_attr() { |
727 | check( | 641 | check( |
728 | r#" | 642 | r#" |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 89e9bda78..e6cc6329c 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -350,7 +350,6 @@ impl<'a> CompletionContext<'a> { | |||
350 | }, | 350 | }, |
351 | ast::IdentPat(it) => { | 351 | ast::IdentPat(it) => { |
352 | cov_mark::hit!(expected_type_if_let_with_leading_char); | 352 | cov_mark::hit!(expected_type_if_let_with_leading_char); |
353 | cov_mark::hit!(expected_type_if_let_without_leading_char); | ||
354 | cov_mark::hit!(expected_type_match_arm_with_leading_char); | 353 | cov_mark::hit!(expected_type_match_arm_with_leading_char); |
355 | let ty = self.sema.type_of_pat(&ast::Pat::from(it)); | 354 | let ty = self.sema.type_of_pat(&ast::Pat::from(it)); |
356 | 355 | ||
@@ -748,7 +747,6 @@ fn foo() { | |||
748 | 747 | ||
749 | #[test] | 748 | #[test] |
750 | fn expected_type_if_let_without_leading_char() { | 749 | fn expected_type_if_let_without_leading_char() { |
751 | cov_mark::check!(expected_type_if_let_without_leading_char); | ||
752 | check_expected_type_and_name( | 750 | check_expected_type_and_name( |
753 | r#" | 751 | r#" |
754 | enum Foo { Bar, Baz, Quux } | 752 | enum Foo { Bar, Baz, Quux } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 670563e50..2514dda7c 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -928,6 +928,66 @@ fn f(foo: &Foo) { f(foo, w$0) } | |||
928 | } | 928 | } |
929 | 929 | ||
930 | #[test] | 930 | #[test] |
931 | fn score_fn_type_and_name_match() { | ||
932 | check_relevance( | ||
933 | r#" | ||
934 | struct A { bar: u8 } | ||
935 | fn baz() -> u8 { 0 } | ||
936 | fn bar() -> u8 { 0 } | ||
937 | fn f() { A { bar: b$0 }; } | ||
938 | "#, | ||
939 | expect![[r#" | ||
940 | fn baz() [type] | ||
941 | st A [] | ||
942 | fn bar() [type+name] | ||
943 | fn f() [] | ||
944 | "#]], | ||
945 | ); | ||
946 | } | ||
947 | |||
948 | #[test] | ||
949 | fn score_method_type_and_name_match() { | ||
950 | check_relevance( | ||
951 | r#" | ||
952 | fn baz(aaa: u32){} | ||
953 | struct Foo; | ||
954 | impl Foo { | ||
955 | fn aaa(&self) -> u32 { 0 } | ||
956 | fn bbb(&self) -> u32 { 0 } | ||
957 | fn ccc(&self) -> u64 { 0 } | ||
958 | } | ||
959 | fn f() { | ||
960 | baz(Foo.$0 | ||
961 | } | ||
962 | "#, | ||
963 | expect![[r#" | ||
964 | me aaa() [type+name] | ||
965 | me bbb() [type] | ||
966 | me ccc() [] | ||
967 | "#]], | ||
968 | ); | ||
969 | } | ||
970 | |||
971 | #[test] | ||
972 | fn score_method_name_match_only() { | ||
973 | check_relevance( | ||
974 | r#" | ||
975 | fn baz(aaa: u32){} | ||
976 | struct Foo; | ||
977 | impl Foo { | ||
978 | fn aaa(&self) -> u64 { 0 } | ||
979 | } | ||
980 | fn f() { | ||
981 | baz(Foo.$0 | ||
982 | } | ||
983 | "#, | ||
984 | expect![[r#" | ||
985 | me aaa() [name] | ||
986 | "#]], | ||
987 | ); | ||
988 | } | ||
989 | |||
990 | #[test] | ||
931 | fn suggest_ref_mut() { | 991 | fn suggest_ref_mut() { |
932 | cov_mark::check!(suggest_ref); | 992 | cov_mark::check!(suggest_ref); |
933 | check( | 993 | check( |
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index f4dabe3d1..47e26a5d8 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs | |||
@@ -5,7 +5,7 @@ use ide_db::SymbolKind; | |||
5 | use syntax::ast::Fn; | 5 | use syntax::ast::Fn; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | item::{CompletionItem, CompletionItemKind, CompletionKind, ImportEdit}, | 8 | item::{CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, ImportEdit}, |
9 | render::{builder_ext::Params, RenderContext}, | 9 | render::{builder_ext::Params, RenderContext}, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -55,6 +55,21 @@ impl<'a> FunctionRender<'a> { | |||
55 | .add_call_parens(self.ctx.completion, self.name, params) | 55 | .add_call_parens(self.ctx.completion, self.name, params) |
56 | .add_import(import_to_add); | 56 | .add_import(import_to_add); |
57 | 57 | ||
58 | let mut relevance = CompletionRelevance::default(); | ||
59 | if let Some(expected_type) = &self.ctx.completion.expected_type { | ||
60 | let ret_ty = self.func.ret_type(self.ctx.db()); | ||
61 | |||
62 | // We don't ever consider a function which returns unit type to be an | ||
63 | // exact type match, since nearly always this is not meaningful to the | ||
64 | // user. | ||
65 | relevance.exact_type_match = &ret_ty == expected_type && !ret_ty.is_unit(); | ||
66 | } | ||
67 | if let Some(expected_name) = &self.ctx.completion.expected_name { | ||
68 | relevance.exact_name_match = | ||
69 | expected_name == &self.func.name(self.ctx.db()).to_string(); | ||
70 | } | ||
71 | item.set_relevance(relevance); | ||
72 | |||
58 | item.build() | 73 | item.build() |
59 | } | 74 | } |
60 | 75 | ||
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs index ca2926125..b4e80f424 100644 --- a/crates/ide_completion/src/render/pattern.rs +++ b/crates/ide_completion/src/render/pattern.rs | |||
@@ -6,24 +6,6 @@ use itertools::Itertools; | |||
6 | 6 | ||
7 | use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind}; | 7 | use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind}; |
8 | 8 | ||
9 | fn visible_fields( | ||
10 | ctx: &RenderContext<'_>, | ||
11 | fields: &[hir::Field], | ||
12 | item: impl HasAttrs, | ||
13 | ) -> Option<(Vec<hir::Field>, bool)> { | ||
14 | let module = ctx.completion.scope.module()?; | ||
15 | let n_fields = fields.len(); | ||
16 | let fields = fields | ||
17 | .into_iter() | ||
18 | .filter(|field| field.is_visible_from(ctx.db(), module)) | ||
19 | .copied() | ||
20 | .collect::<Vec<_>>(); | ||
21 | |||
22 | let fields_omitted = | ||
23 | n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists(); | ||
24 | Some((fields, fields_omitted)) | ||
25 | } | ||
26 | |||
27 | pub(crate) fn render_struct_pat( | 9 | pub(crate) fn render_struct_pat( |
28 | ctx: RenderContext<'_>, | 10 | ctx: RenderContext<'_>, |
29 | strukt: hir::Struct, | 11 | strukt: hir::Struct, |
@@ -148,3 +130,21 @@ fn render_tuple_as_pat(fields: &[hir::Field], name: &str, fields_omitted: bool) | |||
148 | name = name | 130 | name = name |
149 | ) | 131 | ) |
150 | } | 132 | } |
133 | |||
134 | fn visible_fields( | ||
135 | ctx: &RenderContext<'_>, | ||
136 | fields: &[hir::Field], | ||
137 | item: impl HasAttrs, | ||
138 | ) -> Option<(Vec<hir::Field>, bool)> { | ||
139 | let module = ctx.completion.scope.module()?; | ||
140 | let n_fields = fields.len(); | ||
141 | let fields = fields | ||
142 | .into_iter() | ||
143 | .filter(|field| field.is_visible_from(ctx.db(), module)) | ||
144 | .copied() | ||
145 | .collect::<Vec<_>>(); | ||
146 | |||
147 | let fields_omitted = | ||
148 | n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists(); | ||
149 | Some((fields, fields_omitted)) | ||
150 | } | ||
diff --git a/crates/ide_db/Cargo.toml b/crates/ide_db/Cargo.toml index 1f7a90d20..6229996ec 100644 --- a/crates/ide_db/Cargo.toml +++ b/crates/ide_db/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | rayon = "1.5.0" | 15 | rayon = "1.5.0" |
16 | fst = { version = "0.4", default-features = false } | 16 | fst = { version = "0.4", default-features = false } |
diff --git a/crates/ide_ssr/Cargo.toml b/crates/ide_ssr/Cargo.toml index 8c31df13a..5d2221ebc 100644 --- a/crates/ide_ssr/Cargo.toml +++ b/crates/ide_ssr/Cargo.toml | |||
@@ -11,7 +11,7 @@ edition = "2018" | |||
11 | doctest = false | 11 | doctest = false |
12 | 12 | ||
13 | [dependencies] | 13 | [dependencies] |
14 | cov-mark = "1.1" | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
15 | rustc-hash = "1.1.0" | 15 | rustc-hash = "1.1.0" |
16 | itertools = "0.10.0" | 16 | itertools = "0.10.0" |
17 | 17 | ||
diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml index 139214207..8856787c0 100644 --- a/crates/mbe/Cargo.toml +++ b/crates/mbe/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | smallvec = "1.2.0" | 15 | smallvec = "1.2.0" |
16 | log = "0.4.8" | 16 | log = "0.4.8" |
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs index 941d0fe9e..2dd2a8541 100644 --- a/crates/proc_macro_api/src/lib.rs +++ b/crates/proc_macro_api/src/lib.rs | |||
@@ -23,6 +23,7 @@ use tt::{SmolStr, Subtree}; | |||
23 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | 23 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; |
24 | 24 | ||
25 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; | 25 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; |
26 | pub use version::{read_dylib_info, RustCInfo}; | ||
26 | 27 | ||
27 | #[derive(Debug, Clone)] | 28 | #[derive(Debug, Clone)] |
28 | struct ProcMacroProcessExpander { | 29 | struct ProcMacroProcessExpander { |
@@ -76,7 +77,7 @@ impl ProcMacroClient { | |||
76 | } | 77 | } |
77 | 78 | ||
78 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> { | 79 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> { |
79 | match version::read_info(dylib_path) { | 80 | match version::read_dylib_info(dylib_path) { |
80 | Ok(info) => { | 81 | Ok(info) => { |
81 | if info.version.0 < 1 || info.version.1 < 47 { | 82 | if info.version.0 < 1 || info.version.1 < 47 { |
82 | eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.to_string_lossy(), info); | 83 | eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.to_string_lossy(), info); |
diff --git a/crates/proc_macro_api/src/version.rs b/crates/proc_macro_api/src/version.rs index b903658fb..dcf8fae8f 100644 --- a/crates/proc_macro_api/src/version.rs +++ b/crates/proc_macro_api/src/version.rs | |||
@@ -11,14 +11,15 @@ use object::read::{File as BinaryFile, Object, ObjectSection}; | |||
11 | use snap::read::FrameDecoder as SnapDecoder; | 11 | use snap::read::FrameDecoder as SnapDecoder; |
12 | 12 | ||
13 | #[derive(Debug)] | 13 | #[derive(Debug)] |
14 | pub(crate) struct RustCInfo { | 14 | pub struct RustCInfo { |
15 | pub(crate) version: (usize, usize, usize), | 15 | pub version: (usize, usize, usize), |
16 | pub(crate) channel: String, | 16 | pub channel: String, |
17 | pub(crate) commit: String, | 17 | pub commit: String, |
18 | pub(crate) date: String, | 18 | pub date: String, |
19 | } | 19 | } |
20 | 20 | ||
21 | pub(crate) fn read_info(dylib_path: &Path) -> io::Result<RustCInfo> { | 21 | /// Read rustc dylib information |
22 | pub fn read_dylib_info(dylib_path: &Path) -> io::Result<RustCInfo> { | ||
22 | macro_rules! err { | 23 | macro_rules! err { |
23 | ($e:literal) => { | 24 | ($e:literal) => { |
24 | io::Error::new(io::ErrorKind::InvalidData, $e) | 25 | io::Error::new(io::ErrorKind::InvalidData, $e) |
diff --git a/crates/proc_macro_srv/src/tests/mod.rs b/crates/proc_macro_srv/src/tests/mod.rs index fd54f8dfd..b4ab4c077 100644 --- a/crates/proc_macro_srv/src/tests/mod.rs +++ b/crates/proc_macro_srv/src/tests/mod.rs | |||
@@ -56,3 +56,10 @@ DummyTrait [CustomDerive]"#, | |||
56 | &res | 56 | &res |
57 | ); | 57 | ); |
58 | } | 58 | } |
59 | |||
60 | #[test] | ||
61 | fn test_version_check() { | ||
62 | let path = fixtures::dylib_path("proc_macro_test", "0.0.0"); | ||
63 | let info = proc_macro_api::read_dylib_info(&path).unwrap(); | ||
64 | assert!(info.version.1 >= 50); | ||
65 | } | ||
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs index 0484c3af4..f15381f0f 100644 --- a/crates/proc_macro_srv/src/tests/utils.rs +++ b/crates/proc_macro_srv/src/tests/utils.rs | |||
@@ -6,7 +6,7 @@ use proc_macro_api::ListMacrosTask; | |||
6 | use std::str::FromStr; | 6 | use std::str::FromStr; |
7 | use test_utils::assert_eq_text; | 7 | use test_utils::assert_eq_text; |
8 | 8 | ||
9 | mod fixtures { | 9 | pub mod fixtures { |
10 | use cargo_metadata::Message; | 10 | use cargo_metadata::Message; |
11 | use std::path::PathBuf; | 11 | use std::path::PathBuf; |
12 | use std::process::Command; | 12 | use std::process::Command; |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8af7871ac..8f541976e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -172,7 +172,7 @@ config_data! { | |||
172 | notifications_cargoTomlNotFound: bool = "true", | 172 | notifications_cargoTomlNotFound: bool = "true", |
173 | 173 | ||
174 | /// Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`. | 174 | /// Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`. |
175 | procMacro_enable: bool = "false", | 175 | procMacro_enable: bool = "true", |
176 | /// Internal config, path to proc-macro server executable (typically, | 176 | /// Internal config, path to proc-macro server executable (typically, |
177 | /// this is rust-analyzer itself, but we override this in tests). | 177 | /// this is rust-analyzer itself, but we override this in tests). |
178 | procMacro_server: Option<PathBuf> = "null", | 178 | procMacro_server: Option<PathBuf> = "null", |
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 05fca5dc4..c0fd894b0 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -11,7 +11,7 @@ edition = "2018" | |||
11 | doctest = false | 11 | doctest = false |
12 | 12 | ||
13 | [dependencies] | 13 | [dependencies] |
14 | cov-mark = "1.1" | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
15 | itertools = "0.10.0" | 15 | itertools = "0.10.0" |
16 | rowan = "0.12.2" | 16 | rowan = "0.12.2" |
17 | rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } | 17 | rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" } |
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 042ba2d54..c2521289c 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc | |||
@@ -276,7 +276,7 @@ Number of syntax trees rust-analyzer keeps in memory. Defaults to 128. | |||
276 | -- | 276 | -- |
277 | Whether to show `can't find Cargo.toml` error message. | 277 | Whether to show `can't find Cargo.toml` error message. |
278 | -- | 278 | -- |
279 | [[rust-analyzer.procMacro.enable]]rust-analyzer.procMacro.enable (default: `false`):: | 279 | [[rust-analyzer.procMacro.enable]]rust-analyzer.procMacro.enable (default: `true`):: |
280 | + | 280 | + |
281 | -- | 281 | -- |
282 | Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`. | 282 | Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`. |
diff --git a/editors/code/package.json b/editors/code/package.json index 923e9b35a..a2ed9b2d5 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -690,7 +690,7 @@ | |||
690 | }, | 690 | }, |
691 | "rust-analyzer.procMacro.enable": { | 691 | "rust-analyzer.procMacro.enable": { |
692 | "markdownDescription": "Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`.", | 692 | "markdownDescription": "Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`.", |
693 | "default": false, | 693 | "default": true, |
694 | "type": "boolean" | 694 | "type": "boolean" |
695 | }, | 695 | }, |
696 | "rust-analyzer.procMacro.server": { | 696 | "rust-analyzer.procMacro.server": { |
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 72de92c64..3d8d7589b 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs | |||
@@ -26,7 +26,7 @@ impl flags::Metrics { | |||
26 | } | 26 | } |
27 | { | 27 | { |
28 | let _d = pushd("./target/rustc-perf")?; | 28 | let _d = pushd("./target/rustc-perf")?; |
29 | cmd!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033").run()?; | 29 | cmd!("git reset --hard c52ee623e231e7690a93be88d943016968c1036b").run()?; |
30 | } | 30 | } |
31 | 31 | ||
32 | let _env = pushenv("RA_METRICS", "1"); | 32 | let _env = pushenv("RA_METRICS", "1"); |
@@ -35,6 +35,7 @@ impl flags::Metrics { | |||
35 | metrics.measure_analysis_stats_self()?; | 35 | metrics.measure_analysis_stats_self()?; |
36 | metrics.measure_analysis_stats("ripgrep")?; | 36 | metrics.measure_analysis_stats("ripgrep")?; |
37 | metrics.measure_analysis_stats("webrender")?; | 37 | metrics.measure_analysis_stats("webrender")?; |
38 | metrics.measure_analysis_stats("diesel/diesel")?; | ||
38 | 39 | ||
39 | if !self.dry_run { | 40 | if !self.dry_run { |
40 | let _d = pushd("target")?; | 41 | let _d = pushd("target")?; |