diff options
author | Seivan Heidari <[email protected]> | 2019-11-15 15:30:21 +0000 |
---|---|---|
committer | Seivan Heidari <[email protected]> | 2019-11-15 15:30:21 +0000 |
commit | cb26df950699586b314731fb70786e0db8eaa049 (patch) | |
tree | 29a1fd853757824572bfebc956d20458d827926f | |
parent | c622413bc72ea56d5f62a16788d897cb61eca948 (diff) | |
parent | c6f05abfbbfa2fd1ff06e1adeea7885151aaa768 (diff) |
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
40 files changed, 2620 insertions, 2136 deletions
diff --git a/.gitattributes b/.gitattributes index 183e9b521..e749e1dc9 100644 --- a/.gitattributes +++ b/.gitattributes | |||
@@ -1,2 +1,2 @@ | |||
1 | * text=auto eol=lf | ||
1 | crates/ra_syntax/test_data/** -text eof=LF | 2 | crates/ra_syntax/test_data/** -text eof=LF |
2 | crates/ra_ide_api/src/snapshots/** -text eof=LF | ||
diff --git a/Cargo.lock b/Cargo.lock index 1dedf9772..d7ec266c0 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1135,7 +1135,7 @@ dependencies = [ | |||
1135 | "ra_syntax 0.1.0", | 1135 | "ra_syntax 0.1.0", |
1136 | "ra_tt 0.1.0", | 1136 | "ra_tt 0.1.0", |
1137 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1137 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1138 | "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", | 1138 | "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1139 | "test_utils 0.1.0", | 1139 | "test_utils 0.1.0", |
1140 | ] | 1140 | ] |
1141 | 1141 | ||
@@ -1604,6 +1604,11 @@ dependencies = [ | |||
1604 | ] | 1604 | ] |
1605 | 1605 | ||
1606 | [[package]] | 1606 | [[package]] |
1607 | name = "smallvec" | ||
1608 | version = "1.0.0" | ||
1609 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1610 | |||
1611 | [[package]] | ||
1607 | name = "smol_str" | 1612 | name = "smol_str" |
1608 | version = "0.1.15" | 1613 | version = "0.1.15" |
1609 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2007,6 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
2007 | "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" | 2012 | "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" |
2008 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | 2013 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" |
2009 | "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" | 2014 | "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" |
2015 | "checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" | ||
2010 | "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" | 2016 | "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" |
2011 | "checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" | 2017 | "checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" |
2012 | "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" | 2018 | "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" |
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs new file mode 100644 index 000000000..a8839cfba --- /dev/null +++ b/crates/ra_assists/src/assists/add_new.rs | |||
@@ -0,0 +1,379 @@ | |||
1 | use format_buf::format; | ||
2 | use hir::{db::HirDatabase, FromSource}; | ||
3 | use join_to_string::join; | ||
4 | use ra_syntax::{ | ||
5 | ast::{ | ||
6 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, | ||
7 | }, | ||
8 | TextUnit, T, | ||
9 | }; | ||
10 | use std::fmt::Write; | ||
11 | |||
12 | use crate::{Assist, AssistCtx, AssistId}; | ||
13 | |||
14 | // Assist: add_new | ||
15 | // | ||
16 | // Adds a new inherent impl for a type. | ||
17 | // | ||
18 | // ``` | ||
19 | // struct Ctx<T: Clone> { | ||
20 | // data: T,<|> | ||
21 | // } | ||
22 | // ``` | ||
23 | // -> | ||
24 | // ``` | ||
25 | // struct Ctx<T: Clone> { | ||
26 | // data: T, | ||
27 | // } | ||
28 | // | ||
29 | // impl<T: Clone> Ctx<T> { | ||
30 | // fn new(data: T) -> Self { Self { data } } | ||
31 | // } | ||
32 | // | ||
33 | // ``` | ||
34 | pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
35 | let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; | ||
36 | |||
37 | // We want to only apply this to non-union structs with named fields | ||
38 | let field_list = match (strukt.kind(), strukt.is_union()) { | ||
39 | (StructKind::Named(named), false) => named, | ||
40 | _ => return None, | ||
41 | }; | ||
42 | |||
43 | // Return early if we've found an existing new fn | ||
44 | let impl_block = find_struct_impl(&ctx, &strukt)?; | ||
45 | |||
46 | ctx.add_assist(AssistId("add_new"), "add new fn", |edit| { | ||
47 | edit.target(strukt.syntax().text_range()); | ||
48 | |||
49 | let mut buf = String::with_capacity(512); | ||
50 | |||
51 | if impl_block.is_some() { | ||
52 | buf.push('\n'); | ||
53 | } | ||
54 | |||
55 | let vis = strukt.visibility().map(|v| format!("{} ", v.syntax())); | ||
56 | let vis = vis.as_ref().map(String::as_str).unwrap_or(""); | ||
57 | write!(&mut buf, " {}fn new(", vis).unwrap(); | ||
58 | |||
59 | join(field_list.fields().map(|f| { | ||
60 | format!( | ||
61 | "{}: {}", | ||
62 | f.name().unwrap().syntax().text(), | ||
63 | f.ascribed_type().unwrap().syntax().text() | ||
64 | ) | ||
65 | })) | ||
66 | .separator(", ") | ||
67 | .to_buf(&mut buf); | ||
68 | |||
69 | buf.push_str(") -> Self { Self {"); | ||
70 | |||
71 | join(field_list.fields().map(|f| f.name().unwrap().syntax().text())) | ||
72 | .separator(", ") | ||
73 | .surround_with(" ", " ") | ||
74 | .to_buf(&mut buf); | ||
75 | |||
76 | buf.push_str("} }"); | ||
77 | |||
78 | let (start_offset, end_offset) = if let Some(impl_block) = impl_block { | ||
79 | buf.push('\n'); | ||
80 | let start = impl_block | ||
81 | .syntax() | ||
82 | .descendants_with_tokens() | ||
83 | .find(|t| t.kind() == T!['{']) | ||
84 | .unwrap() | ||
85 | .text_range() | ||
86 | .end(); | ||
87 | |||
88 | (start, TextUnit::from_usize(1)) | ||
89 | } else { | ||
90 | buf = generate_impl_text(&strukt, &buf); | ||
91 | let start = strukt.syntax().text_range().end(); | ||
92 | |||
93 | (start, TextUnit::from_usize(3)) | ||
94 | }; | ||
95 | |||
96 | edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); | ||
97 | edit.insert(start_offset, buf); | ||
98 | }) | ||
99 | } | ||
100 | |||
101 | // Generates the surrounding `impl Type { <code> }` including type and lifetime | ||
102 | // parameters | ||
103 | fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { | ||
104 | let type_params = strukt.type_param_list(); | ||
105 | let mut buf = String::with_capacity(code.len()); | ||
106 | buf.push_str("\n\nimpl"); | ||
107 | if let Some(type_params) = &type_params { | ||
108 | format!(buf, "{}", type_params.syntax()); | ||
109 | } | ||
110 | buf.push_str(" "); | ||
111 | buf.push_str(strukt.name().unwrap().text().as_str()); | ||
112 | if let Some(type_params) = type_params { | ||
113 | let lifetime_params = type_params | ||
114 | .lifetime_params() | ||
115 | .filter_map(|it| it.lifetime_token()) | ||
116 | .map(|it| it.text().clone()); | ||
117 | let type_params = | ||
118 | type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); | ||
119 | join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf); | ||
120 | } | ||
121 | |||
122 | format!(&mut buf, " {{\n{}\n}}\n", code); | ||
123 | |||
124 | buf | ||
125 | } | ||
126 | |||
127 | // Uses a syntax-driven approach to find any impl blocks for the struct that | ||
128 | // exist within the module/file | ||
129 | // | ||
130 | // Returns `None` if we've found an existing `new` fn | ||
131 | // | ||
132 | // FIXME: change the new fn checking to a more semantic approach when that's more | ||
133 | // viable (e.g. we process proc macros, etc) | ||
134 | fn find_struct_impl( | ||
135 | ctx: &AssistCtx<impl HirDatabase>, | ||
136 | strukt: &ast::StructDef, | ||
137 | ) -> Option<Option<ast::ImplBlock>> { | ||
138 | let db = ctx.db; | ||
139 | let module = strukt.syntax().ancestors().find(|node| { | ||
140 | ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) | ||
141 | })?; | ||
142 | |||
143 | let struct_ty = { | ||
144 | let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: strukt.clone() }; | ||
145 | hir::Struct::from_source(db, src).unwrap().ty(db) | ||
146 | }; | ||
147 | |||
148 | let mut found_new_fn = false; | ||
149 | |||
150 | let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| { | ||
151 | if found_new_fn { | ||
152 | return false; | ||
153 | } | ||
154 | |||
155 | let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: impl_blk.clone() }; | ||
156 | let blk = hir::ImplBlock::from_source(db, src).unwrap(); | ||
157 | |||
158 | let same_ty = blk.target_ty(db) == struct_ty; | ||
159 | let not_trait_impl = blk.target_trait(db).is_none(); | ||
160 | |||
161 | found_new_fn = has_new_fn(impl_blk); | ||
162 | |||
163 | same_ty && not_trait_impl | ||
164 | }); | ||
165 | |||
166 | if found_new_fn { | ||
167 | None | ||
168 | } else { | ||
169 | Some(block) | ||
170 | } | ||
171 | } | ||
172 | |||
173 | fn has_new_fn(imp: &ast::ImplBlock) -> bool { | ||
174 | if let Some(il) = imp.item_list() { | ||
175 | for item in il.impl_items() { | ||
176 | if let ast::ImplItem::FnDef(f) = item { | ||
177 | if f.name().unwrap().text().eq_ignore_ascii_case("new") { | ||
178 | return true; | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | false | ||
185 | } | ||
186 | |||
187 | #[cfg(test)] | ||
188 | mod tests { | ||
189 | use super::*; | ||
190 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
191 | |||
192 | #[test] | ||
193 | #[rustfmt::skip] | ||
194 | fn test_add_new() { | ||
195 | // Check output of generation | ||
196 | check_assist( | ||
197 | add_new, | ||
198 | "struct Foo {<|>}", | ||
199 | "struct Foo {} | ||
200 | |||
201 | impl Foo { | ||
202 | fn new() -> Self { Self { } }<|> | ||
203 | } | ||
204 | ", | ||
205 | ); | ||
206 | check_assist( | ||
207 | add_new, | ||
208 | "struct Foo<T: Clone> {<|>}", | ||
209 | "struct Foo<T: Clone> {} | ||
210 | |||
211 | impl<T: Clone> Foo<T> { | ||
212 | fn new() -> Self { Self { } }<|> | ||
213 | } | ||
214 | ", | ||
215 | ); | ||
216 | check_assist( | ||
217 | add_new, | ||
218 | "struct Foo<'a, T: Foo<'a>> {<|>}", | ||
219 | "struct Foo<'a, T: Foo<'a>> {} | ||
220 | |||
221 | impl<'a, T: Foo<'a>> Foo<'a, T> { | ||
222 | fn new() -> Self { Self { } }<|> | ||
223 | } | ||
224 | ", | ||
225 | ); | ||
226 | check_assist( | ||
227 | add_new, | ||
228 | "struct Foo { baz: String <|>}", | ||
229 | "struct Foo { baz: String } | ||
230 | |||
231 | impl Foo { | ||
232 | fn new(baz: String) -> Self { Self { baz } }<|> | ||
233 | } | ||
234 | ", | ||
235 | ); | ||
236 | check_assist( | ||
237 | add_new, | ||
238 | "struct Foo { baz: String, qux: Vec<i32> <|>}", | ||
239 | "struct Foo { baz: String, qux: Vec<i32> } | ||
240 | |||
241 | impl Foo { | ||
242 | fn new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }<|> | ||
243 | } | ||
244 | ", | ||
245 | ); | ||
246 | |||
247 | // Check that visibility modifiers don't get brought in for fields | ||
248 | check_assist( | ||
249 | add_new, | ||
250 | "struct Foo { pub baz: String, pub qux: Vec<i32> <|>}", | ||
251 | "struct Foo { pub baz: String, pub qux: Vec<i32> } | ||
252 | |||
253 | impl Foo { | ||
254 | fn new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }<|> | ||
255 | } | ||
256 | ", | ||
257 | ); | ||
258 | |||
259 | // Check that it reuses existing impls | ||
260 | check_assist( | ||
261 | add_new, | ||
262 | "struct Foo {<|>} | ||
263 | |||
264 | impl Foo {} | ||
265 | ", | ||
266 | "struct Foo {} | ||
267 | |||
268 | impl Foo { | ||
269 | fn new() -> Self { Self { } }<|> | ||
270 | } | ||
271 | ", | ||
272 | ); | ||
273 | check_assist( | ||
274 | add_new, | ||
275 | "struct Foo {<|>} | ||
276 | |||
277 | impl Foo { | ||
278 | fn qux(&self) {} | ||
279 | } | ||
280 | ", | ||
281 | "struct Foo {} | ||
282 | |||
283 | impl Foo { | ||
284 | fn new() -> Self { Self { } }<|> | ||
285 | |||
286 | fn qux(&self) {} | ||
287 | } | ||
288 | ", | ||
289 | ); | ||
290 | |||
291 | check_assist( | ||
292 | add_new, | ||
293 | "struct Foo {<|>} | ||
294 | |||
295 | impl Foo { | ||
296 | fn qux(&self) {} | ||
297 | fn baz() -> i32 { | ||
298 | 5 | ||
299 | } | ||
300 | } | ||
301 | ", | ||
302 | "struct Foo {} | ||
303 | |||
304 | impl Foo { | ||
305 | fn new() -> Self { Self { } }<|> | ||
306 | |||
307 | fn qux(&self) {} | ||
308 | fn baz() -> i32 { | ||
309 | 5 | ||
310 | } | ||
311 | } | ||
312 | ", | ||
313 | ); | ||
314 | |||
315 | // Check visibility of new fn based on struct | ||
316 | check_assist( | ||
317 | add_new, | ||
318 | "pub struct Foo {<|>}", | ||
319 | "pub struct Foo {} | ||
320 | |||
321 | impl Foo { | ||
322 | pub fn new() -> Self { Self { } }<|> | ||
323 | } | ||
324 | ", | ||
325 | ); | ||
326 | check_assist( | ||
327 | add_new, | ||
328 | "pub(crate) struct Foo {<|>}", | ||
329 | "pub(crate) struct Foo {} | ||
330 | |||
331 | impl Foo { | ||
332 | pub(crate) fn new() -> Self { Self { } }<|> | ||
333 | } | ||
334 | ", | ||
335 | ); | ||
336 | } | ||
337 | |||
338 | #[test] | ||
339 | fn add_new_not_applicable_if_fn_exists() { | ||
340 | check_assist_not_applicable( | ||
341 | add_new, | ||
342 | " | ||
343 | struct Foo {<|>} | ||
344 | |||
345 | impl Foo { | ||
346 | fn new() -> Self { | ||
347 | Self | ||
348 | } | ||
349 | }", | ||
350 | ); | ||
351 | |||
352 | check_assist_not_applicable( | ||
353 | add_new, | ||
354 | " | ||
355 | struct Foo {<|>} | ||
356 | |||
357 | impl Foo { | ||
358 | fn New() -> Self { | ||
359 | Self | ||
360 | } | ||
361 | }", | ||
362 | ); | ||
363 | } | ||
364 | |||
365 | #[test] | ||
366 | fn add_new_target() { | ||
367 | check_assist_target( | ||
368 | add_new, | ||
369 | " | ||
370 | struct SomeThingIrrelevant; | ||
371 | /// Has a lifetime parameter | ||
372 | struct Foo<'a, T: Foo<'a>> {<|>} | ||
373 | struct EvenMoreIrrelevant; | ||
374 | ", | ||
375 | "/// Has a lifetime parameter | ||
376 | struct Foo<'a, T: Foo<'a>> {}", | ||
377 | ); | ||
378 | } | ||
379 | } | ||
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 1bee76f59..176761efb 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -157,6 +157,28 @@ fn process(map: HashMap<String, String>) {} | |||
157 | } | 157 | } |
158 | 158 | ||
159 | #[test] | 159 | #[test] |
160 | fn doctest_add_new() { | ||
161 | check( | ||
162 | "add_new", | ||
163 | r#####" | ||
164 | struct Ctx<T: Clone> { | ||
165 | data: T,<|> | ||
166 | } | ||
167 | "#####, | ||
168 | r#####" | ||
169 | struct Ctx<T: Clone> { | ||
170 | data: T, | ||
171 | } | ||
172 | |||
173 | impl<T: Clone> Ctx<T> { | ||
174 | fn new(data: T) -> Self { Self { data } } | ||
175 | } | ||
176 | |||
177 | "#####, | ||
178 | ) | ||
179 | } | ||
180 | |||
181 | #[test] | ||
160 | fn doctest_apply_demorgan() { | 182 | fn doctest_apply_demorgan() { |
161 | check( | 183 | check( |
162 | "apply_demorgan", | 184 | "apply_demorgan", |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 39c1c283f..f2f0dacbf 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -95,6 +95,7 @@ mod assists { | |||
95 | mod add_derive; | 95 | mod add_derive; |
96 | mod add_explicit_type; | 96 | mod add_explicit_type; |
97 | mod add_impl; | 97 | mod add_impl; |
98 | mod add_new; | ||
98 | mod apply_demorgan; | 99 | mod apply_demorgan; |
99 | mod flip_comma; | 100 | mod flip_comma; |
100 | mod flip_binexpr; | 101 | mod flip_binexpr; |
@@ -119,6 +120,7 @@ mod assists { | |||
119 | add_derive::add_derive, | 120 | add_derive::add_derive, |
120 | add_explicit_type::add_explicit_type, | 121 | add_explicit_type::add_explicit_type, |
121 | add_impl::add_impl, | 122 | add_impl::add_impl, |
123 | add_new::add_new, | ||
122 | apply_demorgan::apply_demorgan, | 124 | apply_demorgan::apply_demorgan, |
123 | change_visibility::change_visibility, | 125 | change_visibility::change_visibility, |
124 | fill_match_arms::fill_match_arms, | 126 | fill_match_arms::fill_match_arms, |
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index ee883b615..ade187629 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -8,8 +8,8 @@ use rustc_hash::FxHashMap; | |||
8 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | 8 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | CrateGraph, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, SourceRoot, | 11 | CrateGraph, CrateId, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, |
12 | SourceRootId, | 12 | SourceRoot, SourceRootId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 15 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
@@ -33,6 +33,14 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
33 | let pos = with_files(&mut db, fixture); | 33 | let pos = with_files(&mut db, fixture); |
34 | (db, pos.unwrap()) | 34 | (db, pos.unwrap()) |
35 | } | 35 | } |
36 | |||
37 | fn test_crate(&self) -> CrateId { | ||
38 | let crate_graph = self.crate_graph(); | ||
39 | let mut it = crate_graph.iter(); | ||
40 | let res = it.next().unwrap(); | ||
41 | assert!(it.next().is_none()); | ||
42 | res | ||
43 | } | ||
36 | } | 44 | } |
37 | 45 | ||
38 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} | 46 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 962d5a8c1..078bd8609 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -23,7 +23,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | |||
23 | use crate::{ | 23 | use crate::{ |
24 | adt::VariantDef, | 24 | adt::VariantDef, |
25 | db::{AstDatabase, DefDatabase, HirDatabase}, | 25 | db::{AstDatabase, DefDatabase, HirDatabase}, |
26 | expr::{validation::ExprValidator, BindingAnnotation, Body, BodySourceMap, Pat, PatId}, | 26 | expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, |
27 | generics::{GenericDef, HasGenericParams}, | 27 | generics::{GenericDef, HasGenericParams}, |
28 | ids::{ | 28 | ids::{ |
29 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, | 29 | AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, |
@@ -157,7 +157,7 @@ impl Module { | |||
157 | } | 157 | } |
158 | 158 | ||
159 | /// Finds a child module with the specified name. | 159 | /// Finds a child module with the specified name. |
160 | pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> { | 160 | pub fn child(self, db: &impl DefDatabase, name: &Name) -> Option<Module> { |
161 | let def_map = db.crate_def_map(self.id.krate); | 161 | let def_map = db.crate_def_map(self.id.krate); |
162 | let child_id = def_map[self.id.module_id].children.get(name)?; | 162 | let child_id = def_map[self.id.module_id].children.get(name)?; |
163 | Some(self.with_module_id(*child_id)) | 163 | Some(self.with_module_id(*child_id)) |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 9262325f2..e3733779e 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -1,12 +1,19 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub(crate) mod validation; | ||
4 | |||
5 | use std::sync::Arc; | 3 | use std::sync::Arc; |
6 | 4 | ||
5 | use hir_def::path::known; | ||
6 | use hir_expand::diagnostics::DiagnosticSink; | ||
7 | use ra_syntax::ast; | ||
7 | use ra_syntax::AstPtr; | 8 | use ra_syntax::AstPtr; |
9 | use rustc_hash::FxHashSet; | ||
8 | 10 | ||
9 | use crate::{db::HirDatabase, DefWithBody, HasBody, Resolver}; | 11 | use crate::{ |
12 | db::HirDatabase, | ||
13 | diagnostics::{MissingFields, MissingOkInTailExpr}, | ||
14 | ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, | ||
15 | Adt, DefWithBody, Function, HasBody, Name, Path, Resolver, | ||
16 | }; | ||
10 | 17 | ||
11 | pub use hir_def::{ | 18 | pub use hir_def::{ |
12 | body::{ | 19 | body::{ |
@@ -38,196 +45,126 @@ pub(crate) fn resolver_for_scope( | |||
38 | let scopes = owner.expr_scopes(db); | 45 | let scopes = owner.expr_scopes(db); |
39 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); | 46 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); |
40 | for scope in scope_chain.into_iter().rev() { | 47 | for scope in scope_chain.into_iter().rev() { |
41 | r = r.push_expr_scope(Arc::clone(&scopes), scope); | 48 | r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); |
42 | } | 49 | } |
43 | r | 50 | r |
44 | } | 51 | } |
45 | 52 | ||
46 | #[cfg(test)] | 53 | pub(crate) struct ExprValidator<'a, 'b: 'a> { |
47 | mod tests { | 54 | func: Function, |
48 | use hir_expand::Source; | 55 | infer: Arc<InferenceResult>, |
49 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 56 | sink: &'a mut DiagnosticSink<'b>, |
50 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 57 | } |
51 | use test_utils::{assert_eq_text, extract_offset}; | ||
52 | |||
53 | use crate::{source_binder::SourceAnalyzer, test_db::TestDB}; | ||
54 | |||
55 | fn do_check(code: &str, expected: &[&str]) { | ||
56 | let (off, code) = extract_offset(code); | ||
57 | let code = { | ||
58 | let mut buf = String::new(); | ||
59 | let off = u32::from(off) as usize; | ||
60 | buf.push_str(&code[..off]); | ||
61 | buf.push_str("marker"); | ||
62 | buf.push_str(&code[off..]); | ||
63 | buf | ||
64 | }; | ||
65 | 58 | ||
66 | let (db, file_id) = TestDB::with_single_file(&code); | 59 | impl<'a, 'b> ExprValidator<'a, 'b> { |
67 | 60 | pub(crate) fn new( | |
68 | let file = db.parse(file_id).ok().unwrap(); | 61 | func: Function, |
69 | let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); | 62 | infer: Arc<InferenceResult>, |
70 | let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); | 63 | sink: &'a mut DiagnosticSink<'b>, |
71 | 64 | ) -> ExprValidator<'a, 'b> { | |
72 | let scopes = analyzer.scopes(); | 65 | ExprValidator { func, infer, sink } |
73 | let expr_id = analyzer | ||
74 | .body_source_map() | ||
75 | .node_expr(Source { file_id: file_id.into(), ast: &marker.into() }) | ||
76 | .unwrap(); | ||
77 | let scope = scopes.scope_for(expr_id); | ||
78 | |||
79 | let actual = scopes | ||
80 | .scope_chain(scope) | ||
81 | .flat_map(|scope| scopes.entries(scope)) | ||
82 | .map(|it| it.name().to_string()) | ||
83 | .collect::<Vec<_>>() | ||
84 | .join("\n"); | ||
85 | let expected = expected.join("\n"); | ||
86 | assert_eq_text!(&expected, &actual); | ||
87 | } | 66 | } |
88 | 67 | ||
89 | #[test] | 68 | pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { |
90 | fn test_lambda_scope() { | 69 | let body = self.func.body(db); |
91 | do_check( | ||
92 | r" | ||
93 | fn quux(foo: i32) { | ||
94 | let f = |bar, baz: i32| { | ||
95 | <|> | ||
96 | }; | ||
97 | }", | ||
98 | &["bar", "baz", "foo"], | ||
99 | ); | ||
100 | } | ||
101 | 70 | ||
102 | #[test] | 71 | for e in body.exprs() { |
103 | fn test_call_scope() { | 72 | if let (id, Expr::RecordLit { path, fields, spread }) = e { |
104 | do_check( | 73 | self.validate_record_literal(id, path, fields, *spread, db); |
105 | r" | 74 | } |
106 | fn quux() { | 75 | } |
107 | f(|x| <|> ); | ||
108 | }", | ||
109 | &["x"], | ||
110 | ); | ||
111 | } | ||
112 | 76 | ||
113 | #[test] | 77 | let body_expr = &body[body.body_expr()]; |
114 | fn test_method_call_scope() { | 78 | if let Expr::Block { statements: _, tail: Some(t) } = body_expr { |
115 | do_check( | 79 | self.validate_results_in_tail_expr(body.body_expr(), *t, db); |
116 | r" | 80 | } |
117 | fn quux() { | ||
118 | z.f(|x| <|> ); | ||
119 | }", | ||
120 | &["x"], | ||
121 | ); | ||
122 | } | 81 | } |
123 | 82 | ||
124 | #[test] | 83 | fn validate_record_literal( |
125 | fn test_loop_scope() { | 84 | &mut self, |
126 | do_check( | 85 | id: ExprId, |
127 | r" | 86 | _path: &Option<Path>, |
128 | fn quux() { | 87 | fields: &[RecordLitField], |
129 | loop { | 88 | spread: Option<ExprId>, |
130 | let x = (); | 89 | db: &impl HirDatabase, |
131 | <|> | 90 | ) { |
132 | }; | 91 | if spread.is_some() { |
133 | }", | 92 | return; |
134 | &["x"], | 93 | } |
135 | ); | 94 | |
136 | } | 95 | let struct_def = match self.infer[id].as_adt() { |
96 | Some((Adt::Struct(s), _)) => s, | ||
97 | _ => return, | ||
98 | }; | ||
137 | 99 | ||
138 | #[test] | 100 | let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); |
139 | fn test_match() { | 101 | let missed_fields: Vec<Name> = struct_def |
140 | do_check( | 102 | .fields(db) |
141 | r" | 103 | .iter() |
142 | fn quux() { | 104 | .filter_map(|f| { |
143 | match () { | 105 | let name = f.name(db); |
144 | Some(x) => { | 106 | if lit_fields.contains(&name) { |
145 | <|> | 107 | None |
108 | } else { | ||
109 | Some(name) | ||
110 | } | ||
111 | }) | ||
112 | .collect(); | ||
113 | if missed_fields.is_empty() { | ||
114 | return; | ||
115 | } | ||
116 | let source_map = self.func.body_source_map(db); | ||
117 | |||
118 | if let Some(source_ptr) = source_map.expr_syntax(id) { | ||
119 | if let Some(expr) = source_ptr.ast.a() { | ||
120 | let root = source_ptr.file_syntax(db); | ||
121 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | ||
122 | if let Some(field_list) = record_lit.record_field_list() { | ||
123 | self.sink.push(MissingFields { | ||
124 | file: source_ptr.file_id, | ||
125 | field_list: AstPtr::new(&field_list), | ||
126 | missed_fields, | ||
127 | }) | ||
146 | } | 128 | } |
147 | }; | 129 | } |
148 | }", | 130 | } |
149 | &["x"], | 131 | } |
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn test_shadow_variable() { | ||
155 | do_check( | ||
156 | r" | ||
157 | fn foo(x: String) { | ||
158 | let x : &str = &x<|>; | ||
159 | }", | ||
160 | &["x"], | ||
161 | ); | ||
162 | } | 132 | } |
163 | 133 | ||
164 | fn do_check_local_name(code: &str, expected_offset: u32) { | 134 | fn validate_results_in_tail_expr( |
165 | let (off, code) = extract_offset(code); | 135 | &mut self, |
166 | 136 | body_id: ExprId, | |
167 | let (db, file_id) = TestDB::with_single_file(&code); | 137 | id: ExprId, |
168 | let file = db.parse(file_id).ok().unwrap(); | 138 | db: &impl HirDatabase, |
169 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) | 139 | ) { |
170 | .expect("failed to find a name at the target offset"); | 140 | // the mismatch will be on the whole block currently |
171 | let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | 141 | let mismatch = match self.infer.type_mismatch_for_expr(body_id) { |
172 | let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); | 142 | Some(m) => m, |
143 | None => return, | ||
144 | }; | ||
173 | 145 | ||
174 | let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap(); | 146 | let std_result_path = known::std_result_result(); |
175 | let local_name = | ||
176 | local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); | ||
177 | assert_eq!(local_name.range(), expected_name.syntax().text_range()); | ||
178 | } | ||
179 | 147 | ||
180 | #[test] | 148 | let resolver = self.func.resolver(db); |
181 | fn test_resolve_local_name() { | 149 | let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { |
182 | do_check_local_name( | 150 | Some(it) => it, |
183 | r#" | 151 | _ => return, |
184 | fn foo(x: i32, y: u32) { | 152 | }; |
185 | { | ||
186 | let z = x * 2; | ||
187 | } | ||
188 | { | ||
189 | let t = x<|> * 3; | ||
190 | } | ||
191 | }"#, | ||
192 | 21, | ||
193 | ); | ||
194 | } | ||
195 | 153 | ||
196 | #[test] | 154 | let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum)); |
197 | fn test_resolve_local_name_declaration() { | 155 | let params = match &mismatch.expected { |
198 | do_check_local_name( | 156 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, |
199 | r#" | 157 | _ => return, |
200 | fn foo(x: String) { | 158 | }; |
201 | let x : &str = &x<|>; | ||
202 | }"#, | ||
203 | 21, | ||
204 | ); | ||
205 | } | ||
206 | 159 | ||
207 | #[test] | 160 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { |
208 | fn test_resolve_local_name_shadow() { | 161 | let source_map = self.func.body_source_map(db); |
209 | do_check_local_name( | ||
210 | r" | ||
211 | fn foo(x: String) { | ||
212 | let x : &str = &x; | ||
213 | x<|> | ||
214 | } | ||
215 | ", | ||
216 | 53, | ||
217 | ); | ||
218 | } | ||
219 | 162 | ||
220 | #[test] | 163 | if let Some(source_ptr) = source_map.expr_syntax(id) { |
221 | fn ref_patterns_contribute_bindings() { | 164 | if let Some(expr) = source_ptr.ast.a() { |
222 | do_check_local_name( | 165 | self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); |
223 | r" | ||
224 | fn foo() { | ||
225 | if let Some(&from) = bar() { | ||
226 | from<|>; | ||
227 | } | 166 | } |
228 | } | 167 | } |
229 | ", | 168 | } |
230 | 53, | ||
231 | ); | ||
232 | } | 169 | } |
233 | } | 170 | } |
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs deleted file mode 100644 index 3054f1dce..000000000 --- a/crates/ra_hir/src/expr/validation.rs +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_def::path::known; | ||
6 | use hir_expand::diagnostics::DiagnosticSink; | ||
7 | use ra_syntax::ast; | ||
8 | use rustc_hash::FxHashSet; | ||
9 | |||
10 | use crate::{ | ||
11 | db::HirDatabase, | ||
12 | diagnostics::{MissingFields, MissingOkInTailExpr}, | ||
13 | expr::AstPtr, | ||
14 | ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, | ||
15 | Adt, Function, Name, Path, | ||
16 | }; | ||
17 | |||
18 | use super::{Expr, ExprId, RecordLitField}; | ||
19 | |||
20 | pub(crate) struct ExprValidator<'a, 'b: 'a> { | ||
21 | func: Function, | ||
22 | infer: Arc<InferenceResult>, | ||
23 | sink: &'a mut DiagnosticSink<'b>, | ||
24 | } | ||
25 | |||
26 | impl<'a, 'b> ExprValidator<'a, 'b> { | ||
27 | pub(crate) fn new( | ||
28 | func: Function, | ||
29 | infer: Arc<InferenceResult>, | ||
30 | sink: &'a mut DiagnosticSink<'b>, | ||
31 | ) -> ExprValidator<'a, 'b> { | ||
32 | ExprValidator { func, infer, sink } | ||
33 | } | ||
34 | |||
35 | pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { | ||
36 | let body = self.func.body(db); | ||
37 | |||
38 | for e in body.exprs() { | ||
39 | if let (id, Expr::RecordLit { path, fields, spread }) = e { | ||
40 | self.validate_record_literal(id, path, fields, *spread, db); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | let body_expr = &body[body.body_expr()]; | ||
45 | if let Expr::Block { statements: _, tail: Some(t) } = body_expr { | ||
46 | self.validate_results_in_tail_expr(body.body_expr(), *t, db); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | fn validate_record_literal( | ||
51 | &mut self, | ||
52 | id: ExprId, | ||
53 | _path: &Option<Path>, | ||
54 | fields: &[RecordLitField], | ||
55 | spread: Option<ExprId>, | ||
56 | db: &impl HirDatabase, | ||
57 | ) { | ||
58 | if spread.is_some() { | ||
59 | return; | ||
60 | } | ||
61 | |||
62 | let struct_def = match self.infer[id].as_adt() { | ||
63 | Some((Adt::Struct(s), _)) => s, | ||
64 | _ => return, | ||
65 | }; | ||
66 | |||
67 | let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); | ||
68 | let missed_fields: Vec<Name> = struct_def | ||
69 | .fields(db) | ||
70 | .iter() | ||
71 | .filter_map(|f| { | ||
72 | let name = f.name(db); | ||
73 | if lit_fields.contains(&name) { | ||
74 | None | ||
75 | } else { | ||
76 | Some(name) | ||
77 | } | ||
78 | }) | ||
79 | .collect(); | ||
80 | if missed_fields.is_empty() { | ||
81 | return; | ||
82 | } | ||
83 | let source_map = self.func.body_source_map(db); | ||
84 | |||
85 | if let Some(source_ptr) = source_map.expr_syntax(id) { | ||
86 | if let Some(expr) = source_ptr.ast.a() { | ||
87 | let root = source_ptr.file_syntax(db); | ||
88 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | ||
89 | if let Some(field_list) = record_lit.record_field_list() { | ||
90 | self.sink.push(MissingFields { | ||
91 | file: source_ptr.file_id, | ||
92 | field_list: AstPtr::new(&field_list), | ||
93 | missed_fields, | ||
94 | }) | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | fn validate_results_in_tail_expr( | ||
102 | &mut self, | ||
103 | body_id: ExprId, | ||
104 | id: ExprId, | ||
105 | db: &impl HirDatabase, | ||
106 | ) { | ||
107 | // the mismatch will be on the whole block currently | ||
108 | let mismatch = match self.infer.type_mismatch_for_expr(body_id) { | ||
109 | Some(m) => m, | ||
110 | None => return, | ||
111 | }; | ||
112 | |||
113 | let std_result_path = known::std_result_result(); | ||
114 | |||
115 | let resolver = self.func.resolver(db); | ||
116 | let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { | ||
117 | Some(it) => it, | ||
118 | _ => return, | ||
119 | }; | ||
120 | |||
121 | let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum)); | ||
122 | let params = match &mismatch.expected { | ||
123 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, | ||
124 | _ => return, | ||
125 | }; | ||
126 | |||
127 | if params.len() == 2 && ¶ms[0] == &mismatch.actual { | ||
128 | let source_map = self.func.body_source_map(db); | ||
129 | |||
130 | if let Some(source_ptr) = source_map.expr_syntax(id) { | ||
131 | if let Some(expr) = source_ptr.ast.a() { | ||
132 | self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | } | ||
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 9793af858..7e5523c54 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir_def::{StructId, StructOrUnionId, UnionId}; | 3 | use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; |
4 | use hir_expand::name::AsName; | 4 | use hir_expand::name::AsName; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, NameOwner}, | 6 | ast::{self, AstNode, NameOwner}, |
@@ -10,9 +10,9 @@ use ra_syntax::{ | |||
10 | use crate::{ | 10 | use crate::{ |
11 | db::{AstDatabase, DefDatabase, HirDatabase}, | 11 | db::{AstDatabase, DefDatabase, HirDatabase}, |
12 | ids::{AstItemDef, LocationCtx}, | 12 | ids::{AstItemDef, LocationCtx}, |
13 | AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, | 13 | Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, |
14 | ImplBlock, Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, | 14 | Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, |
15 | Union, VariantDef, | 15 | VariantDef, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub trait FromSource: Sized { | 18 | pub trait FromSource: Sized { |
@@ -152,44 +152,48 @@ impl Local { | |||
152 | } | 152 | } |
153 | 153 | ||
154 | impl Module { | 154 | impl Module { |
155 | pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { | 155 | pub fn from_declaration(db: &impl DefDatabase, src: Source<ast::Module>) -> Option<Self> { |
156 | let src_parent = Source { | 156 | let parent_declaration = src.ast.syntax().ancestors().skip(1).find_map(ast::Module::cast); |
157 | file_id: src.file_id, | 157 | |
158 | ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), | 158 | let parent_module = match parent_declaration { |
159 | }; | 159 | Some(parent_declaration) => { |
160 | let parent_module = Module::from_definition(db, src_parent)?; | 160 | let src_parent = Source { file_id: src.file_id, ast: parent_declaration }; |
161 | Module::from_declaration(db, src_parent) | ||
162 | } | ||
163 | _ => { | ||
164 | let src_parent = Source { | ||
165 | file_id: src.file_id, | ||
166 | ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), | ||
167 | }; | ||
168 | Module::from_definition(db, src_parent) | ||
169 | } | ||
170 | }?; | ||
171 | |||
161 | let child_name = src.ast.name()?; | 172 | let child_name = src.ast.name()?; |
162 | parent_module.child(db, &child_name.as_name()) | 173 | parent_module.child(db, &child_name.as_name()) |
163 | } | 174 | } |
164 | 175 | ||
165 | pub fn from_definition( | 176 | pub fn from_definition(db: &impl DefDatabase, src: Source<ModuleSource>) -> Option<Self> { |
166 | db: &(impl DefDatabase + AstDatabase), | 177 | match src.ast { |
167 | src: Source<ModuleSource>, | ||
168 | ) -> Option<Self> { | ||
169 | let decl_id = match src.ast { | ||
170 | ModuleSource::Module(ref module) => { | 178 | ModuleSource::Module(ref module) => { |
171 | assert!(!module.has_semi()); | 179 | assert!(!module.has_semi()); |
172 | let ast_id_map = db.ast_id_map(src.file_id); | 180 | return Module::from_declaration( |
173 | let item_id = AstId::new(src.file_id, ast_id_map.ast_id(module)); | 181 | db, |
174 | Some(item_id) | 182 | Source { file_id: src.file_id, ast: module.clone() }, |
183 | ); | ||
175 | } | 184 | } |
176 | ModuleSource::SourceFile(_) => None, | 185 | ModuleSource::SourceFile(_) => (), |
177 | }; | 186 | }; |
178 | 187 | ||
179 | db.relevant_crates(src.file_id.original_file(db)).iter().find_map(|&crate_id| { | 188 | let original_file = src.file_id.original_file(db); |
180 | let def_map = db.crate_def_map(crate_id); | ||
181 | |||
182 | let (module_id, _module_data) = | ||
183 | def_map.modules.iter().find(|(_module_id, module_data)| { | ||
184 | if decl_id.is_some() { | ||
185 | module_data.declaration == decl_id | ||
186 | } else { | ||
187 | module_data.definition.map(|it| it.into()) == Some(src.file_id) | ||
188 | } | ||
189 | })?; | ||
190 | 189 | ||
191 | Some(Module::new(Crate { crate_id }, module_id)) | 190 | let (krate, module_id) = |
192 | }) | 191 | db.relevant_crates(original_file).iter().find_map(|&crate_id| { |
192 | let crate_def_map = db.crate_def_map(crate_id); | ||
193 | let local_module_id = crate_def_map.modules_for_file(original_file).next()?; | ||
194 | Some((crate_id, local_module_id)) | ||
195 | })?; | ||
196 | Some(Module { id: ModuleId { krate, module_id } }) | ||
193 | } | 197 | } |
194 | } | 198 | } |
195 | 199 | ||
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 2f3e12eb8..2fb913108 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -16,8 +16,8 @@ use crate::{ | |||
16 | expr::{ExprScopes, PatId, ScopeId}, | 16 | expr::{ExprScopes, PatId, ScopeId}, |
17 | generics::GenericParams, | 17 | generics::GenericParams, |
18 | impl_block::ImplBlock, | 18 | impl_block::ImplBlock, |
19 | Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, PerNs, Static, Struct, Trait, | 19 | Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, |
20 | TypeAlias, | 20 | Static, Struct, Trait, TypeAlias, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | #[derive(Debug, Clone, Default)] | 23 | #[derive(Debug, Clone, Default)] |
@@ -34,6 +34,7 @@ pub(crate) struct ModuleItemMap { | |||
34 | 34 | ||
35 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone)] |
36 | pub(crate) struct ExprScope { | 36 | pub(crate) struct ExprScope { |
37 | owner: DefWithBody, | ||
37 | expr_scopes: Arc<ExprScopes>, | 38 | expr_scopes: Arc<ExprScopes>, |
38 | scope_id: ScopeId, | 39 | scope_id: ScopeId, |
39 | } | 40 | } |
@@ -53,7 +54,7 @@ pub(crate) enum Scope { | |||
53 | } | 54 | } |
54 | 55 | ||
55 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 56 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
56 | pub enum TypeNs { | 57 | pub(crate) enum TypeNs { |
57 | SelfType(ImplBlock), | 58 | SelfType(ImplBlock), |
58 | GenericParam(u32), | 59 | GenericParam(u32), |
59 | Adt(Adt), | 60 | Adt(Adt), |
@@ -68,13 +69,13 @@ pub enum TypeNs { | |||
68 | } | 69 | } |
69 | 70 | ||
70 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 71 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
71 | pub enum ResolveValueResult { | 72 | pub(crate) enum ResolveValueResult { |
72 | ValueNs(ValueNs), | 73 | ValueNs(ValueNs), |
73 | Partial(TypeNs, usize), | 74 | Partial(TypeNs, usize), |
74 | } | 75 | } |
75 | 76 | ||
76 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 77 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
77 | pub enum ValueNs { | 78 | pub(crate) enum ValueNs { |
78 | LocalBinding(PatId), | 79 | LocalBinding(PatId), |
79 | Function(Function), | 80 | Function(Function), |
80 | Const(Const), | 81 | Const(Const), |
@@ -399,10 +400,11 @@ impl Resolver { | |||
399 | 400 | ||
400 | pub(crate) fn push_expr_scope( | 401 | pub(crate) fn push_expr_scope( |
401 | self, | 402 | self, |
403 | owner: DefWithBody, | ||
402 | expr_scopes: Arc<ExprScopes>, | 404 | expr_scopes: Arc<ExprScopes>, |
403 | scope_id: ScopeId, | 405 | scope_id: ScopeId, |
404 | ) -> Resolver { | 406 | ) -> Resolver { |
405 | self.push_scope(Scope::ExprScope(ExprScope { expr_scopes, scope_id })) | 407 | self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) |
406 | } | 408 | } |
407 | } | 409 | } |
408 | 410 | ||
@@ -413,7 +415,7 @@ pub enum ScopeDef { | |||
413 | GenericParam(u32), | 415 | GenericParam(u32), |
414 | ImplSelfType(ImplBlock), | 416 | ImplSelfType(ImplBlock), |
415 | AdtSelfType(Adt), | 417 | AdtSelfType(Adt), |
416 | LocalBinding(PatId), | 418 | Local(Local), |
417 | Unknown, | 419 | Unknown, |
418 | } | 420 | } |
419 | 421 | ||
@@ -467,9 +469,10 @@ impl Scope { | |||
467 | Scope::AdtScope(i) => { | 469 | Scope::AdtScope(i) => { |
468 | f(name::SELF_TYPE, ScopeDef::AdtSelfType(*i)); | 470 | f(name::SELF_TYPE, ScopeDef::AdtSelfType(*i)); |
469 | } | 471 | } |
470 | Scope::ExprScope(e) => { | 472 | Scope::ExprScope(scope) => { |
471 | e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { | 473 | scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { |
472 | f(e.name().clone(), ScopeDef::LocalBinding(e.pat())); | 474 | let local = Local { parent: scope.owner, pat_id: e.pat() }; |
475 | f(e.name().clone(), ScopeDef::Local(local)); | ||
473 | }); | 476 | }); |
474 | } | 477 | } |
475 | } | 478 | } |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ca40e3b54..662d3f880 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -19,7 +19,6 @@ use ra_syntax::{ | |||
19 | SyntaxKind::*, | 19 | SyntaxKind::*, |
20 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 20 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
21 | }; | 21 | }; |
22 | use rustc_hash::FxHashSet; | ||
23 | 22 | ||
24 | use crate::{ | 23 | use crate::{ |
25 | db::HirDatabase, | 24 | db::HirDatabase, |
@@ -195,14 +194,6 @@ impl SourceAnalyzer { | |||
195 | Some(self.infer.as_ref()?[pat_id].clone()) | 194 | Some(self.infer.as_ref()?[pat_id].clone()) |
196 | } | 195 | } |
197 | 196 | ||
198 | pub fn type_of_pat_by_id( | ||
199 | &self, | ||
200 | _db: &impl HirDatabase, | ||
201 | pat_id: expr::PatId, | ||
202 | ) -> Option<crate::Ty> { | ||
203 | Some(self.infer.as_ref()?[pat_id].clone()) | ||
204 | } | ||
205 | |||
206 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 197 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
207 | let expr_id = self.expr_id(&call.clone().into())?; | 198 | let expr_id = self.expr_id(&call.clone().into())?; |
208 | self.infer.as_ref()?.method_resolution(expr_id) | 199 | self.infer.as_ref()?.method_resolution(expr_id) |
@@ -293,23 +284,15 @@ impl SourceAnalyzer { | |||
293 | self.resolve_hir_path(db, &hir_path) | 284 | self.resolve_hir_path(db, &hir_path) |
294 | } | 285 | } |
295 | 286 | ||
296 | pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> { | 287 | fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> { |
297 | let mut shadowed = FxHashSet::default(); | ||
298 | let name = name_ref.as_name(); | 288 | let name = name_ref.as_name(); |
299 | let source_map = self.body_source_map.as_ref()?; | 289 | let source_map = self.body_source_map.as_ref()?; |
300 | let scopes = self.scopes.as_ref()?; | 290 | let scopes = self.scopes.as_ref()?; |
301 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax()); | 291 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax())?; |
302 | let ret = scopes | 292 | let entry = scopes.resolve_name_in_scope(scope, &name)?; |
303 | .scope_chain(scope) | 293 | Some(ScopeEntryWithSyntax { |
304 | .flat_map(|scope| scopes.entries(scope).iter()) | 294 | name: entry.name().clone(), |
305 | .filter(|entry| shadowed.insert(entry.name())) | 295 | ptr: source_map.pat_syntax(entry.pat())?.ast, |
306 | .filter(|entry| entry.name() == &name) | ||
307 | .nth(0); | ||
308 | ret.and_then(|entry| { | ||
309 | Some(ScopeEntryWithSyntax { | ||
310 | name: entry.name().clone(), | ||
311 | ptr: source_map.pat_syntax(entry.pat())?.ast, | ||
312 | }) | ||
313 | }) | 296 | }) |
314 | } | 297 | } |
315 | 298 | ||
@@ -317,9 +300,9 @@ impl SourceAnalyzer { | |||
317 | self.resolver.process_all_names(db, f) | 300 | self.resolver.process_all_names(db, f) |
318 | } | 301 | } |
319 | 302 | ||
303 | // FIXME: we only use this in `inline_local_variable` assist, ideally, we | ||
304 | // should switch to general reference search infra there. | ||
320 | pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { | 305 | pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { |
321 | // FIXME: at least, this should work with any DefWithBody, but ideally | ||
322 | // this should be hir-based altogether | ||
323 | let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); | 306 | let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); |
324 | let ptr = Either::A(AstPtr::new(&ast::Pat::from(pat.clone()))); | 307 | let ptr = Either::A(AstPtr::new(&ast::Pat::from(pat.clone()))); |
325 | fn_def | 308 | fn_def |
@@ -421,11 +404,6 @@ impl SourceAnalyzer { | |||
421 | pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> { | 404 | pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> { |
422 | self.infer.clone().unwrap() | 405 | self.infer.clone().unwrap() |
423 | } | 406 | } |
424 | |||
425 | #[cfg(test)] | ||
426 | pub(crate) fn scopes(&self) -> Arc<ExprScopes> { | ||
427 | self.scopes.clone().unwrap() | ||
428 | } | ||
429 | } | 407 | } |
430 | 408 | ||
431 | fn scope_for( | 409 | fn scope_for( |
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs index 5237b303a..1caa2e875 100644 --- a/crates/ra_hir/src/test_db.rs +++ b/crates/ra_hir/src/test_db.rs | |||
@@ -81,7 +81,7 @@ impl TestDB { | |||
81 | let crate_graph = self.crate_graph(); | 81 | let crate_graph = self.crate_graph(); |
82 | for krate in crate_graph.iter().next() { | 82 | for krate in crate_graph.iter().next() { |
83 | let crate_def_map = self.crate_def_map(krate); | 83 | let crate_def_map = self.crate_def_map(krate); |
84 | for (module_id, _) in crate_def_map.modules.iter() { | 84 | for module_id in crate_def_map.modules() { |
85 | let module_id = ModuleId { krate, module_id }; | 85 | let module_id = ModuleId { krate, module_id }; |
86 | let module = crate::Module::from(module_id); | 86 | let module = crate::Module::from(module_id); |
87 | module.diagnostics( | 87 | module.diagnostics( |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 8863c3608..fe9346c78 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -254,7 +254,6 @@ fn test(a: u32, b: isize, c: !, d: &str) { | |||
254 | 1.0f32; | 254 | 1.0f32; |
255 | }"#), | 255 | }"#), |
256 | @r###" | 256 | @r###" |
257 | |||
258 | [9; 10) 'a': u32 | 257 | [9; 10) 'a': u32 |
259 | [17; 18) 'b': isize | 258 | [17; 18) 'b': isize |
260 | [27; 28) 'c': ! | 259 | [27; 28) 'c': ! |
@@ -317,7 +316,6 @@ fn test() { | |||
317 | } | 316 | } |
318 | "#), | 317 | "#), |
319 | @r###" | 318 | @r###" |
320 | |||
321 | [15; 20) '{ 1 }': u32 | 319 | [15; 20) '{ 1 }': u32 |
322 | [17; 18) '1': u32 | 320 | [17; 18) '1': u32 |
323 | [48; 53) '{ 1 }': u32 | 321 | [48; 53) '{ 1 }': u32 |
@@ -354,7 +352,7 @@ fn test() { | |||
354 | [66; 74) 'S::foo()': i32 | 352 | [66; 74) 'S::foo()': i32 |
355 | [80; 88) '<S>::foo': fn foo() -> i32 | 353 | [80; 88) '<S>::foo': fn foo() -> i32 |
356 | [80; 90) '<S>::foo()': i32 | 354 | [80; 90) '<S>::foo()': i32 |
357 | "### | 355 | "### |
358 | ); | 356 | ); |
359 | } | 357 | } |
360 | 358 | ||
@@ -409,7 +407,6 @@ fn test() { | |||
409 | } | 407 | } |
410 | "#), | 408 | "#), |
411 | @r###" | 409 | @r###" |
412 | |||
413 | [72; 154) '{ ...a.c; }': () | 410 | [72; 154) '{ ...a.c; }': () |
414 | [82; 83) 'c': C | 411 | [82; 83) 'c': C |
415 | [86; 87) 'C': C(usize) -> C | 412 | [86; 87) 'C': C(usize) -> C |
@@ -443,7 +440,6 @@ fn test() { | |||
443 | E::V2; | 440 | E::V2; |
444 | }"#), | 441 | }"#), |
445 | @r###" | 442 | @r###" |
446 | |||
447 | [48; 82) '{ E:...:V2; }': () | 443 | [48; 82) '{ E:...:V2; }': () |
448 | [52; 70) 'E::V1 ...d: 1 }': E | 444 | [52; 70) 'E::V1 ...d: 1 }': E |
449 | [67; 68) '1': u32 | 445 | [67; 68) '1': u32 |
@@ -471,7 +467,6 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { | |||
471 | } | 467 | } |
472 | "#), | 468 | "#), |
473 | @r###" | 469 | @r###" |
474 | |||
475 | [9; 10) 'a': &u32 | 470 | [9; 10) 'a': &u32 |
476 | [18; 19) 'b': &mut u32 | 471 | [18; 19) 'b': &mut u32 |
477 | [31; 32) 'c': *const u32 | 472 | [31; 32) 'c': *const u32 |
@@ -524,7 +519,6 @@ fn test() { | |||
524 | } | 519 | } |
525 | "##), | 520 | "##), |
526 | @r###" | 521 | @r###" |
527 | |||
528 | [11; 221) '{ ...o"#; }': () | 522 | [11; 221) '{ ...o"#; }': () |
529 | [17; 21) '5i32': i32 | 523 | [17; 21) '5i32': i32 |
530 | [27; 31) '5f32': f32 | 524 | [27; 31) '5f32': f32 |
@@ -568,7 +562,6 @@ fn test(x: SomeType) { | |||
568 | } | 562 | } |
569 | "#), | 563 | "#), |
570 | @r###" | 564 | @r###" |
571 | |||
572 | [27; 28) 'x': SomeType | 565 | [27; 28) 'x': SomeType |
573 | [40; 272) '{ ...lo"; }': () | 566 | [40; 272) '{ ...lo"; }': () |
574 | [50; 51) 'b': bool | 567 | [50; 51) 'b': bool |
@@ -632,7 +625,6 @@ fn test() -> &mut &f64 { | |||
632 | } | 625 | } |
633 | "#), | 626 | "#), |
634 | @r###" | 627 | @r###" |
635 | |||
636 | [14; 15) 'x': u32 | 628 | [14; 15) 'x': u32 |
637 | [22; 24) '{}': () | 629 | [22; 24) '{}': () |
638 | [78; 231) '{ ...t &c }': &mut &f64 | 630 | [78; 231) '{ ...t &c }': &mut &f64 |
@@ -679,7 +671,6 @@ impl S { | |||
679 | } | 671 | } |
680 | "#), | 672 | "#), |
681 | @r###" | 673 | @r###" |
682 | |||
683 | [34; 38) 'self': &S | 674 | [34; 38) 'self': &S |
684 | [40; 61) '{ ... }': () | 675 | [40; 61) '{ ... }': () |
685 | [50; 54) 'self': &S | 676 | [50; 54) 'self': &S |
@@ -719,7 +710,6 @@ fn test() -> bool { | |||
719 | } | 710 | } |
720 | "#), | 711 | "#), |
721 | @r###" | 712 | @r###" |
722 | |||
723 | [6; 7) 'x': bool | 713 | [6; 7) 'x': bool |
724 | [22; 34) '{ 0i32 }': i32 | 714 | [22; 34) '{ 0i32 }': i32 |
725 | [28; 32) '0i32': i32 | 715 | [28; 32) '0i32': i32 |
@@ -802,7 +792,6 @@ fn test2(a1: *const A, a2: *mut A) { | |||
802 | } | 792 | } |
803 | "#), | 793 | "#), |
804 | @r###" | 794 | @r###" |
805 | |||
806 | [44; 45) 'a': A | 795 | [44; 45) 'a': A |
807 | [50; 213) '{ ...5.b; }': () | 796 | [50; 213) '{ ...5.b; }': () |
808 | [60; 62) 'a1': A | 797 | [60; 62) 'a1': A |
@@ -970,7 +959,7 @@ fn test(a: A<i32>) { | |||
970 | [374; 375) 'B': B<A<i32>>(T) -> B<T> | 959 | [374; 375) 'B': B<A<i32>>(T) -> B<T> |
971 | [374; 378) 'B(a)': B<A<i32>> | 960 | [374; 378) 'B(a)': B<A<i32>> |
972 | [376; 377) 'a': A<i32> | 961 | [376; 377) 'a': A<i32> |
973 | "### | 962 | "### |
974 | ); | 963 | ); |
975 | } | 964 | } |
976 | 965 | ||
@@ -983,7 +972,6 @@ fn test() { | |||
983 | } | 972 | } |
984 | "#), | 973 | "#), |
985 | @r###" | 974 | @r###" |
986 | |||
987 | [11; 37) '{ l... {}; }': () | 975 | [11; 37) '{ l... {}; }': () |
988 | [20; 21) 'x': () | 976 | [20; 21) 'x': () |
989 | [24; 34) 'if true {}': () | 977 | [24; 34) 'if true {}': () |
@@ -1105,7 +1093,6 @@ fn test(a: A) { | |||
1105 | } | 1093 | } |
1106 | "#), | 1094 | "#), |
1107 | @r###" | 1095 | @r###" |
1108 | |||
1109 | [32; 36) 'self': A | 1096 | [32; 36) 'self': A |
1110 | [38; 39) 'x': u32 | 1097 | [38; 39) 'x': u32 |
1111 | [53; 55) '{}': () | 1098 | [53; 55) '{}': () |
@@ -1142,7 +1129,6 @@ fn test() { | |||
1142 | } | 1129 | } |
1143 | "#), | 1130 | "#), |
1144 | @r###" | 1131 | @r###" |
1145 | |||
1146 | [40; 44) 'self': &str | 1132 | [40; 44) 'self': &str |
1147 | [53; 55) '{}': () | 1133 | [53; 55) '{}': () |
1148 | [69; 89) '{ ...o(); }': () | 1134 | [69; 89) '{ ...o(); }': () |
@@ -1166,7 +1152,6 @@ fn test(x: &str, y: isize) { | |||
1166 | } | 1152 | } |
1167 | "#), | 1153 | "#), |
1168 | @r###" | 1154 | @r###" |
1169 | |||
1170 | [9; 10) 'x': &str | 1155 | [9; 10) 'x': &str |
1171 | [18; 19) 'y': isize | 1156 | [18; 19) 'y': isize |
1172 | [28; 170) '{ ...d"); }': () | 1157 | [28; 170) '{ ...d"); }': () |
@@ -1367,7 +1352,6 @@ fn test() { | |||
1367 | } | 1352 | } |
1368 | "#), | 1353 | "#), |
1369 | @r###" | 1354 | @r###" |
1370 | |||
1371 | [28; 79) '{ ...(1); }': () | 1355 | [28; 79) '{ ...(1); }': () |
1372 | [38; 42) 'A(n)': A<i32> | 1356 | [38; 42) 'A(n)': A<i32> |
1373 | [40; 41) 'n': &i32 | 1357 | [40; 41) 'n': &i32 |
@@ -1396,7 +1380,6 @@ fn test() { | |||
1396 | } | 1380 | } |
1397 | "#), | 1381 | "#), |
1398 | @r###" | 1382 | @r###" |
1399 | |||
1400 | [11; 57) '{ ...= v; }': () | 1383 | [11; 57) '{ ...= v; }': () |
1401 | [21; 22) 'v': &(i32, &i32) | 1384 | [21; 22) 'v': &(i32, &i32) |
1402 | [25; 33) '&(1, &2)': &(i32, &i32) | 1385 | [25; 33) '&(1, &2)': &(i32, &i32) |
@@ -1441,7 +1424,6 @@ fn test() { | |||
1441 | } | 1424 | } |
1442 | "#), | 1425 | "#), |
1443 | @r###" | 1426 | @r###" |
1444 | |||
1445 | [68; 289) '{ ... d; }': () | 1427 | [68; 289) '{ ... d; }': () |
1446 | [78; 79) 'e': E | 1428 | [78; 79) 'e': E |
1447 | [82; 95) 'E::A { x: 3 }': E | 1429 | [82; 95) 'E::A { x: 3 }': E |
@@ -1488,7 +1470,6 @@ fn test(a1: A<u32>, i: i32) { | |||
1488 | } | 1470 | } |
1489 | "#), | 1471 | "#), |
1490 | @r###" | 1472 | @r###" |
1491 | |||
1492 | [36; 38) 'a1': A<u32> | 1473 | [36; 38) 'a1': A<u32> |
1493 | [48; 49) 'i': i32 | 1474 | [48; 49) 'i': i32 |
1494 | [56; 147) '{ ...3.x; }': () | 1475 | [56; 147) '{ ...3.x; }': () |
@@ -1569,7 +1550,6 @@ fn test(a1: A<u32>, o: Option<u64>) { | |||
1569 | } | 1550 | } |
1570 | "#), | 1551 | "#), |
1571 | @r###" | 1552 | @r###" |
1572 | |||
1573 | [79; 81) 'a1': A<u32> | 1553 | [79; 81) 'a1': A<u32> |
1574 | [91; 92) 'o': Option<u64> | 1554 | [91; 92) 'o': Option<u64> |
1575 | [107; 244) '{ ... }; }': () | 1555 | [107; 244) '{ ... }; }': () |
@@ -1604,7 +1584,6 @@ fn test() { | |||
1604 | } | 1584 | } |
1605 | "#), | 1585 | "#), |
1606 | @r###" | 1586 | @r###" |
1607 | |||
1608 | [10; 11) 't': T | 1587 | [10; 11) 't': T |
1609 | [21; 26) '{ t }': T | 1588 | [21; 26) '{ t }': T |
1610 | [23; 24) 't': T | 1589 | [23; 24) 't': T |
@@ -1652,7 +1631,6 @@ fn test() -> i128 { | |||
1652 | } | 1631 | } |
1653 | "#), | 1632 | "#), |
1654 | @r###" | 1633 | @r###" |
1655 | |||
1656 | [74; 78) 'self': A<X, Y> | 1634 | [74; 78) 'self': A<X, Y> |
1657 | [85; 107) '{ ... }': X | 1635 | [85; 107) '{ ... }': X |
1658 | [95; 99) 'self': A<X, Y> | 1636 | [95; 99) 'self': A<X, Y> |
@@ -1706,7 +1684,6 @@ fn test(o: Option<u32>) { | |||
1706 | } | 1684 | } |
1707 | "#), | 1685 | "#), |
1708 | @r###" | 1686 | @r###" |
1709 | |||
1710 | [78; 82) 'self': &Option<T> | 1687 | [78; 82) 'self': &Option<T> |
1711 | [98; 100) '{}': () | 1688 | [98; 100) '{}': () |
1712 | [111; 112) 'o': Option<u32> | 1689 | [111; 112) 'o': Option<u32> |
@@ -1744,7 +1721,6 @@ fn test() -> i128 { | |||
1744 | } | 1721 | } |
1745 | "#), | 1722 | "#), |
1746 | @r###" | 1723 | @r###" |
1747 | |||
1748 | [53; 57) 'self': A<T2> | 1724 | [53; 57) 'self': A<T2> |
1749 | [65; 87) '{ ... }': T2 | 1725 | [65; 87) '{ ... }': T2 |
1750 | [75; 79) 'self': A<T2> | 1726 | [75; 79) 'self': A<T2> |
@@ -1921,7 +1897,6 @@ fn test() { | |||
1921 | } | 1897 | } |
1922 | "#), | 1898 | "#), |
1923 | @r###" | 1899 | @r###" |
1924 | |||
1925 | [56; 64) '{ A {} }': A | 1900 | [56; 64) '{ A {} }': A |
1926 | [58; 62) 'A {}': A | 1901 | [58; 62) 'A {}': A |
1927 | [126; 132) '{ 99 }': u32 | 1902 | [126; 132) '{ 99 }': u32 |
@@ -1961,7 +1936,6 @@ fn test() { | |||
1961 | } | 1936 | } |
1962 | "#), | 1937 | "#), |
1963 | @r###" | 1938 | @r###" |
1964 | |||
1965 | [64; 67) 'val': T | 1939 | [64; 67) 'val': T |
1966 | [82; 109) '{ ... }': Gen<T> | 1940 | [82; 109) '{ ... }': Gen<T> |
1967 | [92; 103) 'Gen { val }': Gen<T> | 1941 | [92; 103) 'Gen { val }': Gen<T> |
@@ -2129,7 +2103,6 @@ fn test(x: X) { | |||
2129 | } | 2103 | } |
2130 | "#), | 2104 | "#), |
2131 | @r###" | 2105 | @r###" |
2132 | |||
2133 | [20; 21) 'x': X | 2106 | [20; 21) 'x': X |
2134 | [26; 47) '{ ...eld; }': () | 2107 | [26; 47) '{ ...eld; }': () |
2135 | [32; 33) 'x': X | 2108 | [32; 33) 'x': X |
@@ -2151,7 +2124,6 @@ fn test() { | |||
2151 | } | 2124 | } |
2152 | "#), | 2125 | "#), |
2153 | @r###" | 2126 | @r###" |
2154 | |||
2155 | [11; 89) '{ ... } }': () | 2127 | [11; 89) '{ ... } }': () |
2156 | [17; 21) 'X {}': {unknown} | 2128 | [17; 21) 'X {}': {unknown} |
2157 | [27; 87) 'match ... }': () | 2129 | [27; 87) 'match ... }': () |
@@ -2174,7 +2146,6 @@ fn quux() { | |||
2174 | } | 2146 | } |
2175 | "#), | 2147 | "#), |
2176 | @r###" | 2148 | @r###" |
2177 | |||
2178 | [11; 41) '{ ...+ y; }': () | 2149 | [11; 41) '{ ...+ y; }': () |
2179 | [21; 22) 'y': i32 | 2150 | [21; 22) 'y': i32 |
2180 | [25; 27) '92': i32 | 2151 | [25; 27) '92': i32 |
@@ -2300,7 +2271,6 @@ fn write() { | |||
2300 | } | 2271 | } |
2301 | "#), | 2272 | "#), |
2302 | @r###" | 2273 | @r###" |
2303 | |||
2304 | [54; 139) '{ ... } }': () | 2274 | [54; 139) '{ ... } }': () |
2305 | [60; 137) 'match ... }': () | 2275 | [60; 137) 'match ... }': () |
2306 | [66; 83) 'someth...nknown': Maybe<{unknown}> | 2276 | [66; 83) 'someth...nknown': Maybe<{unknown}> |
@@ -2322,7 +2292,6 @@ fn test_line_buffer() { | |||
2322 | } | 2292 | } |
2323 | "#), | 2293 | "#), |
2324 | @r###" | 2294 | @r###" |
2325 | |||
2326 | [23; 53) '{ ...n']; }': () | 2295 | [23; 53) '{ ...n']; }': () |
2327 | [29; 50) '&[0, b...b'\n']': &[u8;_] | 2296 | [29; 50) '&[0, b...b'\n']': &[u8;_] |
2328 | [30; 50) '[0, b'...b'\n']': [u8;_] | 2297 | [30; 50) '[0, b'...b'\n']': [u8;_] |
@@ -2446,7 +2415,6 @@ fn test<R>(query_response: Canonical<QueryResponse<R>>) { | |||
2446 | } | 2415 | } |
2447 | "#), | 2416 | "#), |
2448 | @r###" | 2417 | @r###" |
2449 | |||
2450 | [92; 106) 'query_response': Canonical<QueryResponse<R>> | 2418 | [92; 106) 'query_response': Canonical<QueryResponse<R>> |
2451 | [137; 167) '{ ...lue; }': () | 2419 | [137; 167) '{ ...lue; }': () |
2452 | [143; 164) '&query....value': &QueryResponse<R> | 2420 | [143; 164) '&query....value': &QueryResponse<R> |
@@ -2472,7 +2440,6 @@ pub fn main_loop() { | |||
2472 | } | 2440 | } |
2473 | "#), | 2441 | "#), |
2474 | @r###" | 2442 | @r###" |
2475 | |||
2476 | [144; 146) '{}': () | 2443 | [144; 146) '{}': () |
2477 | [169; 198) '{ ...t(); }': () | 2444 | [169; 198) '{ ...t(); }': () |
2478 | [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H> | 2445 | [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H> |
@@ -2518,7 +2485,6 @@ fn test() { | |||
2518 | } | 2485 | } |
2519 | "#), | 2486 | "#), |
2520 | @r###" | 2487 | @r###" |
2521 | |||
2522 | [49; 50) '0': u32 | 2488 | [49; 50) '0': u32 |
2523 | [80; 83) '101': u32 | 2489 | [80; 83) '101': u32 |
2524 | [95; 213) '{ ...NST; }': () | 2490 | [95; 213) '{ ...NST; }': () |
@@ -2549,7 +2515,6 @@ fn test() { | |||
2549 | } | 2515 | } |
2550 | "#), | 2516 | "#), |
2551 | @r###" | 2517 | @r###" |
2552 | |||
2553 | [29; 32) '101': u32 | 2518 | [29; 32) '101': u32 |
2554 | [70; 73) '101': u32 | 2519 | [70; 73) '101': u32 |
2555 | [85; 280) '{ ...MUT; }': () | 2520 | [85; 280) '{ ...MUT; }': () |
@@ -2588,7 +2553,6 @@ fn test() { | |||
2588 | } | 2553 | } |
2589 | "#), | 2554 | "#), |
2590 | @r###" | 2555 | @r###" |
2591 | |||
2592 | [31; 35) 'self': &Self | 2556 | [31; 35) 'self': &Self |
2593 | [110; 114) 'self': &Self | 2557 | [110; 114) 'self': &Self |
2594 | [170; 228) '{ ...i128 }': () | 2558 | [170; 228) '{ ...i128 }': () |
@@ -2636,7 +2600,6 @@ mod bar_test { | |||
2636 | } | 2600 | } |
2637 | "#), | 2601 | "#), |
2638 | @r###" | 2602 | @r###" |
2639 | |||
2640 | [63; 67) 'self': &Self | 2603 | [63; 67) 'self': &Self |
2641 | [169; 173) 'self': &Self | 2604 | [169; 173) 'self': &Self |
2642 | [300; 337) '{ ... }': () | 2605 | [300; 337) '{ ... }': () |
@@ -2664,7 +2627,6 @@ fn test() { | |||
2664 | } | 2627 | } |
2665 | "#), | 2628 | "#), |
2666 | @r###" | 2629 | @r###" |
2667 | |||
2668 | [33; 37) 'self': &Self | 2630 | [33; 37) 'self': &Self |
2669 | [92; 111) '{ ...d(); }': () | 2631 | [92; 111) '{ ...d(); }': () |
2670 | [98; 99) 'S': S | 2632 | [98; 99) 'S': S |
@@ -2694,7 +2656,6 @@ fn test() { | |||
2694 | } | 2656 | } |
2695 | "#), | 2657 | "#), |
2696 | @r###" | 2658 | @r###" |
2697 | |||
2698 | [43; 47) 'self': &Self | 2659 | [43; 47) 'self': &Self |
2699 | [82; 86) 'self': &Self | 2660 | [82; 86) 'self': &Self |
2700 | [210; 361) '{ ..., i8 }': () | 2661 | [210; 361) '{ ..., i8 }': () |
@@ -2725,7 +2686,6 @@ fn test() { | |||
2725 | } | 2686 | } |
2726 | "#), | 2687 | "#), |
2727 | @r###" | 2688 | @r###" |
2728 | |||
2729 | [33; 37) 'self': &Self | 2689 | [33; 37) 'self': &Self |
2730 | [102; 127) '{ ...d(); }': () | 2690 | [102; 127) '{ ...d(); }': () |
2731 | [108; 109) 'S': S<u32>(T) -> S<T> | 2691 | [108; 109) 'S': S<u32>(T) -> S<T> |
@@ -3130,7 +3090,6 @@ fn test<T: Iterable<Item=u32>>() { | |||
3130 | } | 3090 | } |
3131 | "#), | 3091 | "#), |
3132 | @r###" | 3092 | @r###" |
3133 | |||
3134 | [67; 100) '{ ...own; }': () | 3093 | [67; 100) '{ ...own; }': () |
3135 | [77; 78) 'y': {unknown} | 3094 | [77; 78) 'y': {unknown} |
3136 | [90; 97) 'unknown': {unknown} | 3095 | [90; 97) 'unknown': {unknown} |
@@ -3146,7 +3105,6 @@ const A: u32 = 1 + 1; | |||
3146 | static B: u64 = { let x = 1; x }; | 3105 | static B: u64 = { let x = 1; x }; |
3147 | "#), | 3106 | "#), |
3148 | @r###" | 3107 | @r###" |
3149 | |||
3150 | [16; 17) '1': u32 | 3108 | [16; 17) '1': u32 |
3151 | [16; 21) '1 + 1': u32 | 3109 | [16; 21) '1 + 1': u32 |
3152 | [20; 21) '1': u32 | 3110 | [20; 21) '1': u32 |
@@ -3170,7 +3128,6 @@ fn test() -> u64 { | |||
3170 | } | 3128 | } |
3171 | "#), | 3129 | "#), |
3172 | @r###" | 3130 | @r###" |
3173 | |||
3174 | [38; 87) '{ ... a.1 }': u64 | 3131 | [38; 87) '{ ... a.1 }': u64 |
3175 | [48; 49) 'a': S | 3132 | [48; 49) 'a': S |
3176 | [52; 53) 'S': S(i32, u64) -> S | 3133 | [52; 53) 'S': S(i32, u64) -> S |
@@ -3225,7 +3182,6 @@ fn indexing_arrays() { | |||
3225 | assert_snapshot!( | 3182 | assert_snapshot!( |
3226 | infer("fn main() { &mut [9][2]; }"), | 3183 | infer("fn main() { &mut [9][2]; }"), |
3227 | @r###" | 3184 | @r###" |
3228 | |||
3229 | [10; 26) '{ &mut...[2]; }': () | 3185 | [10; 26) '{ &mut...[2]; }': () |
3230 | [12; 23) '&mut [9][2]': &mut {unknown} | 3186 | [12; 23) '&mut [9][2]': &mut {unknown} |
3231 | [17; 20) '[9]': [i32;_] | 3187 | [17; 20) '[9]': [i32;_] |
@@ -4822,9 +4778,9 @@ fn main() { | |||
4822 | } | 4778 | } |
4823 | "#), | 4779 | "#), |
4824 | @r###" | 4780 | @r###" |
4825 | ![0; 1) '6': i32 | 4781 | ![0; 1) '6': i32 |
4826 | [64; 88) '{ ...!(); }': () | 4782 | [64; 88) '{ ...!(); }': () |
4827 | [74; 75) 'x': i32 | 4783 | [74; 75) 'x': i32 |
4828 | "### | 4784 | "### |
4829 | ); | 4785 | ); |
4830 | } | 4786 | } |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 09a39e721..10cb87d37 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -67,6 +67,11 @@ impl ExprScopes { | |||
67 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) | 67 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) |
68 | } | 68 | } |
69 | 69 | ||
70 | pub fn resolve_name_in_scope(&self, scope: ScopeId, name: &Name) -> Option<&ScopeEntry> { | ||
71 | self.scope_chain(Some(scope)) | ||
72 | .find_map(|scope| self.entries(scope).iter().find(|it| it.name == *name)) | ||
73 | } | ||
74 | |||
70 | pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { | 75 | pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { |
71 | self.scope_by_expr.get(&expr).copied() | 76 | self.scope_by_expr.get(&expr).copied() |
72 | } | 77 | } |
@@ -163,3 +168,217 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
163 | e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), | 168 | e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), |
164 | }; | 169 | }; |
165 | } | 170 | } |
171 | |||
172 | #[cfg(test)] | ||
173 | mod tests { | ||
174 | use hir_expand::{name::AsName, Source}; | ||
175 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; | ||
176 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | ||
177 | use test_utils::{assert_eq_text, extract_offset}; | ||
178 | |||
179 | use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; | ||
180 | |||
181 | fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { | ||
182 | let krate = db.test_crate(); | ||
183 | let crate_def_map = db.crate_def_map(krate); | ||
184 | |||
185 | let module = crate_def_map.modules_for_file(file_id).next().unwrap(); | ||
186 | let (_, res) = crate_def_map[module].scope.entries().next().unwrap(); | ||
187 | match res.def.take_values().unwrap() { | ||
188 | ModuleDefId::FunctionId(it) => it, | ||
189 | _ => panic!(), | ||
190 | } | ||
191 | } | ||
192 | |||
193 | fn do_check(code: &str, expected: &[&str]) { | ||
194 | let (off, code) = extract_offset(code); | ||
195 | let code = { | ||
196 | let mut buf = String::new(); | ||
197 | let off = u32::from(off) as usize; | ||
198 | buf.push_str(&code[..off]); | ||
199 | buf.push_str("marker"); | ||
200 | buf.push_str(&code[off..]); | ||
201 | buf | ||
202 | }; | ||
203 | |||
204 | let (db, file_id) = TestDB::with_single_file(&code); | ||
205 | |||
206 | let file_syntax = db.parse(file_id).syntax_node(); | ||
207 | let marker: ast::PathExpr = find_node_at_offset(&file_syntax, off).unwrap(); | ||
208 | let function = find_function(&db, file_id); | ||
209 | |||
210 | let scopes = db.expr_scopes(function.into()); | ||
211 | let (_body, source_map) = db.body_with_source_map(function.into()); | ||
212 | |||
213 | let expr_id = | ||
214 | source_map.node_expr(Source { file_id: file_id.into(), ast: &marker.into() }).unwrap(); | ||
215 | let scope = scopes.scope_for(expr_id); | ||
216 | |||
217 | let actual = scopes | ||
218 | .scope_chain(scope) | ||
219 | .flat_map(|scope| scopes.entries(scope)) | ||
220 | .map(|it| it.name().to_string()) | ||
221 | .collect::<Vec<_>>() | ||
222 | .join("\n"); | ||
223 | let expected = expected.join("\n"); | ||
224 | assert_eq_text!(&expected, &actual); | ||
225 | } | ||
226 | |||
227 | #[test] | ||
228 | fn test_lambda_scope() { | ||
229 | do_check( | ||
230 | r" | ||
231 | fn quux(foo: i32) { | ||
232 | let f = |bar, baz: i32| { | ||
233 | <|> | ||
234 | }; | ||
235 | }", | ||
236 | &["bar", "baz", "foo"], | ||
237 | ); | ||
238 | } | ||
239 | |||
240 | #[test] | ||
241 | fn test_call_scope() { | ||
242 | do_check( | ||
243 | r" | ||
244 | fn quux() { | ||
245 | f(|x| <|> ); | ||
246 | }", | ||
247 | &["x"], | ||
248 | ); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn test_method_call_scope() { | ||
253 | do_check( | ||
254 | r" | ||
255 | fn quux() { | ||
256 | z.f(|x| <|> ); | ||
257 | }", | ||
258 | &["x"], | ||
259 | ); | ||
260 | } | ||
261 | |||
262 | #[test] | ||
263 | fn test_loop_scope() { | ||
264 | do_check( | ||
265 | r" | ||
266 | fn quux() { | ||
267 | loop { | ||
268 | let x = (); | ||
269 | <|> | ||
270 | }; | ||
271 | }", | ||
272 | &["x"], | ||
273 | ); | ||
274 | } | ||
275 | |||
276 | #[test] | ||
277 | fn test_match() { | ||
278 | do_check( | ||
279 | r" | ||
280 | fn quux() { | ||
281 | match () { | ||
282 | Some(x) => { | ||
283 | <|> | ||
284 | } | ||
285 | }; | ||
286 | }", | ||
287 | &["x"], | ||
288 | ); | ||
289 | } | ||
290 | |||
291 | #[test] | ||
292 | fn test_shadow_variable() { | ||
293 | do_check( | ||
294 | r" | ||
295 | fn foo(x: String) { | ||
296 | let x : &str = &x<|>; | ||
297 | }", | ||
298 | &["x"], | ||
299 | ); | ||
300 | } | ||
301 | |||
302 | fn do_check_local_name(code: &str, expected_offset: u32) { | ||
303 | let (off, code) = extract_offset(code); | ||
304 | |||
305 | let (db, file_id) = TestDB::with_single_file(&code); | ||
306 | |||
307 | let file = db.parse(file_id).ok().unwrap(); | ||
308 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) | ||
309 | .expect("failed to find a name at the target offset"); | ||
310 | let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | ||
311 | |||
312 | let function = find_function(&db, file_id); | ||
313 | |||
314 | let scopes = db.expr_scopes(function.into()); | ||
315 | let (_body, source_map) = db.body_with_source_map(function.into()); | ||
316 | |||
317 | let expr_scope = { | ||
318 | let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); | ||
319 | let expr_id = | ||
320 | source_map.node_expr(Source { file_id: file_id.into(), ast: &expr_ast }).unwrap(); | ||
321 | scopes.scope_for(expr_id).unwrap() | ||
322 | }; | ||
323 | |||
324 | let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); | ||
325 | let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); | ||
326 | |||
327 | let local_name = pat_src.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); | ||
328 | assert_eq!(local_name.range(), expected_name.syntax().text_range()); | ||
329 | } | ||
330 | |||
331 | #[test] | ||
332 | fn test_resolve_local_name() { | ||
333 | do_check_local_name( | ||
334 | r#" | ||
335 | fn foo(x: i32, y: u32) { | ||
336 | { | ||
337 | let z = x * 2; | ||
338 | } | ||
339 | { | ||
340 | let t = x<|> * 3; | ||
341 | } | ||
342 | }"#, | ||
343 | 21, | ||
344 | ); | ||
345 | } | ||
346 | |||
347 | #[test] | ||
348 | fn test_resolve_local_name_declaration() { | ||
349 | do_check_local_name( | ||
350 | r#" | ||
351 | fn foo(x: String) { | ||
352 | let x : &str = &x<|>; | ||
353 | }"#, | ||
354 | 21, | ||
355 | ); | ||
356 | } | ||
357 | |||
358 | #[test] | ||
359 | fn test_resolve_local_name_shadow() { | ||
360 | do_check_local_name( | ||
361 | r" | ||
362 | fn foo(x: String) { | ||
363 | let x : &str = &x; | ||
364 | x<|> | ||
365 | } | ||
366 | ", | ||
367 | 53, | ||
368 | ); | ||
369 | } | ||
370 | |||
371 | #[test] | ||
372 | fn ref_patterns_contribute_bindings() { | ||
373 | do_check_local_name( | ||
374 | r" | ||
375 | fn foo() { | ||
376 | if let Some(&from) = bar() { | ||
377 | from<|>; | ||
378 | } | ||
379 | } | ||
380 | ", | ||
381 | 53, | ||
382 | ); | ||
383 | } | ||
384 | } | ||
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index d3ecabb9b..21d5f62e0 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -58,7 +58,7 @@ mod tests; | |||
58 | 58 | ||
59 | use std::sync::Arc; | 59 | use std::sync::Arc; |
60 | 60 | ||
61 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, MacroDefId}; | 61 | use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; |
62 | use once_cell::sync::Lazy; | 62 | use once_cell::sync::Lazy; |
63 | use ra_arena::Arena; | 63 | use ra_arena::Arena; |
64 | use ra_db::{CrateId, Edition, FileId}; | 64 | use ra_db::{CrateId, Edition, FileId}; |
@@ -73,7 +73,7 @@ use crate::{ | |||
73 | diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId, | 73 | diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId, |
74 | }, | 74 | }, |
75 | path::Path, | 75 | path::Path, |
76 | AstId, CrateModuleId, ModuleDefId, ModuleId, TraitId, | 76 | AstId, CrateModuleId, FunctionId, ModuleDefId, ModuleId, TraitId, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /// Contains all top-level defs from a macro-expanded crate | 79 | /// Contains all top-level defs from a macro-expanded crate |
@@ -87,7 +87,7 @@ pub struct CrateDefMap { | |||
87 | prelude: Option<ModuleId>, | 87 | prelude: Option<ModuleId>, |
88 | extern_prelude: FxHashMap<Name, ModuleDefId>, | 88 | extern_prelude: FxHashMap<Name, ModuleDefId>, |
89 | root: CrateModuleId, | 89 | root: CrateModuleId, |
90 | pub modules: Arena<CrateModuleId, ModuleData>, | 90 | modules: Arena<CrateModuleId, ModuleData>, |
91 | 91 | ||
92 | /// Some macros are not well-behavior, which leads to infinite loop | 92 | /// Some macros are not well-behavior, which leads to infinite loop |
93 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } | 93 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } |
@@ -124,6 +124,11 @@ pub struct ModuleData { | |||
124 | pub definition: Option<FileId>, | 124 | pub definition: Option<FileId>, |
125 | } | 125 | } |
126 | 126 | ||
127 | #[derive(Default, Debug, PartialEq, Eq, Clone)] | ||
128 | pub(crate) struct Declarations { | ||
129 | fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>, | ||
130 | } | ||
131 | |||
127 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 132 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
128 | pub struct ModuleScope { | 133 | pub struct ModuleScope { |
129 | pub items: FxHashMap<Name, Resolution>, | 134 | pub items: FxHashMap<Name, Resolution>, |
@@ -258,6 +263,17 @@ impl CrateDefMap { | |||
258 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); | 263 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); |
259 | (res.resolved_def, res.segment_index) | 264 | (res.resolved_def, res.segment_index) |
260 | } | 265 | } |
266 | |||
267 | pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { | ||
268 | self.modules.iter().map(|(id, _data)| id) | ||
269 | } | ||
270 | |||
271 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { | ||
272 | self.modules | ||
273 | .iter() | ||
274 | .filter(move |(_id, data)| data.definition == Some(file_id)) | ||
275 | .map(|(id, _data)| id) | ||
276 | } | ||
261 | } | 277 | } |
262 | 278 | ||
263 | mod diagnostics { | 279 | mod diagnostics { |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 37d0f3093..5c899aff3 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -664,7 +664,8 @@ where | |||
664 | let name = def.name.clone(); | 664 | let name = def.name.clone(); |
665 | let def: PerNs = match def.kind { | 665 | let def: PerNs = match def.kind { |
666 | raw::DefKind::Function(ast_id) => { | 666 | raw::DefKind::Function(ast_id) => { |
667 | PerNs::values(FunctionId::from_ast_id(ctx, ast_id).into()) | 667 | let f = FunctionId::from_ast_id(ctx, ast_id); |
668 | PerNs::values(f.into()) | ||
668 | } | 669 | } |
669 | raw::DefKind::Struct(ast_id) => { | 670 | raw::DefKind::Struct(ast_id) => { |
670 | let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); | 671 | let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); |
@@ -798,7 +799,7 @@ mod tests { | |||
798 | 799 | ||
799 | fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { | 800 | fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { |
800 | let (db, _file_id) = TestDB::with_single_file(&code); | 801 | let (db, _file_id) = TestDB::with_single_file(&code); |
801 | let krate = db.crate_graph().iter().next().unwrap(); | 802 | let krate = db.test_crate(); |
802 | 803 | ||
803 | let def_map = { | 804 | let def_map = { |
804 | let edition = db.crate_graph().edition(krate); | 805 | let edition = db.crate_graph().edition(krate); |
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 80dcec62f..903a22771 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{SourceDatabase, SourceDatabaseExt}; | 3 | use ra_db::SourceDatabaseExt; |
4 | 4 | ||
5 | use super::*; | 5 | use super::*; |
6 | 6 | ||
7 | fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { | 7 | fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { |
8 | let (mut db, pos) = TestDB::with_position(initial); | 8 | let (mut db, pos) = TestDB::with_position(initial); |
9 | let krate = db.crate_graph().iter().next().unwrap(); | 9 | let krate = db.test_crate(); |
10 | { | 10 | { |
11 | let events = db.log_executed(|| { | 11 | let events = db.log_executed(|| { |
12 | db.crate_def_map(krate); | 12 | db.crate_def_map(krate); |
@@ -111,7 +111,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { | |||
111 | m!(X); | 111 | m!(X); |
112 | ", | 112 | ", |
113 | ); | 113 | ); |
114 | let krate = db.crate_graph().iter().next().unwrap(); | 114 | let krate = db.test_crate(); |
115 | { | 115 | { |
116 | let events = db.log_executed(|| { | 116 | let events = db.log_executed(|| { |
117 | let crate_def_map = db.crate_def_map(krate); | 117 | let crate_def_map = db.crate_def_map(krate); |
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index dee364a14..eb7b85c07 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -656,7 +656,7 @@ fn unresolved_module_diagnostics() { | |||
656 | //- /foo.rs | 656 | //- /foo.rs |
657 | ", | 657 | ", |
658 | ); | 658 | ); |
659 | let krate = db.crate_graph().iter().next().unwrap(); | 659 | let krate = db.test_crate(); |
660 | 660 | ||
661 | let crate_def_map = db.crate_def_map(krate); | 661 | let crate_def_map = db.crate_def_map(krate); |
662 | 662 | ||
diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 9cd17f0e3..35133d216 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs | |||
@@ -241,10 +241,8 @@ mod tests { | |||
241 | // } | 241 | // } |
242 | let struct_name = mk_ident("Foo"); | 242 | let struct_name = mk_ident("Foo"); |
243 | let fields = [mk_ident("name"), mk_ident("id")]; | 243 | let fields = [mk_ident("name"), mk_ident("id")]; |
244 | let fields = fields | 244 | let fields = |
245 | .into_iter() | 245 | fields.iter().map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()).flatten(); |
246 | .map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()) | ||
247 | .flatten(); | ||
248 | 246 | ||
249 | let list = tt::Subtree { delimiter: tt::Delimiter::Brace, token_trees: fields.collect() }; | 247 | let list = tt::Subtree { delimiter: tt::Delimiter::Brace, token_trees: fields.collect() }; |
250 | 248 | ||
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index b4df6ee2a..4e2c497e1 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -88,16 +88,16 @@ mod tests { | |||
88 | ", | 88 | ", |
89 | ), | 89 | ), |
90 | @r###" | 90 | @r###" |
91 | ⋮[ | 91 | [ |
92 | ⋮ CompletionItem { | 92 | CompletionItem { |
93 | ⋮ label: "the_field", | 93 | label: "the_field", |
94 | ⋮ source_range: [94; 94), | 94 | source_range: [94; 94), |
95 | ⋮ delete: [94; 94), | 95 | delete: [94; 94), |
96 | ⋮ insert: "the_field", | 96 | insert: "the_field", |
97 | ⋮ kind: Field, | 97 | kind: Field, |
98 | ⋮ detail: "u32", | 98 | detail: "u32", |
99 | ⋮ }, | 99 | }, |
100 | ⋮] | 100 | ] |
101 | "### | 101 | "### |
102 | ); | 102 | ); |
103 | } | 103 | } |
@@ -349,24 +349,24 @@ mod tests { | |||
349 | ", | 349 | ", |
350 | ), | 350 | ), |
351 | @r###" | 351 | @r###" |
352 | ⋮[ | 352 | [ |
353 | ⋮ CompletionItem { | 353 | CompletionItem { |
354 | ⋮ label: "0", | 354 | label: "0", |
355 | ⋮ source_range: [75; 75), | 355 | source_range: [75; 75), |
356 | ⋮ delete: [75; 75), | 356 | delete: [75; 75), |
357 | ⋮ insert: "0", | 357 | insert: "0", |
358 | ⋮ kind: Field, | 358 | kind: Field, |
359 | ⋮ detail: "i32", | 359 | detail: "i32", |
360 | ⋮ }, | 360 | }, |
361 | ⋮ CompletionItem { | 361 | CompletionItem { |
362 | ⋮ label: "1", | 362 | label: "1", |
363 | ⋮ source_range: [75; 75), | 363 | source_range: [75; 75), |
364 | ⋮ delete: [75; 75), | 364 | delete: [75; 75), |
365 | ⋮ insert: "1", | 365 | insert: "1", |
366 | ⋮ kind: Field, | 366 | kind: Field, |
367 | ⋮ detail: "f64", | 367 | detail: "f64", |
368 | ⋮ }, | 368 | }, |
369 | ⋮] | 369 | ] |
370 | "### | 370 | "### |
371 | ); | 371 | ); |
372 | } | 372 | } |
@@ -419,16 +419,16 @@ mod tests { | |||
419 | ", | 419 | ", |
420 | ), | 420 | ), |
421 | @r###" | 421 | @r###" |
422 | ⋮[ | 422 | [ |
423 | ⋮ CompletionItem { | 423 | CompletionItem { |
424 | ⋮ label: "the_field", | 424 | label: "the_field", |
425 | ⋮ source_range: [106; 106), | 425 | source_range: [106; 106), |
426 | ⋮ delete: [106; 106), | 426 | delete: [106; 106), |
427 | ⋮ insert: "the_field", | 427 | insert: "the_field", |
428 | ⋮ kind: Field, | 428 | kind: Field, |
429 | ⋮ detail: "u32", | 429 | detail: "u32", |
430 | ⋮ }, | 430 | }, |
431 | ⋮] | 431 | ] |
432 | "### | 432 | "### |
433 | ); | 433 | ); |
434 | } | 434 | } |
@@ -452,15 +452,15 @@ mod tests { | |||
452 | } | 452 | } |
453 | "###, CompletionKind::Keyword), | 453 | "###, CompletionKind::Keyword), |
454 | @r###" | 454 | @r###" |
455 | ⋮[ | 455 | [ |
456 | ⋮ CompletionItem { | 456 | CompletionItem { |
457 | ⋮ label: "await", | 457 | label: "await", |
458 | ⋮ source_range: [74; 74), | 458 | source_range: [74; 74), |
459 | ⋮ delete: [74; 74), | 459 | delete: [74; 74), |
460 | ⋮ insert: "await", | 460 | insert: "await", |
461 | ⋮ detail: "expr.await", | 461 | detail: "expr.await", |
462 | ⋮ }, | 462 | }, |
463 | ⋮] | 463 | ] |
464 | "### | 464 | "### |
465 | ) | 465 | ) |
466 | } | 466 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs index 3e936e3ec..502458706 100644 --- a/crates/ra_ide_api/src/completion/complete_fn_param.rs +++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs | |||
@@ -70,15 +70,15 @@ mod tests { | |||
70 | ", | 70 | ", |
71 | ), | 71 | ), |
72 | @r###" | 72 | @r###" |
73 | ⋮[ | 73 | [ |
74 | ⋮ CompletionItem { | 74 | CompletionItem { |
75 | ⋮ label: "file_id: FileId", | 75 | label: "file_id: FileId", |
76 | ⋮ source_range: [110; 114), | 76 | source_range: [110; 114), |
77 | ⋮ delete: [110; 114), | 77 | delete: [110; 114), |
78 | ⋮ insert: "file_id: FileId", | 78 | insert: "file_id: FileId", |
79 | ⋮ lookup: "file_id", | 79 | lookup: "file_id", |
80 | ⋮ }, | 80 | }, |
81 | ⋮] | 81 | ] |
82 | "### | 82 | "### |
83 | ); | 83 | ); |
84 | } | 84 | } |
@@ -94,15 +94,15 @@ mod tests { | |||
94 | ", | 94 | ", |
95 | ), | 95 | ), |
96 | @r###" | 96 | @r###" |
97 | ⋮[ | 97 | [ |
98 | ⋮ CompletionItem { | 98 | CompletionItem { |
99 | ⋮ label: "file_id: FileId", | 99 | label: "file_id: FileId", |
100 | ⋮ source_range: [110; 114), | 100 | source_range: [110; 114), |
101 | ⋮ delete: [110; 114), | 101 | delete: [110; 114), |
102 | ⋮ insert: "file_id: FileId", | 102 | insert: "file_id: FileId", |
103 | ⋮ lookup: "file_id", | 103 | lookup: "file_id", |
104 | ⋮ }, | 104 | }, |
105 | ⋮] | 105 | ] |
106 | "### | 106 | "### |
107 | ); | 107 | ); |
108 | } | 108 | } |
@@ -121,15 +121,15 @@ mod tests { | |||
121 | ", | 121 | ", |
122 | ), | 122 | ), |
123 | @r###" | 123 | @r###" |
124 | ⋮[ | 124 | [ |
125 | ⋮ CompletionItem { | 125 | CompletionItem { |
126 | ⋮ label: "file_id: FileId", | 126 | label: "file_id: FileId", |
127 | ⋮ source_range: [289; 293), | 127 | source_range: [289; 293), |
128 | ⋮ delete: [289; 293), | 128 | delete: [289; 293), |
129 | ⋮ insert: "file_id: FileId", | 129 | insert: "file_id: FileId", |
130 | ⋮ lookup: "file_id", | 130 | lookup: "file_id", |
131 | ⋮ }, | 131 | }, |
132 | ⋮] | 132 | ] |
133 | "### | 133 | "### |
134 | ); | 134 | ); |
135 | } | 135 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide_api/src/completion/complete_keyword.rs index 48c688a08..eb7cd9ac2 100644 --- a/crates/ra_ide_api/src/completion/complete_keyword.rs +++ b/crates/ra_ide_api/src/completion/complete_keyword.rs | |||
@@ -131,29 +131,31 @@ mod tests { | |||
131 | use <|> | 131 | use <|> |
132 | ", | 132 | ", |
133 | ), | 133 | ), |
134 | @r###"[ | 134 | @r###" |
135 | CompletionItem { | 135 | [ |
136 | label: "crate", | 136 | CompletionItem { |
137 | source_range: [21; 21), | 137 | label: "crate", |
138 | delete: [21; 21), | 138 | source_range: [21; 21), |
139 | insert: "crate::", | 139 | delete: [21; 21), |
140 | kind: Keyword, | 140 | insert: "crate::", |
141 | }, | 141 | kind: Keyword, |
142 | CompletionItem { | 142 | }, |
143 | label: "self", | 143 | CompletionItem { |
144 | source_range: [21; 21), | 144 | label: "self", |
145 | delete: [21; 21), | 145 | source_range: [21; 21), |
146 | insert: "self", | 146 | delete: [21; 21), |
147 | kind: Keyword, | 147 | insert: "self", |
148 | }, | 148 | kind: Keyword, |
149 | CompletionItem { | 149 | }, |
150 | label: "super", | 150 | CompletionItem { |
151 | source_range: [21; 21), | 151 | label: "super", |
152 | delete: [21; 21), | 152 | source_range: [21; 21), |
153 | insert: "super::", | 153 | delete: [21; 21), |
154 | kind: Keyword, | 154 | insert: "super::", |
155 | }, | 155 | kind: Keyword, |
156 | ]"### | 156 | }, |
157 | ] | ||
158 | "### | ||
157 | ); | 159 | ); |
158 | 160 | ||
159 | assert_debug_snapshot!( | 161 | assert_debug_snapshot!( |
@@ -162,22 +164,24 @@ mod tests { | |||
162 | use a::<|> | 164 | use a::<|> |
163 | ", | 165 | ", |
164 | ), | 166 | ), |
165 | @r###"[ | 167 | @r###" |
166 | CompletionItem { | 168 | [ |
167 | label: "self", | 169 | CompletionItem { |
168 | source_range: [24; 24), | 170 | label: "self", |
169 | delete: [24; 24), | 171 | source_range: [24; 24), |
170 | insert: "self", | 172 | delete: [24; 24), |
171 | kind: Keyword, | 173 | insert: "self", |
172 | }, | 174 | kind: Keyword, |
173 | CompletionItem { | 175 | }, |
174 | label: "super", | 176 | CompletionItem { |
175 | source_range: [24; 24), | 177 | label: "super", |
176 | delete: [24; 24), | 178 | source_range: [24; 24), |
177 | insert: "super::", | 179 | delete: [24; 24), |
178 | kind: Keyword, | 180 | insert: "super::", |
179 | }, | 181 | kind: Keyword, |
180 | ]"### | 182 | }, |
183 | ] | ||
184 | "### | ||
181 | ); | 185 | ); |
182 | 186 | ||
183 | assert_debug_snapshot!( | 187 | assert_debug_snapshot!( |
@@ -186,22 +190,24 @@ mod tests { | |||
186 | use a::{b, <|>} | 190 | use a::{b, <|>} |
187 | ", | 191 | ", |
188 | ), | 192 | ), |
189 | @r###"[ | 193 | @r###" |
190 | CompletionItem { | 194 | [ |
191 | label: "self", | 195 | CompletionItem { |
192 | source_range: [28; 28), | 196 | label: "self", |
193 | delete: [28; 28), | 197 | source_range: [28; 28), |
194 | insert: "self", | 198 | delete: [28; 28), |
195 | kind: Keyword, | 199 | insert: "self", |
196 | }, | 200 | kind: Keyword, |
197 | CompletionItem { | 201 | }, |
198 | label: "super", | 202 | CompletionItem { |
199 | source_range: [28; 28), | 203 | label: "super", |
200 | delete: [28; 28), | 204 | source_range: [28; 28), |
201 | insert: "super::", | 205 | delete: [28; 28), |
202 | kind: Keyword, | 206 | insert: "super::", |
203 | }, | 207 | kind: Keyword, |
204 | ]"### | 208 | }, |
209 | ] | ||
210 | "### | ||
205 | ); | 211 | ); |
206 | } | 212 | } |
207 | 213 | ||
@@ -215,43 +221,45 @@ mod tests { | |||
215 | } | 221 | } |
216 | ", | 222 | ", |
217 | ), | 223 | ), |
218 | @r###"[ | 224 | @r###" |
219 | CompletionItem { | 225 | [ |
220 | label: "if", | 226 | CompletionItem { |
221 | source_range: [49; 49), | 227 | label: "if", |
222 | delete: [49; 49), | 228 | source_range: [49; 49), |
223 | insert: "if $0 {}", | 229 | delete: [49; 49), |
224 | kind: Keyword, | 230 | insert: "if $0 {}", |
225 | }, | 231 | kind: Keyword, |
226 | CompletionItem { | 232 | }, |
227 | label: "loop", | 233 | CompletionItem { |
228 | source_range: [49; 49), | 234 | label: "loop", |
229 | delete: [49; 49), | 235 | source_range: [49; 49), |
230 | insert: "loop {$0}", | 236 | delete: [49; 49), |
231 | kind: Keyword, | 237 | insert: "loop {$0}", |
232 | }, | 238 | kind: Keyword, |
233 | CompletionItem { | 239 | }, |
234 | label: "match", | 240 | CompletionItem { |
235 | source_range: [49; 49), | 241 | label: "match", |
236 | delete: [49; 49), | 242 | source_range: [49; 49), |
237 | insert: "match $0 {}", | 243 | delete: [49; 49), |
238 | kind: Keyword, | 244 | insert: "match $0 {}", |
239 | }, | 245 | kind: Keyword, |
240 | CompletionItem { | 246 | }, |
241 | label: "return", | 247 | CompletionItem { |
242 | source_range: [49; 49), | 248 | label: "return", |
243 | delete: [49; 49), | 249 | source_range: [49; 49), |
244 | insert: "return;", | 250 | delete: [49; 49), |
245 | kind: Keyword, | 251 | insert: "return;", |
246 | }, | 252 | kind: Keyword, |
247 | CompletionItem { | 253 | }, |
248 | label: "while", | 254 | CompletionItem { |
249 | source_range: [49; 49), | 255 | label: "while", |
250 | delete: [49; 49), | 256 | source_range: [49; 49), |
251 | insert: "while $0 {}", | 257 | delete: [49; 49), |
252 | kind: Keyword, | 258 | insert: "while $0 {}", |
253 | }, | 259 | kind: Keyword, |
254 | ]"### | 260 | }, |
261 | ] | ||
262 | "### | ||
255 | ); | 263 | ); |
256 | } | 264 | } |
257 | 265 | ||
@@ -267,57 +275,59 @@ mod tests { | |||
267 | } | 275 | } |
268 | ", | 276 | ", |
269 | ), | 277 | ), |
270 | @r###"[ | 278 | @r###" |
271 | CompletionItem { | 279 | [ |
272 | label: "else", | 280 | CompletionItem { |
273 | source_range: [108; 108), | 281 | label: "else", |
274 | delete: [108; 108), | 282 | source_range: [108; 108), |
275 | insert: "else {$0}", | 283 | delete: [108; 108), |
276 | kind: Keyword, | 284 | insert: "else {$0}", |
277 | }, | 285 | kind: Keyword, |
278 | CompletionItem { | 286 | }, |
279 | label: "else if", | 287 | CompletionItem { |
280 | source_range: [108; 108), | 288 | label: "else if", |
281 | delete: [108; 108), | 289 | source_range: [108; 108), |
282 | insert: "else if $0 {}", | 290 | delete: [108; 108), |
283 | kind: Keyword, | 291 | insert: "else if $0 {}", |
284 | }, | 292 | kind: Keyword, |
285 | CompletionItem { | 293 | }, |
286 | label: "if", | 294 | CompletionItem { |
287 | source_range: [108; 108), | 295 | label: "if", |
288 | delete: [108; 108), | 296 | source_range: [108; 108), |
289 | insert: "if $0 {}", | 297 | delete: [108; 108), |
290 | kind: Keyword, | 298 | insert: "if $0 {}", |
291 | }, | 299 | kind: Keyword, |
292 | CompletionItem { | 300 | }, |
293 | label: "loop", | 301 | CompletionItem { |
294 | source_range: [108; 108), | 302 | label: "loop", |
295 | delete: [108; 108), | 303 | source_range: [108; 108), |
296 | insert: "loop {$0}", | 304 | delete: [108; 108), |
297 | kind: Keyword, | 305 | insert: "loop {$0}", |
298 | }, | 306 | kind: Keyword, |
299 | CompletionItem { | 307 | }, |
300 | label: "match", | 308 | CompletionItem { |
301 | source_range: [108; 108), | 309 | label: "match", |
302 | delete: [108; 108), | 310 | source_range: [108; 108), |
303 | insert: "match $0 {}", | 311 | delete: [108; 108), |
304 | kind: Keyword, | 312 | insert: "match $0 {}", |
305 | }, | 313 | kind: Keyword, |
306 | CompletionItem { | 314 | }, |
307 | label: "return", | 315 | CompletionItem { |
308 | source_range: [108; 108), | 316 | label: "return", |
309 | delete: [108; 108), | 317 | source_range: [108; 108), |
310 | insert: "return;", | 318 | delete: [108; 108), |
311 | kind: Keyword, | 319 | insert: "return;", |
312 | }, | 320 | kind: Keyword, |
313 | CompletionItem { | 321 | }, |
314 | label: "while", | 322 | CompletionItem { |
315 | source_range: [108; 108), | 323 | label: "while", |
316 | delete: [108; 108), | 324 | source_range: [108; 108), |
317 | insert: "while $0 {}", | 325 | delete: [108; 108), |
318 | kind: Keyword, | 326 | insert: "while $0 {}", |
319 | }, | 327 | kind: Keyword, |
320 | ]"### | 328 | }, |
329 | ] | ||
330 | "### | ||
321 | ); | 331 | ); |
322 | } | 332 | } |
323 | 333 | ||
@@ -332,43 +342,45 @@ mod tests { | |||
332 | } | 342 | } |
333 | ", | 343 | ", |
334 | ), | 344 | ), |
335 | @r###"[ | 345 | @r###" |
336 | CompletionItem { | 346 | [ |
337 | label: "if", | 347 | CompletionItem { |
338 | source_range: [56; 56), | 348 | label: "if", |
339 | delete: [56; 56), | 349 | source_range: [56; 56), |
340 | insert: "if $0 {}", | 350 | delete: [56; 56), |
341 | kind: Keyword, | 351 | insert: "if $0 {}", |
342 | }, | 352 | kind: Keyword, |
343 | CompletionItem { | 353 | }, |
344 | label: "loop", | 354 | CompletionItem { |
345 | source_range: [56; 56), | 355 | label: "loop", |
346 | delete: [56; 56), | 356 | source_range: [56; 56), |
347 | insert: "loop {$0}", | 357 | delete: [56; 56), |
348 | kind: Keyword, | 358 | insert: "loop {$0}", |
349 | }, | 359 | kind: Keyword, |
350 | CompletionItem { | 360 | }, |
351 | label: "match", | 361 | CompletionItem { |
352 | source_range: [56; 56), | 362 | label: "match", |
353 | delete: [56; 56), | 363 | source_range: [56; 56), |
354 | insert: "match $0 {}", | 364 | delete: [56; 56), |
355 | kind: Keyword, | 365 | insert: "match $0 {}", |
356 | }, | 366 | kind: Keyword, |
357 | CompletionItem { | 367 | }, |
358 | label: "return", | 368 | CompletionItem { |
359 | source_range: [56; 56), | 369 | label: "return", |
360 | delete: [56; 56), | 370 | source_range: [56; 56), |
361 | insert: "return $0;", | 371 | delete: [56; 56), |
362 | kind: Keyword, | 372 | insert: "return $0;", |
363 | }, | 373 | kind: Keyword, |
364 | CompletionItem { | 374 | }, |
365 | label: "while", | 375 | CompletionItem { |
366 | source_range: [56; 56), | 376 | label: "while", |
367 | delete: [56; 56), | 377 | source_range: [56; 56), |
368 | insert: "while $0 {}", | 378 | delete: [56; 56), |
369 | kind: Keyword, | 379 | insert: "while $0 {}", |
370 | }, | 380 | kind: Keyword, |
371 | ]"### | 381 | }, |
382 | ] | ||
383 | "### | ||
372 | ); | 384 | ); |
373 | assert_debug_snapshot!( | 385 | assert_debug_snapshot!( |
374 | do_keyword_completion( | 386 | do_keyword_completion( |
@@ -379,43 +391,45 @@ mod tests { | |||
379 | } | 391 | } |
380 | ", | 392 | ", |
381 | ), | 393 | ), |
382 | @r###"[ | 394 | @r###" |
383 | CompletionItem { | 395 | [ |
384 | label: "if", | 396 | CompletionItem { |
385 | source_range: [49; 49), | 397 | label: "if", |
386 | delete: [49; 49), | 398 | source_range: [49; 49), |
387 | insert: "if $0 {}", | 399 | delete: [49; 49), |
388 | kind: Keyword, | 400 | insert: "if $0 {}", |
389 | }, | 401 | kind: Keyword, |
390 | CompletionItem { | 402 | }, |
391 | label: "loop", | 403 | CompletionItem { |
392 | source_range: [49; 49), | 404 | label: "loop", |
393 | delete: [49; 49), | 405 | source_range: [49; 49), |
394 | insert: "loop {$0}", | 406 | delete: [49; 49), |
395 | kind: Keyword, | 407 | insert: "loop {$0}", |
396 | }, | 408 | kind: Keyword, |
397 | CompletionItem { | 409 | }, |
398 | label: "match", | 410 | CompletionItem { |
399 | source_range: [49; 49), | 411 | label: "match", |
400 | delete: [49; 49), | 412 | source_range: [49; 49), |
401 | insert: "match $0 {}", | 413 | delete: [49; 49), |
402 | kind: Keyword, | 414 | insert: "match $0 {}", |
403 | }, | 415 | kind: Keyword, |
404 | CompletionItem { | 416 | }, |
405 | label: "return", | 417 | CompletionItem { |
406 | source_range: [49; 49), | 418 | label: "return", |
407 | delete: [49; 49), | 419 | source_range: [49; 49), |
408 | insert: "return;", | 420 | delete: [49; 49), |
409 | kind: Keyword, | 421 | insert: "return;", |
410 | }, | 422 | kind: Keyword, |
411 | CompletionItem { | 423 | }, |
412 | label: "while", | 424 | CompletionItem { |
413 | source_range: [49; 49), | 425 | label: "while", |
414 | delete: [49; 49), | 426 | source_range: [49; 49), |
415 | insert: "while $0 {}", | 427 | delete: [49; 49), |
416 | kind: Keyword, | 428 | insert: "while $0 {}", |
417 | }, | 429 | kind: Keyword, |
418 | ]"### | 430 | }, |
431 | ] | ||
432 | "### | ||
419 | ); | 433 | ); |
420 | } | 434 | } |
421 | 435 | ||
@@ -431,43 +445,45 @@ mod tests { | |||
431 | } | 445 | } |
432 | ", | 446 | ", |
433 | ), | 447 | ), |
434 | @r###"[ | 448 | @r###" |
435 | CompletionItem { | 449 | [ |
436 | label: "if", | 450 | CompletionItem { |
437 | source_range: [97; 97), | 451 | label: "if", |
438 | delete: [97; 97), | 452 | source_range: [97; 97), |
439 | insert: "if $0 {}", | 453 | delete: [97; 97), |
440 | kind: Keyword, | 454 | insert: "if $0 {}", |
441 | }, | 455 | kind: Keyword, |
442 | CompletionItem { | 456 | }, |
443 | label: "loop", | 457 | CompletionItem { |
444 | source_range: [97; 97), | 458 | label: "loop", |
445 | delete: [97; 97), | 459 | source_range: [97; 97), |
446 | insert: "loop {$0}", | 460 | delete: [97; 97), |
447 | kind: Keyword, | 461 | insert: "loop {$0}", |
448 | }, | 462 | kind: Keyword, |
449 | CompletionItem { | 463 | }, |
450 | label: "match", | 464 | CompletionItem { |
451 | source_range: [97; 97), | 465 | label: "match", |
452 | delete: [97; 97), | 466 | source_range: [97; 97), |
453 | insert: "match $0 {}", | 467 | delete: [97; 97), |
454 | kind: Keyword, | 468 | insert: "match $0 {}", |
455 | }, | 469 | kind: Keyword, |
456 | CompletionItem { | 470 | }, |
457 | label: "return", | 471 | CompletionItem { |
458 | source_range: [97; 97), | 472 | label: "return", |
459 | delete: [97; 97), | 473 | source_range: [97; 97), |
460 | insert: "return $0", | 474 | delete: [97; 97), |
461 | kind: Keyword, | 475 | insert: "return $0", |
462 | }, | 476 | kind: Keyword, |
463 | CompletionItem { | 477 | }, |
464 | label: "while", | 478 | CompletionItem { |
465 | source_range: [97; 97), | 479 | label: "while", |
466 | delete: [97; 97), | 480 | source_range: [97; 97), |
467 | insert: "while $0 {}", | 481 | delete: [97; 97), |
468 | kind: Keyword, | 482 | insert: "while $0 {}", |
469 | }, | 483 | kind: Keyword, |
470 | ]"### | 484 | }, |
485 | ] | ||
486 | "### | ||
471 | ); | 487 | ); |
472 | } | 488 | } |
473 | 489 | ||
@@ -483,43 +499,45 @@ mod tests { | |||
483 | } | 499 | } |
484 | ", | 500 | ", |
485 | ), | 501 | ), |
486 | @r###"[ | 502 | @r###" |
487 | CompletionItem { | 503 | [ |
488 | label: "if", | 504 | CompletionItem { |
489 | source_range: [95; 95), | 505 | label: "if", |
490 | delete: [95; 95), | 506 | source_range: [95; 95), |
491 | insert: "if $0 {}", | 507 | delete: [95; 95), |
492 | kind: Keyword, | 508 | insert: "if $0 {}", |
493 | }, | 509 | kind: Keyword, |
494 | CompletionItem { | 510 | }, |
495 | label: "loop", | 511 | CompletionItem { |
496 | source_range: [95; 95), | 512 | label: "loop", |
497 | delete: [95; 95), | 513 | source_range: [95; 95), |
498 | insert: "loop {$0}", | 514 | delete: [95; 95), |
499 | kind: Keyword, | 515 | insert: "loop {$0}", |
500 | }, | 516 | kind: Keyword, |
501 | CompletionItem { | 517 | }, |
502 | label: "match", | 518 | CompletionItem { |
503 | source_range: [95; 95), | 519 | label: "match", |
504 | delete: [95; 95), | 520 | source_range: [95; 95), |
505 | insert: "match $0 {}", | 521 | delete: [95; 95), |
506 | kind: Keyword, | 522 | insert: "match $0 {}", |
507 | }, | 523 | kind: Keyword, |
508 | CompletionItem { | 524 | }, |
509 | label: "return", | 525 | CompletionItem { |
510 | source_range: [95; 95), | 526 | label: "return", |
511 | delete: [95; 95), | 527 | source_range: [95; 95), |
512 | insert: "return $0;", | 528 | delete: [95; 95), |
513 | kind: Keyword, | 529 | insert: "return $0;", |
514 | }, | 530 | kind: Keyword, |
515 | CompletionItem { | 531 | }, |
516 | label: "while", | 532 | CompletionItem { |
517 | source_range: [95; 95), | 533 | label: "while", |
518 | delete: [95; 95), | 534 | source_range: [95; 95), |
519 | insert: "while $0 {}", | 535 | delete: [95; 95), |
520 | kind: Keyword, | 536 | insert: "while $0 {}", |
521 | }, | 537 | kind: Keyword, |
522 | ]"### | 538 | }, |
539 | ] | ||
540 | "### | ||
523 | ); | 541 | ); |
524 | assert_debug_snapshot!( | 542 | assert_debug_snapshot!( |
525 | do_keyword_completion( | 543 | do_keyword_completion( |
@@ -533,43 +551,45 @@ mod tests { | |||
533 | } | 551 | } |
534 | ", | 552 | ", |
535 | ), | 553 | ), |
536 | @r###"[ | 554 | @r###" |
537 | CompletionItem { | 555 | [ |
538 | label: "if", | 556 | CompletionItem { |
539 | source_range: [95; 95), | 557 | label: "if", |
540 | delete: [95; 95), | 558 | source_range: [95; 95), |
541 | insert: "if $0 {}", | 559 | delete: [95; 95), |
542 | kind: Keyword, | 560 | insert: "if $0 {}", |
543 | }, | 561 | kind: Keyword, |
544 | CompletionItem { | 562 | }, |
545 | label: "loop", | 563 | CompletionItem { |
546 | source_range: [95; 95), | 564 | label: "loop", |
547 | delete: [95; 95), | 565 | source_range: [95; 95), |
548 | insert: "loop {$0}", | 566 | delete: [95; 95), |
549 | kind: Keyword, | 567 | insert: "loop {$0}", |
550 | }, | 568 | kind: Keyword, |
551 | CompletionItem { | 569 | }, |
552 | label: "match", | 570 | CompletionItem { |
553 | source_range: [95; 95), | 571 | label: "match", |
554 | delete: [95; 95), | 572 | source_range: [95; 95), |
555 | insert: "match $0 {}", | 573 | delete: [95; 95), |
556 | kind: Keyword, | 574 | insert: "match $0 {}", |
557 | }, | 575 | kind: Keyword, |
558 | CompletionItem { | 576 | }, |
559 | label: "return", | 577 | CompletionItem { |
560 | source_range: [95; 95), | 578 | label: "return", |
561 | delete: [95; 95), | 579 | source_range: [95; 95), |
562 | insert: "return $0;", | 580 | delete: [95; 95), |
563 | kind: Keyword, | 581 | insert: "return $0;", |
564 | }, | 582 | kind: Keyword, |
565 | CompletionItem { | 583 | }, |
566 | label: "while", | 584 | CompletionItem { |
567 | source_range: [95; 95), | 585 | label: "while", |
568 | delete: [95; 95), | 586 | source_range: [95; 95), |
569 | insert: "while $0 {}", | 587 | delete: [95; 95), |
570 | kind: Keyword, | 588 | insert: "while $0 {}", |
571 | }, | 589 | kind: Keyword, |
572 | ]"### | 590 | }, |
591 | ] | ||
592 | "### | ||
573 | ); | 593 | ); |
574 | } | 594 | } |
575 | 595 | ||
@@ -583,57 +603,59 @@ mod tests { | |||
583 | } | 603 | } |
584 | ", | 604 | ", |
585 | ), | 605 | ), |
586 | @r###"[ | 606 | @r###" |
587 | CompletionItem { | 607 | [ |
588 | label: "break", | 608 | CompletionItem { |
589 | source_range: [63; 63), | 609 | label: "break", |
590 | delete: [63; 63), | 610 | source_range: [63; 63), |
591 | insert: "break;", | 611 | delete: [63; 63), |
592 | kind: Keyword, | 612 | insert: "break;", |
593 | }, | 613 | kind: Keyword, |
594 | CompletionItem { | 614 | }, |
595 | label: "continue", | 615 | CompletionItem { |
596 | source_range: [63; 63), | 616 | label: "continue", |
597 | delete: [63; 63), | 617 | source_range: [63; 63), |
598 | insert: "continue;", | 618 | delete: [63; 63), |
599 | kind: Keyword, | 619 | insert: "continue;", |
600 | }, | 620 | kind: Keyword, |
601 | CompletionItem { | 621 | }, |
602 | label: "if", | 622 | CompletionItem { |
603 | source_range: [63; 63), | 623 | label: "if", |
604 | delete: [63; 63), | 624 | source_range: [63; 63), |
605 | insert: "if $0 {}", | 625 | delete: [63; 63), |
606 | kind: Keyword, | 626 | insert: "if $0 {}", |
607 | }, | 627 | kind: Keyword, |
608 | CompletionItem { | 628 | }, |
609 | label: "loop", | 629 | CompletionItem { |
610 | source_range: [63; 63), | 630 | label: "loop", |
611 | delete: [63; 63), | 631 | source_range: [63; 63), |
612 | insert: "loop {$0}", | 632 | delete: [63; 63), |
613 | kind: Keyword, | 633 | insert: "loop {$0}", |
614 | }, | 634 | kind: Keyword, |
615 | CompletionItem { | 635 | }, |
616 | label: "match", | 636 | CompletionItem { |
617 | source_range: [63; 63), | 637 | label: "match", |
618 | delete: [63; 63), | 638 | source_range: [63; 63), |
619 | insert: "match $0 {}", | 639 | delete: [63; 63), |
620 | kind: Keyword, | 640 | insert: "match $0 {}", |
621 | }, | 641 | kind: Keyword, |
622 | CompletionItem { | 642 | }, |
623 | label: "return", | 643 | CompletionItem { |
624 | source_range: [63; 63), | 644 | label: "return", |
625 | delete: [63; 63), | 645 | source_range: [63; 63), |
626 | insert: "return $0;", | 646 | delete: [63; 63), |
627 | kind: Keyword, | 647 | insert: "return $0;", |
628 | }, | 648 | kind: Keyword, |
629 | CompletionItem { | 649 | }, |
630 | label: "while", | 650 | CompletionItem { |
631 | source_range: [63; 63), | 651 | label: "while", |
632 | delete: [63; 63), | 652 | source_range: [63; 63), |
633 | insert: "while $0 {}", | 653 | delete: [63; 63), |
634 | kind: Keyword, | 654 | insert: "while $0 {}", |
635 | }, | 655 | kind: Keyword, |
636 | ]"### | 656 | }, |
657 | ] | ||
658 | "### | ||
637 | ); | 659 | ); |
638 | 660 | ||
639 | // No completion: lambda isolates control flow | 661 | // No completion: lambda isolates control flow |
@@ -645,43 +667,45 @@ mod tests { | |||
645 | } | 667 | } |
646 | ", | 668 | ", |
647 | ), | 669 | ), |
648 | @r###"[ | 670 | @r###" |
649 | CompletionItem { | 671 | [ |
650 | label: "if", | 672 | CompletionItem { |
651 | source_range: [68; 68), | 673 | label: "if", |
652 | delete: [68; 68), | 674 | source_range: [68; 68), |
653 | insert: "if $0 {}", | 675 | delete: [68; 68), |
654 | kind: Keyword, | 676 | insert: "if $0 {}", |
655 | }, | 677 | kind: Keyword, |
656 | CompletionItem { | 678 | }, |
657 | label: "loop", | 679 | CompletionItem { |
658 | source_range: [68; 68), | 680 | label: "loop", |
659 | delete: [68; 68), | 681 | source_range: [68; 68), |
660 | insert: "loop {$0}", | 682 | delete: [68; 68), |
661 | kind: Keyword, | 683 | insert: "loop {$0}", |
662 | }, | 684 | kind: Keyword, |
663 | CompletionItem { | 685 | }, |
664 | label: "match", | 686 | CompletionItem { |
665 | source_range: [68; 68), | 687 | label: "match", |
666 | delete: [68; 68), | 688 | source_range: [68; 68), |
667 | insert: "match $0 {}", | 689 | delete: [68; 68), |
668 | kind: Keyword, | 690 | insert: "match $0 {}", |
669 | }, | 691 | kind: Keyword, |
670 | CompletionItem { | 692 | }, |
671 | label: "return", | 693 | CompletionItem { |
672 | source_range: [68; 68), | 694 | label: "return", |
673 | delete: [68; 68), | 695 | source_range: [68; 68), |
674 | insert: "return $0;", | 696 | delete: [68; 68), |
675 | kind: Keyword, | 697 | insert: "return $0;", |
676 | }, | 698 | kind: Keyword, |
677 | CompletionItem { | 699 | }, |
678 | label: "while", | 700 | CompletionItem { |
679 | source_range: [68; 68), | 701 | label: "while", |
680 | delete: [68; 68), | 702 | source_range: [68; 68), |
681 | insert: "while $0 {}", | 703 | delete: [68; 68), |
682 | kind: Keyword, | 704 | insert: "while $0 {}", |
683 | }, | 705 | kind: Keyword, |
684 | ]"### | 706 | }, |
707 | ] | ||
708 | "### | ||
685 | ); | 709 | ); |
686 | } | 710 | } |
687 | 711 | ||
@@ -699,57 +723,59 @@ mod tests { | |||
699 | } | 723 | } |
700 | ", | 724 | ", |
701 | ), | 725 | ), |
702 | @r###"[ | 726 | @r###" |
703 | CompletionItem { | 727 | [ |
704 | label: "break", | 728 | CompletionItem { |
705 | source_range: [122; 124), | 729 | label: "break", |
706 | delete: [122; 124), | 730 | source_range: [122; 124), |
707 | insert: "break", | 731 | delete: [122; 124), |
708 | kind: Keyword, | 732 | insert: "break", |
709 | }, | 733 | kind: Keyword, |
710 | CompletionItem { | 734 | }, |
711 | label: "continue", | 735 | CompletionItem { |
712 | source_range: [122; 124), | 736 | label: "continue", |
713 | delete: [122; 124), | 737 | source_range: [122; 124), |
714 | insert: "continue", | 738 | delete: [122; 124), |
715 | kind: Keyword, | 739 | insert: "continue", |
716 | }, | 740 | kind: Keyword, |
717 | CompletionItem { | 741 | }, |
718 | label: "if", | 742 | CompletionItem { |
719 | source_range: [122; 124), | 743 | label: "if", |
720 | delete: [122; 124), | 744 | source_range: [122; 124), |
721 | insert: "if $0 {}", | 745 | delete: [122; 124), |
722 | kind: Keyword, | 746 | insert: "if $0 {}", |
723 | }, | 747 | kind: Keyword, |
724 | CompletionItem { | 748 | }, |
725 | label: "loop", | 749 | CompletionItem { |
726 | source_range: [122; 124), | 750 | label: "loop", |
727 | delete: [122; 124), | 751 | source_range: [122; 124), |
728 | insert: "loop {$0}", | 752 | delete: [122; 124), |
729 | kind: Keyword, | 753 | insert: "loop {$0}", |
730 | }, | 754 | kind: Keyword, |
731 | CompletionItem { | 755 | }, |
732 | label: "match", | 756 | CompletionItem { |
733 | source_range: [122; 124), | 757 | label: "match", |
734 | delete: [122; 124), | 758 | source_range: [122; 124), |
735 | insert: "match $0 {}", | 759 | delete: [122; 124), |
736 | kind: Keyword, | 760 | insert: "match $0 {}", |
737 | }, | 761 | kind: Keyword, |
738 | CompletionItem { | 762 | }, |
739 | label: "return", | 763 | CompletionItem { |
740 | source_range: [122; 124), | 764 | label: "return", |
741 | delete: [122; 124), | 765 | source_range: [122; 124), |
742 | insert: "return", | 766 | delete: [122; 124), |
743 | kind: Keyword, | 767 | insert: "return", |
744 | }, | 768 | kind: Keyword, |
745 | CompletionItem { | 769 | }, |
746 | label: "while", | 770 | CompletionItem { |
747 | source_range: [122; 124), | 771 | label: "while", |
748 | delete: [122; 124), | 772 | source_range: [122; 124), |
749 | insert: "while $0 {}", | 773 | delete: [122; 124), |
750 | kind: Keyword, | 774 | insert: "while $0 {}", |
751 | }, | 775 | kind: Keyword, |
752 | ]"### | 776 | }, |
777 | ] | ||
778 | "### | ||
753 | ) | 779 | ) |
754 | } | 780 | } |
755 | } | 781 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs index 09f743c66..faadd1e3f 100644 --- a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs +++ b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs | |||
@@ -37,16 +37,18 @@ mod tests { | |||
37 | <|> | 37 | <|> |
38 | " | 38 | " |
39 | ), | 39 | ), |
40 | @r##"[ | 40 | @r###" |
41 | CompletionItem { | 41 | [ |
42 | label: "foo!", | 42 | CompletionItem { |
43 | source_range: [46; 46), | 43 | label: "foo!", |
44 | delete: [46; 46), | 44 | source_range: [46; 46), |
45 | insert: "foo!($0)", | 45 | delete: [46; 46), |
46 | kind: Macro, | 46 | insert: "foo!($0)", |
47 | detail: "macro_rules! foo", | 47 | kind: Macro, |
48 | }, | 48 | detail: "macro_rules! foo", |
49 | ]"## | 49 | }, |
50 | ] | ||
51 | "### | ||
50 | ); | 52 | ); |
51 | } | 53 | } |
52 | 54 | ||
@@ -75,19 +77,21 @@ mod tests { | |||
75 | <|> | 77 | <|> |
76 | " | 78 | " |
77 | ), | 79 | ), |
78 | @r##"[ | 80 | @r###" |
79 | CompletionItem { | 81 | [ |
80 | label: "vec!", | 82 | CompletionItem { |
81 | source_range: [280; 280), | 83 | label: "vec!", |
82 | delete: [280; 280), | 84 | source_range: [280; 280), |
83 | insert: "vec![$0]", | 85 | delete: [280; 280), |
84 | kind: Macro, | 86 | insert: "vec![$0]", |
85 | detail: "macro_rules! vec", | 87 | kind: Macro, |
86 | documentation: Documentation( | 88 | detail: "macro_rules! vec", |
87 | "Creates a [`Vec`] containing the arguments.\n\n- Create a [`Vec`] containing a given list of elements:\n\n```\nlet v = vec![1, 2, 3];\nassert_eq!(v[0], 1);\nassert_eq!(v[1], 2);\nassert_eq!(v[2], 3);\n```", | 89 | documentation: Documentation( |
88 | ), | 90 | "Creates a [`Vec`] containing the arguments.\n\n- Create a [`Vec`] containing a given list of elements:\n\n```\nlet v = vec![1, 2, 3];\nassert_eq!(v[0], 1);\nassert_eq!(v[1], 2);\nassert_eq!(v[2], 3);\n```", |
89 | }, | 91 | ), |
90 | ]"## | 92 | }, |
93 | ] | ||
94 | "### | ||
91 | ); | 95 | ); |
92 | } | 96 | } |
93 | 97 | ||
@@ -110,28 +114,29 @@ mod tests { | |||
110 | } | 114 | } |
111 | " | 115 | " |
112 | ), | 116 | ), |
113 | @r###"[ | 117 | @r###" |
114 | CompletionItem { | 118 | [ |
115 | label: "foo!", | 119 | CompletionItem { |
116 | source_range: [163; 163), | 120 | label: "foo!", |
117 | delete: [163; 163), | 121 | source_range: [163; 163), |
118 | insert: "foo! {$0}", | 122 | delete: [163; 163), |
119 | kind: Macro, | 123 | insert: "foo! {$0}", |
120 | detail: "macro_rules! foo", | 124 | kind: Macro, |
121 | documentation: Documentation( | 125 | detail: "macro_rules! foo", |
122 | "Foo\n\nNot call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`.\nCall as `let _=foo! { hello world };`", | 126 | documentation: Documentation( |
123 | ), | 127 | "Foo\n\nNot call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`.\nCall as `let _=foo! { hello world };`", |
124 | }, | 128 | ), |
125 | CompletionItem { | 129 | }, |
126 | label: "main()", | 130 | CompletionItem { |
127 | source_range: [163; 163), | 131 | label: "main()", |
128 | delete: [163; 163), | 132 | source_range: [163; 163), |
129 | insert: "main()$0", | 133 | delete: [163; 163), |
130 | kind: Function, | 134 | insert: "main()$0", |
131 | lookup: "main", | 135 | kind: Function, |
132 | detail: "fn main()", | 136 | lookup: "main", |
133 | }, | 137 | detail: "fn main()", |
134 | ] | 138 | }, |
139 | ] | ||
135 | "### | 140 | "### |
136 | ); | 141 | ); |
137 | } | 142 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 09ca40179..5d974cf6d 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -152,18 +152,20 @@ mod tests { | |||
152 | } | 152 | } |
153 | " | 153 | " |
154 | ), | 154 | ), |
155 | @r###"[ | 155 | @r###" |
156 | CompletionItem { | 156 | [ |
157 | label: "my", | 157 | CompletionItem { |
158 | source_range: [27; 29), | 158 | label: "my", |
159 | delete: [27; 29), | 159 | source_range: [27; 29), |
160 | insert: "my", | 160 | delete: [27; 29), |
161 | kind: Module, | 161 | insert: "my", |
162 | documentation: Documentation( | 162 | kind: Module, |
163 | "Some simple\ndocs describing `mod my`.", | 163 | documentation: Documentation( |
164 | ), | 164 | "Some simple\ndocs describing `mod my`.", |
165 | }, | 165 | ), |
166 | ]"### | 166 | }, |
167 | ] | ||
168 | "### | ||
167 | ); | 169 | ); |
168 | } | 170 | } |
169 | 171 | ||
@@ -179,15 +181,17 @@ mod tests { | |||
179 | } | 181 | } |
180 | " | 182 | " |
181 | ), | 183 | ), |
182 | @r###"[ | 184 | @r###" |
183 | CompletionItem { | 185 | [ |
184 | label: "Bar", | 186 | CompletionItem { |
185 | source_range: [30; 30), | 187 | label: "Bar", |
186 | delete: [30; 30), | 188 | source_range: [30; 30), |
187 | insert: "Bar", | 189 | delete: [30; 30), |
188 | kind: Struct, | 190 | insert: "Bar", |
189 | }, | 191 | kind: Struct, |
190 | ]"### | 192 | }, |
193 | ] | ||
194 | "### | ||
191 | ); | 195 | ); |
192 | } | 196 | } |
193 | 197 | ||
@@ -203,22 +207,24 @@ mod tests { | |||
203 | use crate::Sp<|> | 207 | use crate::Sp<|> |
204 | " | 208 | " |
205 | ), | 209 | ), |
206 | @r###"[ | 210 | @r###" |
207 | CompletionItem { | 211 | [ |
208 | label: "Spam", | 212 | CompletionItem { |
209 | source_range: [11; 13), | 213 | label: "Spam", |
210 | delete: [11; 13), | 214 | source_range: [11; 13), |
211 | insert: "Spam", | 215 | delete: [11; 13), |
212 | kind: Struct, | 216 | insert: "Spam", |
213 | }, | 217 | kind: Struct, |
214 | CompletionItem { | 218 | }, |
215 | label: "foo", | 219 | CompletionItem { |
216 | source_range: [11; 13), | 220 | label: "foo", |
217 | delete: [11; 13), | 221 | source_range: [11; 13), |
218 | insert: "foo", | 222 | delete: [11; 13), |
219 | kind: Module, | 223 | insert: "foo", |
220 | }, | 224 | kind: Module, |
221 | ]"### | 225 | }, |
226 | ] | ||
227 | "### | ||
222 | ); | 228 | ); |
223 | } | 229 | } |
224 | 230 | ||
@@ -234,22 +240,24 @@ mod tests { | |||
234 | use crate::{Sp<|>}; | 240 | use crate::{Sp<|>}; |
235 | " | 241 | " |
236 | ), | 242 | ), |
237 | @r###"[ | 243 | @r###" |
238 | CompletionItem { | 244 | [ |
239 | label: "Spam", | 245 | CompletionItem { |
240 | source_range: [12; 14), | 246 | label: "Spam", |
241 | delete: [12; 14), | 247 | source_range: [12; 14), |
242 | insert: "Spam", | 248 | delete: [12; 14), |
243 | kind: Struct, | 249 | insert: "Spam", |
244 | }, | 250 | kind: Struct, |
245 | CompletionItem { | 251 | }, |
246 | label: "foo", | 252 | CompletionItem { |
247 | source_range: [12; 14), | 253 | label: "foo", |
248 | delete: [12; 14), | 254 | source_range: [12; 14), |
249 | insert: "foo", | 255 | delete: [12; 14), |
250 | kind: Module, | 256 | insert: "foo", |
251 | }, | 257 | kind: Module, |
252 | ]"### | 258 | }, |
259 | ] | ||
260 | "### | ||
253 | ); | 261 | ); |
254 | } | 262 | } |
255 | 263 | ||
@@ -269,15 +277,17 @@ mod tests { | |||
269 | use crate::{bar::{baz::Sp<|>}}; | 277 | use crate::{bar::{baz::Sp<|>}}; |
270 | " | 278 | " |
271 | ), | 279 | ), |
272 | @r###"[ | 280 | @r###" |
273 | CompletionItem { | 281 | [ |
274 | label: "Spam", | 282 | CompletionItem { |
275 | source_range: [23; 25), | 283 | label: "Spam", |
276 | delete: [23; 25), | 284 | source_range: [23; 25), |
277 | insert: "Spam", | 285 | delete: [23; 25), |
278 | kind: Struct, | 286 | insert: "Spam", |
279 | }, | 287 | kind: Struct, |
280 | ]"### | 288 | }, |
289 | ] | ||
290 | "### | ||
281 | ); | 291 | ); |
282 | } | 292 | } |
283 | 293 | ||
@@ -297,30 +307,32 @@ mod tests { | |||
297 | fn foo() { let _ = E::<|> } | 307 | fn foo() { let _ = E::<|> } |
298 | " | 308 | " |
299 | ), | 309 | ), |
300 | @r###"[ | 310 | @r###" |
301 | CompletionItem { | 311 | [ |
302 | label: "Bar", | 312 | CompletionItem { |
303 | source_range: [116; 116), | 313 | label: "Bar", |
304 | delete: [116; 116), | 314 | source_range: [116; 116), |
305 | insert: "Bar", | 315 | delete: [116; 116), |
306 | kind: EnumVariant, | 316 | insert: "Bar", |
307 | detail: "(i32)", | 317 | kind: EnumVariant, |
308 | documentation: Documentation( | 318 | detail: "(i32)", |
309 | "Bar Variant with i32", | 319 | documentation: Documentation( |
310 | ), | 320 | "Bar Variant with i32", |
311 | }, | 321 | ), |
312 | CompletionItem { | 322 | }, |
313 | label: "Foo", | 323 | CompletionItem { |
314 | source_range: [116; 116), | 324 | label: "Foo", |
315 | delete: [116; 116), | 325 | source_range: [116; 116), |
316 | insert: "Foo", | 326 | delete: [116; 116), |
317 | kind: EnumVariant, | 327 | insert: "Foo", |
318 | detail: "()", | 328 | kind: EnumVariant, |
319 | documentation: Documentation( | 329 | detail: "()", |
320 | "Foo Variant", | 330 | documentation: Documentation( |
321 | ), | 331 | "Foo Variant", |
322 | }, | 332 | ), |
323 | ]"### | 333 | }, |
334 | ] | ||
335 | "### | ||
324 | ); | 336 | ); |
325 | } | 337 | } |
326 | 338 | ||
@@ -343,41 +355,43 @@ mod tests { | |||
343 | fn foo() { let _ = E::<|> } | 355 | fn foo() { let _ = E::<|> } |
344 | " | 356 | " |
345 | ), | 357 | ), |
346 | @r###"[ | 358 | @r###" |
347 | CompletionItem { | 359 | [ |
348 | label: "Bar", | 360 | CompletionItem { |
349 | source_range: [180; 180), | 361 | label: "Bar", |
350 | delete: [180; 180), | 362 | source_range: [180; 180), |
351 | insert: "Bar", | 363 | delete: [180; 180), |
352 | kind: EnumVariant, | 364 | insert: "Bar", |
353 | detail: "(i32, u32)", | 365 | kind: EnumVariant, |
354 | documentation: Documentation( | 366 | detail: "(i32, u32)", |
355 | "Bar Variant with i32 and u32", | 367 | documentation: Documentation( |
356 | ), | 368 | "Bar Variant with i32 and u32", |
357 | }, | 369 | ), |
358 | CompletionItem { | 370 | }, |
359 | label: "Foo", | 371 | CompletionItem { |
360 | source_range: [180; 180), | 372 | label: "Foo", |
361 | delete: [180; 180), | 373 | source_range: [180; 180), |
362 | insert: "Foo", | 374 | delete: [180; 180), |
363 | kind: EnumVariant, | 375 | insert: "Foo", |
364 | detail: "()", | 376 | kind: EnumVariant, |
365 | documentation: Documentation( | 377 | detail: "()", |
366 | "Foo Variant (empty)", | 378 | documentation: Documentation( |
367 | ), | 379 | "Foo Variant (empty)", |
368 | }, | 380 | ), |
369 | CompletionItem { | 381 | }, |
370 | label: "S", | 382 | CompletionItem { |
371 | source_range: [180; 180), | 383 | label: "S", |
372 | delete: [180; 180), | 384 | source_range: [180; 180), |
373 | insert: "S", | 385 | delete: [180; 180), |
374 | kind: EnumVariant, | 386 | insert: "S", |
375 | detail: "(S)", | 387 | kind: EnumVariant, |
376 | documentation: Documentation( | 388 | detail: "(S)", |
377 | "", | 389 | documentation: Documentation( |
378 | ), | 390 | "", |
379 | }, | 391 | ), |
380 | ]"### | 392 | }, |
393 | ] | ||
394 | "### | ||
381 | ); | 395 | ); |
382 | } | 396 | } |
383 | 397 | ||
@@ -434,19 +448,21 @@ mod tests { | |||
434 | fn foo() { let _ = S::<|> } | 448 | fn foo() { let _ = S::<|> } |
435 | " | 449 | " |
436 | ), | 450 | ), |
437 | @r###"[ | 451 | @r###" |
438 | CompletionItem { | 452 | [ |
439 | label: "C", | 453 | CompletionItem { |
440 | source_range: [107; 107), | 454 | label: "C", |
441 | delete: [107; 107), | 455 | source_range: [107; 107), |
442 | insert: "C", | 456 | delete: [107; 107), |
443 | kind: Const, | 457 | insert: "C", |
444 | detail: "const C: i32 = 42;", | 458 | kind: Const, |
445 | documentation: Documentation( | 459 | detail: "const C: i32 = 42;", |
446 | "An associated const", | 460 | documentation: Documentation( |
447 | ), | 461 | "An associated const", |
448 | }, | 462 | ), |
449 | ]"### | 463 | }, |
464 | ] | ||
465 | "### | ||
450 | ); | 466 | ); |
451 | } | 467 | } |
452 | 468 | ||
@@ -467,19 +483,21 @@ mod tests { | |||
467 | fn foo() { let _ = S::<|> } | 483 | fn foo() { let _ = S::<|> } |
468 | " | 484 | " |
469 | ), | 485 | ), |
470 | @r###"[ | 486 | @r###" |
471 | CompletionItem { | 487 | [ |
472 | label: "T", | 488 | CompletionItem { |
473 | source_range: [101; 101), | 489 | label: "T", |
474 | delete: [101; 101), | 490 | source_range: [101; 101), |
475 | insert: "T", | 491 | delete: [101; 101), |
476 | kind: TypeAlias, | 492 | insert: "T", |
477 | detail: "type T = i32;", | 493 | kind: TypeAlias, |
478 | documentation: Documentation( | 494 | detail: "type T = i32;", |
479 | "An associated type", | 495 | documentation: Documentation( |
480 | ), | 496 | "An associated type", |
481 | }, | 497 | ), |
482 | ]"### | 498 | }, |
499 | ] | ||
500 | "### | ||
483 | ); | 501 | ); |
484 | } | 502 | } |
485 | 503 | ||
@@ -569,15 +587,17 @@ mod tests { | |||
569 | } | 587 | } |
570 | " | 588 | " |
571 | ), | 589 | ), |
572 | @r###"[ | 590 | @r###" |
573 | CompletionItem { | 591 | [ |
574 | label: "bar", | 592 | CompletionItem { |
575 | source_range: [9; 9), | 593 | label: "bar", |
576 | delete: [9; 9), | 594 | source_range: [9; 9), |
577 | insert: "bar", | 595 | delete: [9; 9), |
578 | kind: Module, | 596 | insert: "bar", |
579 | }, | 597 | kind: Module, |
580 | ]"### | 598 | }, |
599 | ] | ||
600 | "### | ||
581 | ); | 601 | ); |
582 | } | 602 | } |
583 | 603 | ||
diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide_api/src/completion/complete_pattern.rs index 513ad6e5f..fd03b1c40 100644 --- a/crates/ra_ide_api/src/completion/complete_pattern.rs +++ b/crates/ra_ide_api/src/completion/complete_pattern.rs | |||
@@ -54,36 +54,36 @@ mod tests { | |||
54 | ", | 54 | ", |
55 | ); | 55 | ); |
56 | assert_debug_snapshot!(completions, @r###" | 56 | assert_debug_snapshot!(completions, @r###" |
57 | ⋮[ | 57 | [ |
58 | ⋮ CompletionItem { | 58 | CompletionItem { |
59 | ⋮ label: "E", | 59 | label: "E", |
60 | ⋮ source_range: [246; 246), | 60 | source_range: [246; 246), |
61 | ⋮ delete: [246; 246), | 61 | delete: [246; 246), |
62 | ⋮ insert: "E", | 62 | insert: "E", |
63 | ⋮ kind: Enum, | 63 | kind: Enum, |
64 | ⋮ }, | 64 | }, |
65 | ⋮ CompletionItem { | 65 | CompletionItem { |
66 | ⋮ label: "X", | 66 | label: "X", |
67 | ⋮ source_range: [246; 246), | 67 | source_range: [246; 246), |
68 | ⋮ delete: [246; 246), | 68 | delete: [246; 246), |
69 | ⋮ insert: "X", | 69 | insert: "X", |
70 | ⋮ kind: EnumVariant, | 70 | kind: EnumVariant, |
71 | ⋮ }, | 71 | }, |
72 | ⋮ CompletionItem { | 72 | CompletionItem { |
73 | ⋮ label: "Z", | 73 | label: "Z", |
74 | ⋮ source_range: [246; 246), | 74 | source_range: [246; 246), |
75 | ⋮ delete: [246; 246), | 75 | delete: [246; 246), |
76 | ⋮ insert: "Z", | 76 | insert: "Z", |
77 | ⋮ kind: Const, | 77 | kind: Const, |
78 | ⋮ }, | 78 | }, |
79 | ⋮ CompletionItem { | 79 | CompletionItem { |
80 | ⋮ label: "m", | 80 | label: "m", |
81 | ⋮ source_range: [246; 246), | 81 | source_range: [246; 246), |
82 | ⋮ delete: [246; 246), | 82 | delete: [246; 246), |
83 | ⋮ insert: "m", | 83 | insert: "m", |
84 | ⋮ kind: Module, | 84 | kind: Module, |
85 | ⋮ }, | 85 | }, |
86 | ⋮] | 86 | ] |
87 | "###); | 87 | "###); |
88 | } | 88 | } |
89 | } | 89 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs index 99fed8689..17b75cf7e 100644 --- a/crates/ra_ide_api/src/completion/complete_postfix.rs +++ b/crates/ra_ide_api/src/completion/complete_postfix.rs | |||
@@ -104,64 +104,66 @@ mod tests { | |||
104 | } | 104 | } |
105 | "#, | 105 | "#, |
106 | ), | 106 | ), |
107 | @r###"[ | 107 | @r###" |
108 | CompletionItem { | 108 | [ |
109 | label: "box", | 109 | CompletionItem { |
110 | source_range: [89; 89), | 110 | label: "box", |
111 | delete: [85; 89), | 111 | source_range: [89; 89), |
112 | insert: "Box::new(bar)", | 112 | delete: [85; 89), |
113 | detail: "Box::new(expr)", | 113 | insert: "Box::new(bar)", |
114 | }, | 114 | detail: "Box::new(expr)", |
115 | CompletionItem { | 115 | }, |
116 | label: "dbg", | 116 | CompletionItem { |
117 | source_range: [89; 89), | 117 | label: "dbg", |
118 | delete: [85; 89), | 118 | source_range: [89; 89), |
119 | insert: "dbg!(bar)", | 119 | delete: [85; 89), |
120 | detail: "dbg!(expr)", | 120 | insert: "dbg!(bar)", |
121 | }, | 121 | detail: "dbg!(expr)", |
122 | CompletionItem { | 122 | }, |
123 | label: "if", | 123 | CompletionItem { |
124 | source_range: [89; 89), | 124 | label: "if", |
125 | delete: [85; 89), | 125 | source_range: [89; 89), |
126 | insert: "if bar {$0}", | 126 | delete: [85; 89), |
127 | detail: "if expr {}", | 127 | insert: "if bar {$0}", |
128 | }, | 128 | detail: "if expr {}", |
129 | CompletionItem { | 129 | }, |
130 | label: "match", | 130 | CompletionItem { |
131 | source_range: [89; 89), | 131 | label: "match", |
132 | delete: [85; 89), | 132 | source_range: [89; 89), |
133 | insert: "match bar {\n ${1:_} => {$0\\},\n}", | 133 | delete: [85; 89), |
134 | detail: "match expr {}", | 134 | insert: "match bar {\n ${1:_} => {$0\\},\n}", |
135 | }, | 135 | detail: "match expr {}", |
136 | CompletionItem { | 136 | }, |
137 | label: "not", | 137 | CompletionItem { |
138 | source_range: [89; 89), | 138 | label: "not", |
139 | delete: [85; 89), | 139 | source_range: [89; 89), |
140 | insert: "!bar", | 140 | delete: [85; 89), |
141 | detail: "!expr", | 141 | insert: "!bar", |
142 | }, | 142 | detail: "!expr", |
143 | CompletionItem { | 143 | }, |
144 | label: "ref", | 144 | CompletionItem { |
145 | source_range: [89; 89), | 145 | label: "ref", |
146 | delete: [85; 89), | 146 | source_range: [89; 89), |
147 | insert: "&bar", | 147 | delete: [85; 89), |
148 | detail: "&expr", | 148 | insert: "&bar", |
149 | }, | 149 | detail: "&expr", |
150 | CompletionItem { | 150 | }, |
151 | label: "refm", | 151 | CompletionItem { |
152 | source_range: [89; 89), | 152 | label: "refm", |
153 | delete: [85; 89), | 153 | source_range: [89; 89), |
154 | insert: "&mut bar", | 154 | delete: [85; 89), |
155 | detail: "&mut expr", | 155 | insert: "&mut bar", |
156 | }, | 156 | detail: "&mut expr", |
157 | CompletionItem { | 157 | }, |
158 | label: "while", | 158 | CompletionItem { |
159 | source_range: [89; 89), | 159 | label: "while", |
160 | delete: [85; 89), | 160 | source_range: [89; 89), |
161 | insert: "while bar {\n$0\n}", | 161 | delete: [85; 89), |
162 | detail: "while expr {}", | 162 | insert: "while bar {\n$0\n}", |
163 | }, | 163 | detail: "while expr {}", |
164 | ]"### | 164 | }, |
165 | ] | ||
166 | "### | ||
165 | ); | 167 | ); |
166 | } | 168 | } |
167 | 169 | ||
@@ -176,50 +178,52 @@ mod tests { | |||
176 | } | 178 | } |
177 | "#, | 179 | "#, |
178 | ), | 180 | ), |
179 | @r###"[ | 181 | @r###" |
180 | CompletionItem { | 182 | [ |
181 | label: "box", | 183 | CompletionItem { |
182 | source_range: [91; 91), | 184 | label: "box", |
183 | delete: [87; 91), | 185 | source_range: [91; 91), |
184 | insert: "Box::new(bar)", | 186 | delete: [87; 91), |
185 | detail: "Box::new(expr)", | 187 | insert: "Box::new(bar)", |
186 | }, | 188 | detail: "Box::new(expr)", |
187 | CompletionItem { | 189 | }, |
188 | label: "dbg", | 190 | CompletionItem { |
189 | source_range: [91; 91), | 191 | label: "dbg", |
190 | delete: [87; 91), | 192 | source_range: [91; 91), |
191 | insert: "dbg!(bar)", | 193 | delete: [87; 91), |
192 | detail: "dbg!(expr)", | 194 | insert: "dbg!(bar)", |
193 | }, | 195 | detail: "dbg!(expr)", |
194 | CompletionItem { | 196 | }, |
195 | label: "match", | 197 | CompletionItem { |
196 | source_range: [91; 91), | 198 | label: "match", |
197 | delete: [87; 91), | 199 | source_range: [91; 91), |
198 | insert: "match bar {\n ${1:_} => {$0\\},\n}", | 200 | delete: [87; 91), |
199 | detail: "match expr {}", | 201 | insert: "match bar {\n ${1:_} => {$0\\},\n}", |
200 | }, | 202 | detail: "match expr {}", |
201 | CompletionItem { | 203 | }, |
202 | label: "not", | 204 | CompletionItem { |
203 | source_range: [91; 91), | 205 | label: "not", |
204 | delete: [87; 91), | 206 | source_range: [91; 91), |
205 | insert: "!bar", | 207 | delete: [87; 91), |
206 | detail: "!expr", | 208 | insert: "!bar", |
207 | }, | 209 | detail: "!expr", |
208 | CompletionItem { | 210 | }, |
209 | label: "ref", | 211 | CompletionItem { |
210 | source_range: [91; 91), | 212 | label: "ref", |
211 | delete: [87; 91), | 213 | source_range: [91; 91), |
212 | insert: "&bar", | 214 | delete: [87; 91), |
213 | detail: "&expr", | 215 | insert: "&bar", |
214 | }, | 216 | detail: "&expr", |
215 | CompletionItem { | 217 | }, |
216 | label: "refm", | 218 | CompletionItem { |
217 | source_range: [91; 91), | 219 | label: "refm", |
218 | delete: [87; 91), | 220 | source_range: [91; 91), |
219 | insert: "&mut bar", | 221 | delete: [87; 91), |
220 | detail: "&mut expr", | 222 | insert: "&mut bar", |
221 | }, | 223 | detail: "&mut expr", |
222 | ]"### | 224 | }, |
225 | ] | ||
226 | "### | ||
223 | ); | 227 | ); |
224 | } | 228 | } |
225 | 229 | ||
@@ -233,50 +237,52 @@ mod tests { | |||
233 | } | 237 | } |
234 | "#, | 238 | "#, |
235 | ), | 239 | ), |
236 | @r###"[ | 240 | @r###" |
237 | CompletionItem { | 241 | [ |
238 | label: "box", | 242 | CompletionItem { |
239 | source_range: [52; 52), | 243 | label: "box", |
240 | delete: [49; 52), | 244 | source_range: [52; 52), |
241 | insert: "Box::new(42)", | 245 | delete: [49; 52), |
242 | detail: "Box::new(expr)", | 246 | insert: "Box::new(42)", |
243 | }, | 247 | detail: "Box::new(expr)", |
244 | CompletionItem { | 248 | }, |
245 | label: "dbg", | 249 | CompletionItem { |
246 | source_range: [52; 52), | 250 | label: "dbg", |
247 | delete: [49; 52), | 251 | source_range: [52; 52), |
248 | insert: "dbg!(42)", | 252 | delete: [49; 52), |
249 | detail: "dbg!(expr)", | 253 | insert: "dbg!(42)", |
250 | }, | 254 | detail: "dbg!(expr)", |
251 | CompletionItem { | 255 | }, |
252 | label: "match", | 256 | CompletionItem { |
253 | source_range: [52; 52), | 257 | label: "match", |
254 | delete: [49; 52), | 258 | source_range: [52; 52), |
255 | insert: "match 42 {\n ${1:_} => {$0\\},\n}", | 259 | delete: [49; 52), |
256 | detail: "match expr {}", | 260 | insert: "match 42 {\n ${1:_} => {$0\\},\n}", |
257 | }, | 261 | detail: "match expr {}", |
258 | CompletionItem { | 262 | }, |
259 | label: "not", | 263 | CompletionItem { |
260 | source_range: [52; 52), | 264 | label: "not", |
261 | delete: [49; 52), | 265 | source_range: [52; 52), |
262 | insert: "!42", | 266 | delete: [49; 52), |
263 | detail: "!expr", | 267 | insert: "!42", |
264 | }, | 268 | detail: "!expr", |
265 | CompletionItem { | 269 | }, |
266 | label: "ref", | 270 | CompletionItem { |
267 | source_range: [52; 52), | 271 | label: "ref", |
268 | delete: [49; 52), | 272 | source_range: [52; 52), |
269 | insert: "&42", | 273 | delete: [49; 52), |
270 | detail: "&expr", | 274 | insert: "&42", |
271 | }, | 275 | detail: "&expr", |
272 | CompletionItem { | 276 | }, |
273 | label: "refm", | 277 | CompletionItem { |
274 | source_range: [52; 52), | 278 | label: "refm", |
275 | delete: [49; 52), | 279 | source_range: [52; 52), |
276 | insert: "&mut 42", | 280 | delete: [49; 52), |
277 | detail: "&mut expr", | 281 | insert: "&mut 42", |
278 | }, | 282 | detail: "&mut expr", |
279 | ]"### | 283 | }, |
284 | ] | ||
285 | "### | ||
280 | ); | 286 | ); |
281 | } | 287 | } |
282 | } | 288 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs index 0295b8101..45a4a9738 100644 --- a/crates/ra_ide_api/src/completion/complete_record_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs | |||
@@ -45,17 +45,17 @@ mod tests { | |||
45 | ", | 45 | ", |
46 | ); | 46 | ); |
47 | assert_debug_snapshot!(completions, @r###" | 47 | assert_debug_snapshot!(completions, @r###" |
48 | ⋮[ | 48 | [ |
49 | ⋮ CompletionItem { | 49 | CompletionItem { |
50 | ⋮ label: "the_field", | 50 | label: "the_field", |
51 | ⋮ source_range: [142; 145), | 51 | source_range: [142; 145), |
52 | ⋮ delete: [142; 145), | 52 | delete: [142; 145), |
53 | ⋮ insert: "the_field", | 53 | insert: "the_field", |
54 | ⋮ kind: Field, | 54 | kind: Field, |
55 | ⋮ detail: "u32", | 55 | detail: "u32", |
56 | ⋮ deprecated: true, | 56 | deprecated: true, |
57 | ⋮ }, | 57 | }, |
58 | ⋮] | 58 | ] |
59 | "###); | 59 | "###); |
60 | } | 60 | } |
61 | 61 | ||
@@ -70,16 +70,16 @@ mod tests { | |||
70 | ", | 70 | ", |
71 | ); | 71 | ); |
72 | assert_debug_snapshot!(completions, @r###" | 72 | assert_debug_snapshot!(completions, @r###" |
73 | ⋮[ | 73 | [ |
74 | ⋮ CompletionItem { | 74 | CompletionItem { |
75 | ⋮ label: "the_field", | 75 | label: "the_field", |
76 | ⋮ source_range: [83; 86), | 76 | source_range: [83; 86), |
77 | ⋮ delete: [83; 86), | 77 | delete: [83; 86), |
78 | ⋮ insert: "the_field", | 78 | insert: "the_field", |
79 | ⋮ kind: Field, | 79 | kind: Field, |
80 | ⋮ detail: "u32", | 80 | detail: "u32", |
81 | ⋮ }, | 81 | }, |
82 | ⋮] | 82 | ] |
83 | "###); | 83 | "###); |
84 | } | 84 | } |
85 | 85 | ||
@@ -96,16 +96,16 @@ mod tests { | |||
96 | ", | 96 | ", |
97 | ); | 97 | ); |
98 | assert_debug_snapshot!(completions, @r###" | 98 | assert_debug_snapshot!(completions, @r###" |
99 | ⋮[ | 99 | [ |
100 | ⋮ CompletionItem { | 100 | CompletionItem { |
101 | ⋮ label: "a", | 101 | label: "a", |
102 | ⋮ source_range: [119; 119), | 102 | source_range: [119; 119), |
103 | ⋮ delete: [119; 119), | 103 | delete: [119; 119), |
104 | ⋮ insert: "a", | 104 | insert: "a", |
105 | ⋮ kind: Field, | 105 | kind: Field, |
106 | ⋮ detail: "u32", | 106 | detail: "u32", |
107 | ⋮ }, | 107 | }, |
108 | ⋮] | 108 | ] |
109 | "###); | 109 | "###); |
110 | } | 110 | } |
111 | 111 | ||
@@ -122,16 +122,16 @@ mod tests { | |||
122 | ", | 122 | ", |
123 | ); | 123 | ); |
124 | assert_debug_snapshot!(completions, @r###" | 124 | assert_debug_snapshot!(completions, @r###" |
125 | ⋮[ | 125 | [ |
126 | ⋮ CompletionItem { | 126 | CompletionItem { |
127 | ⋮ label: "b", | 127 | label: "b", |
128 | ⋮ source_range: [119; 119), | 128 | source_range: [119; 119), |
129 | ⋮ delete: [119; 119), | 129 | delete: [119; 119), |
130 | ⋮ insert: "b", | 130 | insert: "b", |
131 | ⋮ kind: Field, | 131 | kind: Field, |
132 | ⋮ detail: "u32", | 132 | detail: "u32", |
133 | ⋮ }, | 133 | }, |
134 | ⋮] | 134 | ] |
135 | "###); | 135 | "###); |
136 | } | 136 | } |
137 | 137 | ||
@@ -147,16 +147,16 @@ mod tests { | |||
147 | ", | 147 | ", |
148 | ); | 148 | ); |
149 | assert_debug_snapshot!(completions, @r###" | 149 | assert_debug_snapshot!(completions, @r###" |
150 | ⋮[ | 150 | [ |
151 | ⋮ CompletionItem { | 151 | CompletionItem { |
152 | ⋮ label: "a", | 152 | label: "a", |
153 | ⋮ source_range: [93; 93), | 153 | source_range: [93; 93), |
154 | ⋮ delete: [93; 93), | 154 | delete: [93; 93), |
155 | ⋮ insert: "a", | 155 | insert: "a", |
156 | ⋮ kind: Field, | 156 | kind: Field, |
157 | ⋮ detail: "u32", | 157 | detail: "u32", |
158 | ⋮ }, | 158 | }, |
159 | ⋮] | 159 | ] |
160 | "###); | 160 | "###); |
161 | } | 161 | } |
162 | } | 162 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs index d20fa796c..aa0fd6d24 100644 --- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs +++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs | |||
@@ -44,16 +44,16 @@ mod tests { | |||
44 | ", | 44 | ", |
45 | ); | 45 | ); |
46 | assert_debug_snapshot!(completions, @r###" | 46 | assert_debug_snapshot!(completions, @r###" |
47 | ⋮[ | 47 | [ |
48 | ⋮ CompletionItem { | 48 | CompletionItem { |
49 | ⋮ label: "foo", | 49 | label: "foo", |
50 | ⋮ source_range: [117; 118), | 50 | source_range: [117; 118), |
51 | ⋮ delete: [117; 118), | 51 | delete: [117; 118), |
52 | ⋮ insert: "foo", | 52 | insert: "foo", |
53 | ⋮ kind: Field, | 53 | kind: Field, |
54 | ⋮ detail: "u32", | 54 | detail: "u32", |
55 | ⋮ }, | 55 | }, |
56 | ⋮] | 56 | ] |
57 | "###); | 57 | "###); |
58 | } | 58 | } |
59 | 59 | ||
@@ -73,24 +73,24 @@ mod tests { | |||
73 | ", | 73 | ", |
74 | ); | 74 | ); |
75 | assert_debug_snapshot!(completions, @r###" | 75 | assert_debug_snapshot!(completions, @r###" |
76 | ⋮[ | 76 | [ |
77 | ⋮ CompletionItem { | 77 | CompletionItem { |
78 | ⋮ label: "bar", | 78 | label: "bar", |
79 | ⋮ source_range: [161; 161), | 79 | source_range: [161; 161), |
80 | ⋮ delete: [161; 161), | 80 | delete: [161; 161), |
81 | ⋮ insert: "bar", | 81 | insert: "bar", |
82 | ⋮ kind: Field, | 82 | kind: Field, |
83 | ⋮ detail: "()", | 83 | detail: "()", |
84 | ⋮ }, | 84 | }, |
85 | ⋮ CompletionItem { | 85 | CompletionItem { |
86 | ⋮ label: "foo", | 86 | label: "foo", |
87 | ⋮ source_range: [161; 161), | 87 | source_range: [161; 161), |
88 | ⋮ delete: [161; 161), | 88 | delete: [161; 161), |
89 | ⋮ insert: "foo", | 89 | insert: "foo", |
90 | ⋮ kind: Field, | 90 | kind: Field, |
91 | ⋮ detail: "u32", | 91 | detail: "u32", |
92 | ⋮ }, | 92 | }, |
93 | ⋮] | 93 | ] |
94 | "###); | 94 | "###); |
95 | } | 95 | } |
96 | } | 96 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 3e205efd1..8c57c907d 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -409,15 +409,17 @@ mod tests { | |||
409 | // nothing here | 409 | // nothing here |
410 | " | 410 | " |
411 | ), | 411 | ), |
412 | @r#"[ | 412 | @r###" |
413 | CompletionItem { | 413 | [ |
414 | label: "other_crate", | 414 | CompletionItem { |
415 | source_range: [4; 4), | 415 | label: "other_crate", |
416 | delete: [4; 4), | 416 | source_range: [4; 4), |
417 | insert: "other_crate", | 417 | delete: [4; 4), |
418 | kind: Module, | 418 | insert: "other_crate", |
419 | }, | 419 | kind: Module, |
420 | ]"# | 420 | }, |
421 | ] | ||
422 | "### | ||
421 | ); | 423 | ); |
422 | } | 424 | } |
423 | 425 | ||
@@ -530,23 +532,25 @@ mod tests { | |||
530 | fn completes_self_in_methods() { | 532 | fn completes_self_in_methods() { |
531 | assert_debug_snapshot!( | 533 | assert_debug_snapshot!( |
532 | do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), | 534 | do_reference_completion(r"impl S { fn foo(&self) { <|> } }"), |
533 | @r#"[ | 535 | @r###" |
534 | CompletionItem { | 536 | [ |
535 | label: "Self", | 537 | CompletionItem { |
536 | source_range: [25; 25), | 538 | label: "Self", |
537 | delete: [25; 25), | 539 | source_range: [25; 25), |
538 | insert: "Self", | 540 | delete: [25; 25), |
539 | kind: TypeParam, | 541 | insert: "Self", |
540 | }, | 542 | kind: TypeParam, |
541 | CompletionItem { | 543 | }, |
542 | label: "self", | 544 | CompletionItem { |
543 | source_range: [25; 25), | 545 | label: "self", |
544 | delete: [25; 25), | 546 | source_range: [25; 25), |
545 | insert: "self", | 547 | delete: [25; 25), |
546 | kind: Binding, | 548 | insert: "self", |
547 | detail: "&{unknown}", | 549 | kind: Binding, |
548 | }, | 550 | detail: "&{unknown}", |
549 | ]"# | 551 | }, |
552 | ] | ||
553 | "### | ||
550 | ); | 554 | ); |
551 | } | 555 | } |
552 | 556 | ||
diff --git a/crates/ra_ide_api/src/completion/complete_snippet.rs b/crates/ra_ide_api/src/completion/complete_snippet.rs index 2df79b6c3..1f2988b36 100644 --- a/crates/ra_ide_api/src/completion/complete_snippet.rs +++ b/crates/ra_ide_api/src/completion/complete_snippet.rs | |||
@@ -52,22 +52,24 @@ mod tests { | |||
52 | fn completes_snippets_in_expressions() { | 52 | fn completes_snippets_in_expressions() { |
53 | assert_debug_snapshot!( | 53 | assert_debug_snapshot!( |
54 | do_snippet_completion(r"fn foo(x: i32) { <|> }"), | 54 | do_snippet_completion(r"fn foo(x: i32) { <|> }"), |
55 | @r#"[ | 55 | @r###" |
56 | CompletionItem { | 56 | [ |
57 | label: "pd", | 57 | CompletionItem { |
58 | source_range: [17; 17), | 58 | label: "pd", |
59 | delete: [17; 17), | 59 | source_range: [17; 17), |
60 | insert: "eprintln!(\"$0 = {:?}\", $0);", | 60 | delete: [17; 17), |
61 | kind: Snippet, | 61 | insert: "eprintln!(\"$0 = {:?}\", $0);", |
62 | }, | 62 | kind: Snippet, |
63 | CompletionItem { | 63 | }, |
64 | label: "ppd", | 64 | CompletionItem { |
65 | source_range: [17; 17), | 65 | label: "ppd", |
66 | delete: [17; 17), | 66 | source_range: [17; 17), |
67 | insert: "eprintln!(\"$0 = {:#?}\", $0);", | 67 | delete: [17; 17), |
68 | kind: Snippet, | 68 | insert: "eprintln!(\"$0 = {:#?}\", $0);", |
69 | }, | 69 | kind: Snippet, |
70 | ]"# | 70 | }, |
71 | ] | ||
72 | "### | ||
71 | ); | 73 | ); |
72 | } | 74 | } |
73 | 75 | ||
@@ -75,11 +77,11 @@ mod tests { | |||
75 | fn should_not_complete_snippets_in_path() { | 77 | fn should_not_complete_snippets_in_path() { |
76 | assert_debug_snapshot!( | 78 | assert_debug_snapshot!( |
77 | do_snippet_completion(r"fn foo(x: i32) { ::foo<|> }"), | 79 | do_snippet_completion(r"fn foo(x: i32) { ::foo<|> }"), |
78 | @r#"[]"# | 80 | @"[]" |
79 | ); | 81 | ); |
80 | assert_debug_snapshot!( | 82 | assert_debug_snapshot!( |
81 | do_snippet_completion(r"fn foo(x: i32) { ::<|> }"), | 83 | do_snippet_completion(r"fn foo(x: i32) { ::<|> }"), |
82 | @r#"[]"# | 84 | @"[]" |
83 | ); | 85 | ); |
84 | } | 86 | } |
85 | 87 | ||
@@ -94,23 +96,25 @@ mod tests { | |||
94 | } | 96 | } |
95 | " | 97 | " |
96 | ), | 98 | ), |
97 | @r###"[ | 99 | @r###" |
98 | CompletionItem { | 100 | [ |
99 | label: "Test function", | 101 | CompletionItem { |
100 | source_range: [78; 78), | 102 | label: "Test function", |
101 | delete: [78; 78), | 103 | source_range: [78; 78), |
102 | insert: "#[test]\nfn ${1:feature}() {\n $0\n}", | 104 | delete: [78; 78), |
103 | kind: Snippet, | 105 | insert: "#[test]\nfn ${1:feature}() {\n $0\n}", |
104 | lookup: "tfn", | 106 | kind: Snippet, |
105 | }, | 107 | lookup: "tfn", |
106 | CompletionItem { | 108 | }, |
107 | label: "pub(crate)", | 109 | CompletionItem { |
108 | source_range: [78; 78), | 110 | label: "pub(crate)", |
109 | delete: [78; 78), | 111 | source_range: [78; 78), |
110 | insert: "pub(crate) $0", | 112 | delete: [78; 78), |
111 | kind: Snippet, | 113 | insert: "pub(crate) $0", |
112 | }, | 114 | kind: Snippet, |
113 | ]"### | 115 | }, |
116 | ] | ||
117 | "### | ||
114 | ); | 118 | ); |
115 | } | 119 | } |
116 | } | 120 | } |
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index d861303b7..501b7da4e 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -68,7 +68,7 @@ impl Completions { | |||
68 | ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::TypeAlias, | 68 | ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::TypeAlias, |
69 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, | 69 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, |
70 | ScopeDef::GenericParam(..) => CompletionItemKind::TypeParam, | 70 | ScopeDef::GenericParam(..) => CompletionItemKind::TypeParam, |
71 | ScopeDef::LocalBinding(..) => CompletionItemKind::Binding, | 71 | ScopeDef::Local(..) => CompletionItemKind::Binding, |
72 | // (does this need its own kind?) | 72 | // (does this need its own kind?) |
73 | ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam, | 73 | ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam, |
74 | ScopeDef::MacroDef(mac) => { | 74 | ScopeDef::MacroDef(mac) => { |
@@ -96,13 +96,11 @@ impl Completions { | |||
96 | 96 | ||
97 | let mut completion_item = | 97 | let mut completion_item = |
98 | CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); | 98 | CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); |
99 | if let ScopeDef::LocalBinding(pat_id) = resolution { | 99 | if let ScopeDef::Local(local) = resolution { |
100 | let ty = ctx | 100 | let ty = local.ty(ctx.db); |
101 | .analyzer | 101 | if ty != Ty::Unknown { |
102 | .type_of_pat_by_id(ctx.db, pat_id.clone()) | 102 | completion_item = completion_item.detail(ty.display(ctx.db).to_string()); |
103 | .filter(|t| t != &Ty::Unknown) | 103 | } |
104 | .map(|t| t.display(ctx.db).to_string()); | ||
105 | completion_item = completion_item.set_detail(ty); | ||
106 | }; | 104 | }; |
107 | 105 | ||
108 | // If not an import, add parenthesis automatically. | 106 | // If not an import, add parenthesis automatically. |
@@ -325,38 +323,38 @@ mod tests { | |||
325 | "#, | 323 | "#, |
326 | ), | 324 | ), |
327 | @r###" | 325 | @r###" |
328 | [ | 326 | [ |
329 | CompletionItem { | 327 | CompletionItem { |
330 | label: "main()", | 328 | label: "main()", |
331 | source_range: [203; 206), | 329 | source_range: [203; 206), |
332 | delete: [203; 206), | 330 | delete: [203; 206), |
333 | insert: "main()$0", | 331 | insert: "main()$0", |
334 | kind: Function, | 332 | kind: Function, |
335 | lookup: "main", | 333 | lookup: "main", |
336 | detail: "fn main()", | 334 | detail: "fn main()", |
337 | }, | 335 | }, |
338 | CompletionItem { | 336 | CompletionItem { |
339 | label: "something_deprecated()", | 337 | label: "something_deprecated()", |
340 | source_range: [203; 206), | 338 | source_range: [203; 206), |
341 | delete: [203; 206), | 339 | delete: [203; 206), |
342 | insert: "something_deprecated()$0", | 340 | insert: "something_deprecated()$0", |
343 | kind: Function, | 341 | kind: Function, |
344 | lookup: "something_deprecated", | 342 | lookup: "something_deprecated", |
345 | detail: "fn something_deprecated()", | 343 | detail: "fn something_deprecated()", |
346 | deprecated: true, | 344 | deprecated: true, |
347 | }, | 345 | }, |
348 | CompletionItem { | 346 | CompletionItem { |
349 | label: "something_else_deprecated()", | 347 | label: "something_else_deprecated()", |
350 | source_range: [203; 206), | 348 | source_range: [203; 206), |
351 | delete: [203; 206), | 349 | delete: [203; 206), |
352 | insert: "something_else_deprecated()$0", | 350 | insert: "something_else_deprecated()$0", |
353 | kind: Function, | 351 | kind: Function, |
354 | lookup: "something_else_deprecated", | 352 | lookup: "something_else_deprecated", |
355 | detail: "fn something_else_deprecated()", | 353 | detail: "fn something_else_deprecated()", |
356 | deprecated: true, | 354 | deprecated: true, |
357 | }, | 355 | }, |
358 | ] | 356 | ] |
359 | "### | 357 | "### |
360 | ); | 358 | ); |
361 | } | 359 | } |
362 | 360 | ||
@@ -461,16 +459,18 @@ mod tests { | |||
461 | use crate::m::f<|>; | 459 | use crate::m::f<|>; |
462 | " | 460 | " |
463 | ), | 461 | ), |
464 | @r#"[ | 462 | @r###" |
465 | CompletionItem { | 463 | [ |
466 | label: "foo", | 464 | CompletionItem { |
467 | source_range: [40; 41), | 465 | label: "foo", |
468 | delete: [40; 41), | 466 | source_range: [40; 41), |
469 | insert: "foo", | 467 | delete: [40; 41), |
470 | kind: Function, | 468 | insert: "foo", |
471 | detail: "pub fn foo()", | 469 | kind: Function, |
472 | }, | 470 | detail: "pub fn foo()", |
473 | ]"# | 471 | }, |
472 | ] | ||
473 | "### | ||
474 | ); | 474 | ); |
475 | } | 475 | } |
476 | 476 | ||
@@ -486,24 +486,26 @@ mod tests { | |||
486 | } | 486 | } |
487 | " | 487 | " |
488 | ), | 488 | ), |
489 | @r#"[ | 489 | @r###" |
490 | CompletionItem { | 490 | [ |
491 | label: "frobnicate", | 491 | CompletionItem { |
492 | source_range: [35; 39), | 492 | label: "frobnicate", |
493 | delete: [35; 39), | 493 | source_range: [35; 39), |
494 | insert: "frobnicate", | 494 | delete: [35; 39), |
495 | kind: Function, | 495 | insert: "frobnicate", |
496 | detail: "fn frobnicate()", | 496 | kind: Function, |
497 | }, | 497 | detail: "fn frobnicate()", |
498 | CompletionItem { | 498 | }, |
499 | label: "main", | 499 | CompletionItem { |
500 | source_range: [35; 39), | 500 | label: "main", |
501 | delete: [35; 39), | 501 | source_range: [35; 39), |
502 | insert: "main", | 502 | delete: [35; 39), |
503 | kind: Function, | 503 | insert: "main", |
504 | detail: "fn main()", | 504 | kind: Function, |
505 | }, | 505 | detail: "fn main()", |
506 | ]"# | 506 | }, |
507 | ] | ||
508 | "### | ||
507 | ); | 509 | ); |
508 | assert_debug_snapshot!( | 510 | assert_debug_snapshot!( |
509 | do_reference_completion( | 511 | do_reference_completion( |
@@ -516,16 +518,18 @@ mod tests { | |||
516 | } | 518 | } |
517 | " | 519 | " |
518 | ), | 520 | ), |
519 | @r#"[ | 521 | @r###" |
520 | CompletionItem { | 522 | [ |
521 | label: "new", | 523 | CompletionItem { |
522 | source_range: [67; 69), | 524 | label: "new", |
523 | delete: [67; 69), | 525 | source_range: [67; 69), |
524 | insert: "new", | 526 | delete: [67; 69), |
525 | kind: Function, | 527 | insert: "new", |
526 | detail: "fn new() -> Foo", | 528 | kind: Function, |
527 | }, | 529 | detail: "fn new() -> Foo", |
528 | ]"# | 530 | }, |
531 | ] | ||
532 | "### | ||
529 | ); | 533 | ); |
530 | } | 534 | } |
531 | 535 | ||
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index 2890a3d2b..e52ffefb3 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs | |||
@@ -526,28 +526,28 @@ mod tests { | |||
526 | let (analysis, file_id) = single_file("mod foo;"); | 526 | let (analysis, file_id) = single_file("mod foo;"); |
527 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 527 | let diagnostics = analysis.diagnostics(file_id).unwrap(); |
528 | assert_debug_snapshot!(diagnostics, @r###" | 528 | assert_debug_snapshot!(diagnostics, @r###" |
529 | ⋮[ | 529 | [ |
530 | ⋮ Diagnostic { | 530 | Diagnostic { |
531 | ⋮ message: "unresolved module", | 531 | message: "unresolved module", |
532 | ⋮ range: [0; 8), | 532 | range: [0; 8), |
533 | ⋮ fix: Some( | 533 | fix: Some( |
534 | ⋮ SourceChange { | 534 | SourceChange { |
535 | ⋮ label: "create module", | 535 | label: "create module", |
536 | ⋮ source_file_edits: [], | 536 | source_file_edits: [], |
537 | ⋮ file_system_edits: [ | 537 | file_system_edits: [ |
538 | ⋮ CreateFile { | 538 | CreateFile { |
539 | ⋮ source_root: SourceRootId( | 539 | source_root: SourceRootId( |
540 | ⋮ 0, | 540 | 0, |
541 | ⋮ ), | 541 | ), |
542 | ⋮ path: "foo.rs", | 542 | path: "foo.rs", |
543 | ⋮ }, | 543 | }, |
544 | ⋮ ], | 544 | ], |
545 | ⋮ cursor_position: None, | 545 | cursor_position: None, |
546 | ⋮ }, | 546 | }, |
547 | ⋮ ), | 547 | ), |
548 | ⋮ severity: Error, | 548 | severity: Error, |
549 | ⋮ }, | 549 | }, |
550 | ⋮] | 550 | ] |
551 | "###); | 551 | "###); |
552 | } | 552 | } |
553 | 553 | ||
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs index ddd8b7b20..a80d65ac7 100644 --- a/crates/ra_ide_api/src/display/structure.rs +++ b/crates/ra_ide_api/src/display/structure.rs | |||
@@ -209,191 +209,193 @@ fn very_obsolete() {} | |||
209 | .unwrap(); | 209 | .unwrap(); |
210 | let structure = file_structure(&file); | 210 | let structure = file_structure(&file); |
211 | assert_debug_snapshot!(structure, | 211 | assert_debug_snapshot!(structure, |
212 | @r#"[ | 212 | @r###" |
213 | StructureNode { | 213 | [ |
214 | parent: None, | 214 | StructureNode { |
215 | label: "Foo", | 215 | parent: None, |
216 | navigation_range: [8; 11), | 216 | label: "Foo", |
217 | node_range: [1; 26), | 217 | navigation_range: [8; 11), |
218 | kind: STRUCT_DEF, | 218 | node_range: [1; 26), |
219 | detail: None, | 219 | kind: STRUCT_DEF, |
220 | deprecated: false, | 220 | detail: None, |
221 | }, | 221 | deprecated: false, |
222 | StructureNode { | 222 | }, |
223 | parent: Some( | 223 | StructureNode { |
224 | 0, | 224 | parent: Some( |
225 | ), | 225 | 0, |
226 | label: "x", | 226 | ), |
227 | navigation_range: [18; 19), | 227 | label: "x", |
228 | node_range: [18; 24), | 228 | navigation_range: [18; 19), |
229 | kind: RECORD_FIELD_DEF, | 229 | node_range: [18; 24), |
230 | detail: Some( | 230 | kind: RECORD_FIELD_DEF, |
231 | "i32", | 231 | detail: Some( |
232 | ), | 232 | "i32", |
233 | deprecated: false, | 233 | ), |
234 | }, | 234 | deprecated: false, |
235 | StructureNode { | 235 | }, |
236 | parent: None, | 236 | StructureNode { |
237 | label: "m", | 237 | parent: None, |
238 | navigation_range: [32; 33), | 238 | label: "m", |
239 | node_range: [28; 158), | 239 | navigation_range: [32; 33), |
240 | kind: MODULE, | 240 | node_range: [28; 158), |
241 | detail: None, | 241 | kind: MODULE, |
242 | deprecated: false, | 242 | detail: None, |
243 | }, | 243 | deprecated: false, |
244 | StructureNode { | 244 | }, |
245 | parent: Some( | 245 | StructureNode { |
246 | 2, | 246 | parent: Some( |
247 | ), | 247 | 2, |
248 | label: "bar1", | 248 | ), |
249 | navigation_range: [43; 47), | 249 | label: "bar1", |
250 | node_range: [40; 52), | 250 | navigation_range: [43; 47), |
251 | kind: FN_DEF, | 251 | node_range: [40; 52), |
252 | detail: Some( | 252 | kind: FN_DEF, |
253 | "fn()", | 253 | detail: Some( |
254 | ), | 254 | "fn()", |
255 | deprecated: false, | 255 | ), |
256 | }, | 256 | deprecated: false, |
257 | StructureNode { | 257 | }, |
258 | parent: Some( | 258 | StructureNode { |
259 | 2, | 259 | parent: Some( |
260 | ), | 260 | 2, |
261 | label: "bar2", | 261 | ), |
262 | navigation_range: [60; 64), | 262 | label: "bar2", |
263 | node_range: [57; 81), | 263 | navigation_range: [60; 64), |
264 | kind: FN_DEF, | 264 | node_range: [57; 81), |
265 | detail: Some( | 265 | kind: FN_DEF, |
266 | "fn<T>(t: T) -> T", | 266 | detail: Some( |
267 | ), | 267 | "fn<T>(t: T) -> T", |
268 | deprecated: false, | 268 | ), |
269 | }, | 269 | deprecated: false, |
270 | StructureNode { | 270 | }, |
271 | parent: Some( | 271 | StructureNode { |
272 | 2, | 272 | parent: Some( |
273 | ), | 273 | 2, |
274 | label: "bar3", | 274 | ), |
275 | navigation_range: [89; 93), | 275 | label: "bar3", |
276 | node_range: [86; 156), | 276 | navigation_range: [89; 93), |
277 | kind: FN_DEF, | 277 | node_range: [86; 156), |
278 | detail: Some( | 278 | kind: FN_DEF, |
279 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", | 279 | detail: Some( |
280 | ), | 280 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", |
281 | deprecated: false, | 281 | ), |
282 | }, | 282 | deprecated: false, |
283 | StructureNode { | 283 | }, |
284 | parent: None, | 284 | StructureNode { |
285 | label: "E", | 285 | parent: None, |
286 | navigation_range: [165; 166), | 286 | label: "E", |
287 | node_range: [160; 180), | 287 | navigation_range: [165; 166), |
288 | kind: ENUM_DEF, | 288 | node_range: [160; 180), |
289 | detail: None, | 289 | kind: ENUM_DEF, |
290 | deprecated: false, | 290 | detail: None, |
291 | }, | 291 | deprecated: false, |
292 | StructureNode { | 292 | }, |
293 | parent: Some( | 293 | StructureNode { |
294 | 6, | 294 | parent: Some( |
295 | ), | 295 | 6, |
296 | label: "X", | 296 | ), |
297 | navigation_range: [169; 170), | 297 | label: "X", |
298 | node_range: [169; 170), | 298 | navigation_range: [169; 170), |
299 | kind: ENUM_VARIANT, | 299 | node_range: [169; 170), |
300 | detail: None, | 300 | kind: ENUM_VARIANT, |
301 | deprecated: false, | 301 | detail: None, |
302 | }, | 302 | deprecated: false, |
303 | StructureNode { | 303 | }, |
304 | parent: Some( | 304 | StructureNode { |
305 | 6, | 305 | parent: Some( |
306 | ), | 306 | 6, |
307 | label: "Y", | 307 | ), |
308 | navigation_range: [172; 173), | 308 | label: "Y", |
309 | node_range: [172; 178), | 309 | navigation_range: [172; 173), |
310 | kind: ENUM_VARIANT, | 310 | node_range: [172; 178), |
311 | detail: None, | 311 | kind: ENUM_VARIANT, |
312 | deprecated: false, | 312 | detail: None, |
313 | }, | 313 | deprecated: false, |
314 | StructureNode { | 314 | }, |
315 | parent: None, | 315 | StructureNode { |
316 | label: "T", | 316 | parent: None, |
317 | navigation_range: [186; 187), | 317 | label: "T", |
318 | node_range: [181; 193), | 318 | navigation_range: [186; 187), |
319 | kind: TYPE_ALIAS_DEF, | 319 | node_range: [181; 193), |
320 | detail: Some( | 320 | kind: TYPE_ALIAS_DEF, |
321 | "()", | 321 | detail: Some( |
322 | ), | 322 | "()", |
323 | deprecated: false, | 323 | ), |
324 | }, | 324 | deprecated: false, |
325 | StructureNode { | 325 | }, |
326 | parent: None, | 326 | StructureNode { |
327 | label: "S", | 327 | parent: None, |
328 | navigation_range: [201; 202), | 328 | label: "S", |
329 | node_range: [194; 213), | 329 | navigation_range: [201; 202), |
330 | kind: STATIC_DEF, | 330 | node_range: [194; 213), |
331 | detail: Some( | 331 | kind: STATIC_DEF, |
332 | "i32", | 332 | detail: Some( |
333 | ), | 333 | "i32", |
334 | deprecated: false, | 334 | ), |
335 | }, | 335 | deprecated: false, |
336 | StructureNode { | 336 | }, |
337 | parent: None, | 337 | StructureNode { |
338 | label: "C", | 338 | parent: None, |
339 | navigation_range: [220; 221), | 339 | label: "C", |
340 | node_range: [214; 232), | 340 | navigation_range: [220; 221), |
341 | kind: CONST_DEF, | 341 | node_range: [214; 232), |
342 | detail: Some( | 342 | kind: CONST_DEF, |
343 | "i32", | 343 | detail: Some( |
344 | ), | 344 | "i32", |
345 | deprecated: false, | 345 | ), |
346 | }, | 346 | deprecated: false, |
347 | StructureNode { | 347 | }, |
348 | parent: None, | 348 | StructureNode { |
349 | label: "impl E", | 349 | parent: None, |
350 | navigation_range: [239; 240), | 350 | label: "impl E", |
351 | node_range: [234; 243), | 351 | navigation_range: [239; 240), |
352 | kind: IMPL_BLOCK, | 352 | node_range: [234; 243), |
353 | detail: None, | 353 | kind: IMPL_BLOCK, |
354 | deprecated: false, | 354 | detail: None, |
355 | }, | 355 | deprecated: false, |
356 | StructureNode { | 356 | }, |
357 | parent: None, | 357 | StructureNode { |
358 | label: "impl fmt::Debug for E", | 358 | parent: None, |
359 | navigation_range: [265; 266), | 359 | label: "impl fmt::Debug for E", |
360 | node_range: [245; 269), | 360 | navigation_range: [265; 266), |
361 | kind: IMPL_BLOCK, | 361 | node_range: [245; 269), |
362 | detail: None, | 362 | kind: IMPL_BLOCK, |
363 | deprecated: false, | 363 | detail: None, |
364 | }, | 364 | deprecated: false, |
365 | StructureNode { | 365 | }, |
366 | parent: None, | 366 | StructureNode { |
367 | label: "mc", | 367 | parent: None, |
368 | navigation_range: [284; 286), | 368 | label: "mc", |
369 | node_range: [271; 303), | 369 | navigation_range: [284; 286), |
370 | kind: MACRO_CALL, | 370 | node_range: [271; 303), |
371 | detail: None, | 371 | kind: MACRO_CALL, |
372 | deprecated: false, | 372 | detail: None, |
373 | }, | 373 | deprecated: false, |
374 | StructureNode { | 374 | }, |
375 | parent: None, | 375 | StructureNode { |
376 | label: "obsolete", | 376 | parent: None, |
377 | navigation_range: [322; 330), | 377 | label: "obsolete", |
378 | node_range: [305; 335), | 378 | navigation_range: [322; 330), |
379 | kind: FN_DEF, | 379 | node_range: [305; 335), |
380 | detail: Some( | 380 | kind: FN_DEF, |
381 | "fn()", | 381 | detail: Some( |
382 | ), | 382 | "fn()", |
383 | deprecated: true, | 383 | ), |
384 | }, | 384 | deprecated: true, |
385 | StructureNode { | 385 | }, |
386 | parent: None, | 386 | StructureNode { |
387 | label: "very_obsolete", | 387 | parent: None, |
388 | navigation_range: [375; 388), | 388 | label: "very_obsolete", |
389 | node_range: [337; 393), | 389 | navigation_range: [375; 388), |
390 | kind: FN_DEF, | 390 | node_range: [337; 393), |
391 | detail: Some( | 391 | kind: FN_DEF, |
392 | "fn()", | 392 | detail: Some( |
393 | ), | 393 | "fn()", |
394 | deprecated: true, | 394 | ), |
395 | }, | 395 | deprecated: true, |
396 | ]"# | 396 | }, |
397 | ] | ||
398 | "### | ||
397 | ); | 399 | ); |
398 | } | 400 | } |
399 | } | 401 | } |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 086e6dec3..07d511fb3 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -5,7 +5,7 @@ use ra_db::SourceDatabase; | |||
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, | 6 | algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, |
7 | ast::{self, DocCommentsOwner}, | 7 | ast::{self, DocCommentsOwner}, |
8 | match_ast, AstNode, | 8 | AstNode, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -14,7 +14,7 @@ use crate::{ | |||
14 | description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, | 14 | description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, |
15 | rust_code_markup_with_doc, ShortLabel, | 15 | rust_code_markup_with_doc, ShortLabel, |
16 | }, | 16 | }, |
17 | references::{classify_name_ref, NameKind::*}, | 17 | references::{classify_name, classify_name_ref, NameKind, NameKind::*}, |
18 | FilePosition, FileRange, RangeInfo, | 18 | FilePosition, FileRange, RangeInfo, |
19 | }; | 19 | }; |
20 | 20 | ||
@@ -92,65 +92,88 @@ fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> { | |||
92 | } | 92 | } |
93 | } | 93 | } |
94 | 94 | ||
95 | fn hover_text_from_name_kind( | ||
96 | db: &RootDatabase, | ||
97 | name_kind: NameKind, | ||
98 | no_fallback: &mut bool, | ||
99 | ) -> Option<String> { | ||
100 | return match name_kind { | ||
101 | Macro(it) => { | ||
102 | let src = it.source(db); | ||
103 | hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast))) | ||
104 | } | ||
105 | Field(it) => { | ||
106 | let src = it.source(db); | ||
107 | match src.ast { | ||
108 | hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), | ||
109 | _ => None, | ||
110 | } | ||
111 | } | ||
112 | AssocItem(it) => match it { | ||
113 | hir::AssocItem::Function(it) => from_def_source(db, it), | ||
114 | hir::AssocItem::Const(it) => from_def_source(db, it), | ||
115 | hir::AssocItem::TypeAlias(it) => from_def_source(db, it), | ||
116 | }, | ||
117 | Def(it) => match it { | ||
118 | hir::ModuleDef::Module(it) => match it.definition_source(db).ast { | ||
119 | hir::ModuleSource::Module(it) => { | ||
120 | hover_text(it.doc_comment_text(), it.short_label()) | ||
121 | } | ||
122 | _ => None, | ||
123 | }, | ||
124 | hir::ModuleDef::Function(it) => from_def_source(db, it), | ||
125 | hir::ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it), | ||
126 | hir::ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it), | ||
127 | hir::ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it), | ||
128 | hir::ModuleDef::EnumVariant(it) => from_def_source(db, it), | ||
129 | hir::ModuleDef::Const(it) => from_def_source(db, it), | ||
130 | hir::ModuleDef::Static(it) => from_def_source(db, it), | ||
131 | hir::ModuleDef::Trait(it) => from_def_source(db, it), | ||
132 | hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), | ||
133 | hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), | ||
134 | }, | ||
135 | SelfType(ty) => match ty.as_adt() { | ||
136 | Some((adt_def, _)) => match adt_def { | ||
137 | hir::Adt::Struct(it) => from_def_source(db, it), | ||
138 | hir::Adt::Union(it) => from_def_source(db, it), | ||
139 | hir::Adt::Enum(it) => from_def_source(db, it), | ||
140 | }, | ||
141 | _ => None, | ||
142 | }, | ||
143 | Local(_) => { | ||
144 | // Hover for these shows type names | ||
145 | *no_fallback = true; | ||
146 | None | ||
147 | } | ||
148 | GenericParam(_) => { | ||
149 | // FIXME: Hover for generic param | ||
150 | None | ||
151 | } | ||
152 | }; | ||
153 | |||
154 | fn from_def_source<A, D>(db: &RootDatabase, def: D) -> Option<String> | ||
155 | where | ||
156 | D: HasSource<Ast = A>, | ||
157 | A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, | ||
158 | { | ||
159 | let src = def.source(db); | ||
160 | hover_text(src.ast.doc_comment_text(), src.ast.short_label()) | ||
161 | } | ||
162 | } | ||
163 | |||
95 | pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> { | 164 | pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> { |
96 | let parse = db.parse(position.file_id); | 165 | let parse = db.parse(position.file_id); |
97 | let file = parse.tree(); | 166 | let file = parse.tree(); |
167 | |||
98 | let mut res = HoverResult::new(); | 168 | let mut res = HoverResult::new(); |
99 | 169 | ||
100 | let mut range = None; | 170 | let mut range = if let Some(name_ref) = |
101 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { | 171 | find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) |
172 | { | ||
102 | let mut no_fallback = false; | 173 | let mut no_fallback = false; |
103 | let name_kind = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind); | 174 | if let Some(name_kind) = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind) |
104 | match name_kind { | 175 | { |
105 | Some(Macro(it)) => { | 176 | res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) |
106 | let src = it.source(db); | ||
107 | res.extend(hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast)))); | ||
108 | } | ||
109 | Some(Field(it)) => { | ||
110 | let src = it.source(db); | ||
111 | if let hir::FieldSource::Named(it) = src.ast { | ||
112 | res.extend(hover_text(it.doc_comment_text(), it.short_label())); | ||
113 | } | ||
114 | } | ||
115 | Some(AssocItem(it)) => res.extend(match it { | ||
116 | hir::AssocItem::Function(it) => from_def_source(db, it), | ||
117 | hir::AssocItem::Const(it) => from_def_source(db, it), | ||
118 | hir::AssocItem::TypeAlias(it) => from_def_source(db, it), | ||
119 | }), | ||
120 | Some(Def(it)) => match it { | ||
121 | hir::ModuleDef::Module(it) => { | ||
122 | if let hir::ModuleSource::Module(it) = it.definition_source(db).ast { | ||
123 | res.extend(hover_text(it.doc_comment_text(), it.short_label())) | ||
124 | } | ||
125 | } | ||
126 | hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)), | ||
127 | hir::ModuleDef::Adt(Adt::Struct(it)) => res.extend(from_def_source(db, it)), | ||
128 | hir::ModuleDef::Adt(Adt::Union(it)) => res.extend(from_def_source(db, it)), | ||
129 | hir::ModuleDef::Adt(Adt::Enum(it)) => res.extend(from_def_source(db, it)), | ||
130 | hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)), | ||
131 | hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)), | ||
132 | hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)), | ||
133 | hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)), | ||
134 | hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)), | ||
135 | hir::ModuleDef::BuiltinType(it) => res.extend(Some(it.to_string())), | ||
136 | }, | ||
137 | Some(SelfType(ty)) => { | ||
138 | if let Some((adt_def, _)) = ty.as_adt() { | ||
139 | res.extend(match adt_def { | ||
140 | hir::Adt::Struct(it) => from_def_source(db, it), | ||
141 | hir::Adt::Union(it) => from_def_source(db, it), | ||
142 | hir::Adt::Enum(it) => from_def_source(db, it), | ||
143 | }) | ||
144 | } | ||
145 | } | ||
146 | Some(Local(_)) => { | ||
147 | // Hover for these shows type names | ||
148 | no_fallback = true; | ||
149 | } | ||
150 | Some(GenericParam(_)) => { | ||
151 | // FIXME: Hover for generic param | ||
152 | } | ||
153 | None => {} | ||
154 | } | 177 | } |
155 | 178 | ||
156 | if res.is_empty() && !no_fallback { | 179 | if res.is_empty() && !no_fallback { |
@@ -164,55 +187,24 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
164 | } | 187 | } |
165 | 188 | ||
166 | if !res.is_empty() { | 189 | if !res.is_empty() { |
167 | range = Some(name_ref.syntax().text_range()) | 190 | Some(name_ref.syntax().text_range()) |
191 | } else { | ||
192 | None | ||
168 | } | 193 | } |
169 | } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { | 194 | } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { |
170 | if let Some(parent) = name.syntax().parent() { | 195 | if let Some(name_kind) = classify_name(db, position.file_id, &name).map(|d| d.kind) { |
171 | let text = match_ast! { | 196 | let mut _b: bool = true; |
172 | match parent { | 197 | res.extend(hover_text_from_name_kind(db, name_kind, &mut _b)); |
173 | ast::StructDef(it) => { | ||
174 | hover_text(it.doc_comment_text(), it.short_label()) | ||
175 | }, | ||
176 | ast::EnumDef(it) => { | ||
177 | hover_text(it.doc_comment_text(), it.short_label()) | ||
178 | }, | ||
179 | ast::EnumVariant(it) => { | ||
180 | hover_text(it.doc_comment_text(), it.short_label()) | ||
181 | }, | ||
182 | ast::FnDef(it) => { | ||
183 | hover_text(it.doc_comment_text(), it.short_label()) | ||
184 | }, | ||
185 | ast::TypeAliasDef(it) => { | ||
186 | hover_text(it.doc_comment_text(), it.short_label()) | ||
187 | }, | ||
188 | ast::ConstDef(it) => { | ||
189 | hover_text(it.doc_comment_text(), it.short_label()) | ||
190 | }, | ||
191 | ast::StaticDef(it) => { | ||
192 | hover_text(it.doc_comment_text(), it.short_label()) | ||
193 | }, | ||
194 | ast::TraitDef(it) => { | ||
195 | hover_text(it.doc_comment_text(), it.short_label()) | ||
196 | }, | ||
197 | ast::RecordFieldDef(it) => { | ||
198 | hover_text(it.doc_comment_text(), it.short_label()) | ||
199 | }, | ||
200 | ast::Module(it) => { | ||
201 | hover_text(it.doc_comment_text(), it.short_label()) | ||
202 | }, | ||
203 | ast::MacroCall(it) => { | ||
204 | hover_text(it.doc_comment_text(), None) | ||
205 | }, | ||
206 | _ => None, | ||
207 | } | ||
208 | }; | ||
209 | res.extend(text); | ||
210 | } | 198 | } |
211 | 199 | ||
212 | if !res.is_empty() && range.is_none() { | 200 | if !res.is_empty() { |
213 | range = Some(name.syntax().text_range()); | 201 | Some(name.syntax().text_range()) |
202 | } else { | ||
203 | None | ||
214 | } | 204 | } |
215 | } | 205 | } else { |
206 | None | ||
207 | }; | ||
216 | 208 | ||
217 | if range.is_none() { | 209 | if range.is_none() { |
218 | let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| { | 210 | let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| { |
@@ -221,23 +213,13 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
221 | let frange = FileRange { file_id: position.file_id, range: node.text_range() }; | 213 | let frange = FileRange { file_id: position.file_id, range: node.text_range() }; |
222 | res.extend(type_of(db, frange).map(rust_code_markup)); | 214 | res.extend(type_of(db, frange).map(rust_code_markup)); |
223 | range = Some(node.text_range()); | 215 | range = Some(node.text_range()); |
224 | } | 216 | }; |
225 | 217 | ||
226 | let range = range?; | 218 | let range = range?; |
227 | if res.is_empty() { | 219 | if res.is_empty() { |
228 | return None; | 220 | return None; |
229 | } | 221 | } |
230 | let res = RangeInfo::new(range, res); | 222 | Some(RangeInfo::new(range, res)) |
231 | return Some(res); | ||
232 | |||
233 | fn from_def_source<A, D>(db: &RootDatabase, def: D) -> Option<String> | ||
234 | where | ||
235 | D: HasSource<Ast = A>, | ||
236 | A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, | ||
237 | { | ||
238 | let src = def.source(db); | ||
239 | hover_text(src.ast.doc_comment_text(), src.ast.short_label()) | ||
240 | } | ||
241 | } | 223 | } |
242 | 224 | ||
243 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | 225 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { |
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index f1c0dc164..2ff10b89a 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs | |||
@@ -214,58 +214,60 @@ fn main() { | |||
214 | }"#, | 214 | }"#, |
215 | ); | 215 | ); |
216 | 216 | ||
217 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ | 217 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
218 | InlayHint { | 218 | [ |
219 | range: [193; 197), | 219 | InlayHint { |
220 | kind: TypeHint, | 220 | range: [193; 197), |
221 | label: "i32", | 221 | kind: TypeHint, |
222 | }, | 222 | label: "i32", |
223 | InlayHint { | 223 | }, |
224 | range: [236; 244), | 224 | InlayHint { |
225 | kind: TypeHint, | 225 | range: [236; 244), |
226 | label: "i32", | 226 | kind: TypeHint, |
227 | }, | 227 | label: "i32", |
228 | InlayHint { | 228 | }, |
229 | range: [275; 279), | 229 | InlayHint { |
230 | kind: TypeHint, | 230 | range: [275; 279), |
231 | label: "&str", | 231 | kind: TypeHint, |
232 | }, | 232 | label: "&str", |
233 | InlayHint { | 233 | }, |
234 | range: [539; 543), | 234 | InlayHint { |
235 | kind: TypeHint, | 235 | range: [539; 543), |
236 | label: "(i32, char)", | 236 | kind: TypeHint, |
237 | }, | 237 | label: "(i32, char)", |
238 | InlayHint { | 238 | }, |
239 | range: [566; 567), | 239 | InlayHint { |
240 | kind: TypeHint, | 240 | range: [566; 567), |
241 | label: "i32", | 241 | kind: TypeHint, |
242 | }, | 242 | label: "i32", |
243 | InlayHint { | 243 | }, |
244 | range: [570; 571), | 244 | InlayHint { |
245 | kind: TypeHint, | 245 | range: [570; 571), |
246 | label: "i32", | 246 | kind: TypeHint, |
247 | }, | 247 | label: "i32", |
248 | InlayHint { | 248 | }, |
249 | range: [573; 574), | 249 | InlayHint { |
250 | kind: TypeHint, | 250 | range: [573; 574), |
251 | label: "i32", | 251 | kind: TypeHint, |
252 | }, | 252 | label: "i32", |
253 | InlayHint { | 253 | }, |
254 | range: [584; 585), | 254 | InlayHint { |
255 | kind: TypeHint, | 255 | range: [584; 585), |
256 | label: "i32", | 256 | kind: TypeHint, |
257 | }, | 257 | label: "i32", |
258 | InlayHint { | 258 | }, |
259 | range: [577; 578), | 259 | InlayHint { |
260 | kind: TypeHint, | 260 | range: [577; 578), |
261 | label: "f64", | 261 | kind: TypeHint, |
262 | }, | 262 | label: "f64", |
263 | InlayHint { | 263 | }, |
264 | range: [580; 581), | 264 | InlayHint { |
265 | kind: TypeHint, | 265 | range: [580; 581), |
266 | label: "f64", | 266 | kind: TypeHint, |
267 | }, | 267 | label: "f64", |
268 | ]"# | 268 | }, |
269 | ] | ||
270 | "### | ||
269 | ); | 271 | ); |
270 | } | 272 | } |
271 | 273 | ||
@@ -281,18 +283,20 @@ fn main() { | |||
281 | }"#, | 283 | }"#, |
282 | ); | 284 | ); |
283 | 285 | ||
284 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ | 286 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
285 | InlayHint { | 287 | [ |
286 | range: [21; 30), | 288 | InlayHint { |
287 | kind: TypeHint, | 289 | range: [21; 30), |
288 | label: "i32", | 290 | kind: TypeHint, |
289 | }, | 291 | label: "i32", |
290 | InlayHint { | 292 | }, |
291 | range: [57; 66), | 293 | InlayHint { |
292 | kind: TypeHint, | 294 | range: [57; 66), |
293 | label: "i32", | 295 | kind: TypeHint, |
294 | }, | 296 | label: "i32", |
295 | ]"# | 297 | }, |
298 | ] | ||
299 | "### | ||
296 | ); | 300 | ); |
297 | } | 301 | } |
298 | 302 | ||
@@ -308,18 +312,20 @@ fn main() { | |||
308 | }"#, | 312 | }"#, |
309 | ); | 313 | ); |
310 | 314 | ||
311 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ | 315 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
312 | InlayHint { | 316 | [ |
313 | range: [21; 30), | 317 | InlayHint { |
314 | kind: TypeHint, | 318 | range: [21; 30), |
315 | label: "i32", | 319 | kind: TypeHint, |
316 | }, | 320 | label: "i32", |
317 | InlayHint { | 321 | }, |
318 | range: [44; 53), | 322 | InlayHint { |
319 | kind: TypeHint, | 323 | range: [44; 53), |
320 | label: "i32", | 324 | kind: TypeHint, |
321 | }, | 325 | label: "i32", |
322 | ]"# | 326 | }, |
327 | ] | ||
328 | "### | ||
323 | ); | 329 | ); |
324 | } | 330 | } |
325 | 331 | ||
@@ -354,33 +360,35 @@ fn main() { | |||
354 | }"#, | 360 | }"#, |
355 | ); | 361 | ); |
356 | 362 | ||
357 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ | 363 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
358 | InlayHint { | 364 | [ |
359 | range: [166; 170), | 365 | InlayHint { |
360 | kind: TypeHint, | 366 | range: [166; 170), |
361 | label: "CustomOption<Test>", | 367 | kind: TypeHint, |
362 | }, | 368 | label: "CustomOption<Test>", |
363 | InlayHint { | 369 | }, |
364 | range: [334; 338), | 370 | InlayHint { |
365 | kind: TypeHint, | 371 | range: [334; 338), |
366 | label: "&Test", | 372 | kind: TypeHint, |
367 | }, | 373 | label: "&Test", |
368 | InlayHint { | 374 | }, |
369 | range: [389; 390), | 375 | InlayHint { |
370 | kind: TypeHint, | 376 | range: [389; 390), |
371 | label: "&CustomOption<u32>", | 377 | kind: TypeHint, |
372 | }, | 378 | label: "&CustomOption<u32>", |
373 | InlayHint { | 379 | }, |
374 | range: [392; 393), | 380 | InlayHint { |
375 | kind: TypeHint, | 381 | range: [392; 393), |
376 | label: "&u8", | 382 | kind: TypeHint, |
377 | }, | 383 | label: "&u8", |
378 | InlayHint { | 384 | }, |
379 | range: [531; 532), | 385 | InlayHint { |
380 | kind: TypeHint, | 386 | range: [531; 532), |
381 | label: "&u32", | 387 | kind: TypeHint, |
382 | }, | 388 | label: "&u32", |
383 | ]"# | 389 | }, |
390 | ] | ||
391 | "### | ||
384 | ); | 392 | ); |
385 | } | 393 | } |
386 | 394 | ||
@@ -416,33 +424,33 @@ fn main() { | |||
416 | ); | 424 | ); |
417 | 425 | ||
418 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" | 426 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
419 | ⋮[ | 427 | [ |
420 | ⋮ InlayHint { | 428 | InlayHint { |
421 | ⋮ range: [166; 170), | 429 | range: [166; 170), |
422 | ⋮ kind: TypeHint, | 430 | kind: TypeHint, |
423 | ⋮ label: "CustomOption<Test>", | 431 | label: "CustomOption<Test>", |
424 | ⋮ }, | 432 | }, |
425 | ⋮ InlayHint { | 433 | InlayHint { |
426 | ⋮ range: [343; 347), | 434 | range: [343; 347), |
427 | ⋮ kind: TypeHint, | 435 | kind: TypeHint, |
428 | ⋮ label: "&Test", | 436 | label: "&Test", |
429 | ⋮ }, | 437 | }, |
430 | ⋮ InlayHint { | 438 | InlayHint { |
431 | ⋮ range: [401; 402), | 439 | range: [401; 402), |
432 | ⋮ kind: TypeHint, | 440 | kind: TypeHint, |
433 | ⋮ label: "&CustomOption<u32>", | 441 | label: "&CustomOption<u32>", |
434 | ⋮ }, | 442 | }, |
435 | ⋮ InlayHint { | 443 | InlayHint { |
436 | ⋮ range: [404; 405), | 444 | range: [404; 405), |
437 | ⋮ kind: TypeHint, | 445 | kind: TypeHint, |
438 | ⋮ label: "&u8", | 446 | label: "&u8", |
439 | ⋮ }, | 447 | }, |
440 | ⋮ InlayHint { | 448 | InlayHint { |
441 | ⋮ range: [549; 550), | 449 | range: [549; 550), |
442 | ⋮ kind: TypeHint, | 450 | kind: TypeHint, |
443 | ⋮ label: "&u32", | 451 | label: "&u32", |
444 | ⋮ }, | 452 | }, |
445 | ⋮] | 453 | ] |
446 | "### | 454 | "### |
447 | ); | 455 | ); |
448 | } | 456 | } |
@@ -478,28 +486,30 @@ fn main() { | |||
478 | }"#, | 486 | }"#, |
479 | ); | 487 | ); |
480 | 488 | ||
481 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r#"[ | 489 | assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" |
482 | InlayHint { | 490 | [ |
483 | range: [311; 315), | 491 | InlayHint { |
484 | kind: TypeHint, | 492 | range: [311; 315), |
485 | label: "Test", | 493 | kind: TypeHint, |
486 | }, | 494 | label: "Test", |
487 | InlayHint { | 495 | }, |
488 | range: [358; 359), | 496 | InlayHint { |
489 | kind: TypeHint, | 497 | range: [358; 359), |
490 | label: "CustomOption<u32>", | 498 | kind: TypeHint, |
491 | }, | 499 | label: "CustomOption<u32>", |
492 | InlayHint { | 500 | }, |
493 | range: [361; 362), | 501 | InlayHint { |
494 | kind: TypeHint, | 502 | range: [361; 362), |
495 | label: "u8", | 503 | kind: TypeHint, |
496 | }, | 504 | label: "u8", |
497 | InlayHint { | 505 | }, |
498 | range: [484; 485), | 506 | InlayHint { |
499 | kind: TypeHint, | 507 | range: [484; 485), |
500 | label: "u32", | 508 | kind: TypeHint, |
501 | }, | 509 | label: "u32", |
502 | ]"# | 510 | }, |
511 | ] | ||
512 | "### | ||
503 | ); | 513 | ); |
504 | } | 514 | } |
505 | } | 515 | } |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 1b5c8deea..366ac8048 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -97,24 +97,26 @@ mod tests { | |||
97 | ); | 97 | ); |
98 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 98 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
99 | assert_debug_snapshot!(&runnables, | 99 | assert_debug_snapshot!(&runnables, |
100 | @r#"[ | 100 | @r###" |
101 | Runnable { | 101 | [ |
102 | range: [1; 21), | 102 | Runnable { |
103 | kind: Bin, | 103 | range: [1; 21), |
104 | }, | 104 | kind: Bin, |
105 | Runnable { | 105 | }, |
106 | range: [22; 46), | 106 | Runnable { |
107 | kind: Test { | 107 | range: [22; 46), |
108 | name: "test_foo", | 108 | kind: Test { |
109 | }, | 109 | name: "test_foo", |
110 | }, | 110 | }, |
111 | Runnable { | 111 | }, |
112 | range: [47; 81), | 112 | Runnable { |
113 | kind: Test { | 113 | range: [47; 81), |
114 | name: "test_foo", | 114 | kind: Test { |
115 | }, | 115 | name: "test_foo", |
116 | }, | 116 | }, |
117 | ]"# | 117 | }, |
118 | ] | ||
119 | "### | ||
118 | ); | 120 | ); |
119 | } | 121 | } |
120 | 122 | ||
@@ -132,20 +134,22 @@ mod tests { | |||
132 | ); | 134 | ); |
133 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 135 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
134 | assert_debug_snapshot!(&runnables, | 136 | assert_debug_snapshot!(&runnables, |
135 | @r#"[ | 137 | @r###" |
136 | Runnable { | 138 | [ |
137 | range: [1; 59), | 139 | Runnable { |
138 | kind: TestMod { | 140 | range: [1; 59), |
139 | path: "test_mod", | 141 | kind: TestMod { |
140 | }, | 142 | path: "test_mod", |
141 | }, | 143 | }, |
142 | Runnable { | 144 | }, |
143 | range: [28; 57), | 145 | Runnable { |
144 | kind: Test { | 146 | range: [28; 57), |
145 | name: "test_foo1", | 147 | kind: Test { |
146 | }, | 148 | name: "test_foo1", |
147 | }, | 149 | }, |
148 | ]"# | 150 | }, |
151 | ] | ||
152 | "### | ||
149 | ); | 153 | ); |
150 | } | 154 | } |
151 | 155 | ||
@@ -165,20 +169,22 @@ mod tests { | |||
165 | ); | 169 | ); |
166 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 170 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
167 | assert_debug_snapshot!(&runnables, | 171 | assert_debug_snapshot!(&runnables, |
168 | @r#"[ | 172 | @r###" |
169 | Runnable { | 173 | [ |
170 | range: [23; 85), | 174 | Runnable { |
171 | kind: TestMod { | 175 | range: [23; 85), |
172 | path: "foo::test_mod", | 176 | kind: TestMod { |
173 | }, | 177 | path: "foo::test_mod", |
174 | }, | 178 | }, |
175 | Runnable { | 179 | }, |
176 | range: [46; 79), | 180 | Runnable { |
177 | kind: Test { | 181 | range: [46; 79), |
178 | name: "test_foo1", | 182 | kind: Test { |
179 | }, | 183 | name: "test_foo1", |
180 | }, | 184 | }, |
181 | ]"# | 185 | }, |
186 | ] | ||
187 | "### | ||
182 | ); | 188 | ); |
183 | } | 189 | } |
184 | 190 | ||
@@ -200,20 +206,22 @@ mod tests { | |||
200 | ); | 206 | ); |
201 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 207 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
202 | assert_debug_snapshot!(&runnables, | 208 | assert_debug_snapshot!(&runnables, |
203 | @r#"[ | 209 | @r###" |
204 | Runnable { | 210 | [ |
205 | range: [41; 115), | 211 | Runnable { |
206 | kind: TestMod { | 212 | range: [41; 115), |
207 | path: "foo::bar::test_mod", | 213 | kind: TestMod { |
208 | }, | 214 | path: "foo::bar::test_mod", |
209 | }, | 215 | }, |
210 | Runnable { | 216 | }, |
211 | range: [68; 105), | 217 | Runnable { |
212 | kind: Test { | 218 | range: [68; 105), |
213 | name: "test_foo1", | 219 | kind: Test { |
214 | }, | 220 | name: "test_foo1", |
215 | }, | 221 | }, |
216 | ]"# | 222 | }, |
223 | ] | ||
224 | "### | ||
217 | ); | 225 | ); |
218 | } | 226 | } |
219 | 227 | ||
diff --git a/crates/ra_mbe/Cargo.toml b/crates/ra_mbe/Cargo.toml index e8ef2457b..b02e45ee3 100644 --- a/crates/ra_mbe/Cargo.toml +++ b/crates/ra_mbe/Cargo.toml | |||
@@ -9,7 +9,7 @@ ra_syntax = { path = "../ra_syntax" } | |||
9 | ra_parser = { path = "../ra_parser" } | 9 | ra_parser = { path = "../ra_parser" } |
10 | tt = { path = "../ra_tt", package = "ra_tt" } | 10 | tt = { path = "../ra_tt", package = "ra_tt" } |
11 | rustc-hash = "1.0.0" | 11 | rustc-hash = "1.0.0" |
12 | smallvec = "0.6.9" | 12 | smallvec = "1.0.0" |
13 | log = "0.4.5" | 13 | log = "0.4.5" |
14 | 14 | ||
15 | [dev-dependencies] | 15 | [dev-dependencies] |
diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml index bb241258c..751bcdeb8 100644 --- a/crates/ra_prof/Cargo.toml +++ b/crates/ra_prof/Cargo.toml | |||
@@ -1,19 +1,19 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | 2 | edition = "2018" |
3 | name = "ra_prof" | 3 | name = "ra_prof" |
4 | version = "0.1.0" | 4 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | publish = false | 6 | publish = false |
7 | 7 | ||
8 | [dependencies] | 8 | [dependencies] |
9 | once_cell = "1.0.1" | 9 | once_cell = "1.0.1" |
10 | itertools = "0.8.0" | 10 | itertools = "0.8.0" |
11 | backtrace = "0.3.28" | 11 | backtrace = "0.3.28" |
12 | 12 | ||
13 | [target.'cfg(not(target_env = "msvc"))'.dependencies] | 13 | [target.'cfg(not(target_env = "msvc"))'.dependencies] |
14 | jemallocator = { version = "0.3.2", optional = true } | 14 | jemallocator = { version = "0.3.2", optional = true } |
15 | jemalloc-ctl = { version = "0.3.2", optional = true } | 15 | jemalloc-ctl = { version = "0.3.2", optional = true } |
16 | 16 | ||
17 | [features] | 17 | [features] |
18 | jemalloc = [ "jemallocator", "jemalloc-ctl" ] | 18 | jemalloc = [ "jemallocator", "jemalloc-ctl" ] |
19 | cpu_profiler = [] | 19 | cpu_profiler = [] |
diff --git a/docs/user/assists.md b/docs/user/assists.md index 303353e74..8da7578e2 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -150,6 +150,27 @@ use std::collections::HashMap; | |||
150 | fn process(map: HashMap<String, String>) {} | 150 | fn process(map: HashMap<String, String>) {} |
151 | ``` | 151 | ``` |
152 | 152 | ||
153 | ## `add_new` | ||
154 | |||
155 | Adds a new inherent impl for a type. | ||
156 | |||
157 | ```rust | ||
158 | // BEFORE | ||
159 | struct Ctx<T: Clone> { | ||
160 | data: T,┃ | ||
161 | } | ||
162 | |||
163 | // AFTER | ||
164 | struct Ctx<T: Clone> { | ||
165 | data: T, | ||
166 | } | ||
167 | |||
168 | impl<T: Clone> Ctx<T> { | ||
169 | fn new(data: T) -> Self { Self { data } } | ||
170 | } | ||
171 | |||
172 | ``` | ||
173 | |||
153 | ## `apply_demorgan` | 174 | ## `apply_demorgan` |
154 | 175 | ||
155 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | 176 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). |