diff options
author | Aleksey Kladov <[email protected]> | 2019-01-03 17:15:12 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-03 17:15:12 +0000 |
commit | cd32177a25a98026584a514de46461ce66f3eb56 (patch) | |
tree | 62a4dfebe2b179df6c7636100e1c13e33afe16f5 /crates/ra_analysis/tests/test/main.rs | |
parent | 8a24f25482f07eecab254c93223369fa532c076f (diff) |
don't create many compilation units for tests
Diffstat (limited to 'crates/ra_analysis/tests/test/main.rs')
-rw-r--r-- | crates/ra_analysis/tests/test/main.rs | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/crates/ra_analysis/tests/test/main.rs b/crates/ra_analysis/tests/test/main.rs new file mode 100644 index 000000000..23a5799b9 --- /dev/null +++ b/crates/ra_analysis/tests/test/main.rs | |||
@@ -0,0 +1,549 @@ | |||
1 | mod runnables; | ||
2 | mod type_of; | ||
3 | |||
4 | use ra_syntax::TextRange; | ||
5 | use test_utils::{assert_eq_dbg, assert_eq_text}; | ||
6 | |||
7 | use ra_analysis::{ | ||
8 | mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis}, | ||
9 | AnalysisChange, CrateGraph, FileId, FnSignatureInfo, | ||
10 | }; | ||
11 | |||
12 | fn get_signature(text: &str) -> (FnSignatureInfo, Option<usize>) { | ||
13 | let (analysis, position) = single_file_with_position(text); | ||
14 | analysis.resolve_callable(position).unwrap().unwrap() | ||
15 | } | ||
16 | |||
17 | #[test] | ||
18 | fn approximate_resolve_works_in_items() { | ||
19 | let (analysis, pos) = analysis_and_position( | ||
20 | " | ||
21 | //- /lib.rs | ||
22 | struct Foo; | ||
23 | enum E { X(Foo<|>) } | ||
24 | ", | ||
25 | ); | ||
26 | |||
27 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); | ||
28 | assert_eq_dbg( | ||
29 | r#"ReferenceResolution { | ||
30 | reference_range: [23; 26), | ||
31 | resolves_to: [NavigationTarget { file_id: FileId(1), name: "Foo", kind: STRUCT_DEF, range: [0; 11), ptr: Some(LocalSyntaxPtr { range: [0; 11), kind: STRUCT_DEF }) }] | ||
32 | }"#, | ||
33 | &symbols, | ||
34 | ); | ||
35 | } | ||
36 | |||
37 | #[test] | ||
38 | fn test_resolve_module() { | ||
39 | let (analysis, pos) = analysis_and_position( | ||
40 | " | ||
41 | //- /lib.rs | ||
42 | mod <|>foo; | ||
43 | //- /foo.rs | ||
44 | // empty | ||
45 | ", | ||
46 | ); | ||
47 | |||
48 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); | ||
49 | assert_eq_dbg( | ||
50 | r#"ReferenceResolution { | ||
51 | reference_range: [4; 7), | ||
52 | resolves_to: [NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }] | ||
53 | }"#, | ||
54 | &symbols, | ||
55 | ); | ||
56 | |||
57 | let (analysis, pos) = analysis_and_position( | ||
58 | " | ||
59 | //- /lib.rs | ||
60 | mod <|>foo; | ||
61 | //- /foo/mod.rs | ||
62 | // empty | ||
63 | ", | ||
64 | ); | ||
65 | |||
66 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); | ||
67 | assert_eq_dbg( | ||
68 | r#"ReferenceResolution { | ||
69 | reference_range: [4; 7), | ||
70 | resolves_to: [NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }] | ||
71 | }"#, | ||
72 | &symbols, | ||
73 | ); | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn test_unresolved_module_diagnostic() { | ||
78 | let (analysis, file_id) = single_file("mod foo;"); | ||
79 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | ||
80 | assert_eq_dbg( | ||
81 | r#"[Diagnostic { | ||
82 | message: "unresolved module", | ||
83 | range: [4; 7), | ||
84 | fix: Some(SourceChange { | ||
85 | label: "create module", | ||
86 | source_file_edits: [], | ||
87 | file_system_edits: [CreateFile { source_root: SourceRootId(0), path: "foo.rs" }], | ||
88 | cursor_position: None }), | ||
89 | severity: Error }]"#, | ||
90 | &diagnostics, | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | #[test] | ||
95 | fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() { | ||
96 | let (analysis, file_id) = single_file("mod foo {}"); | ||
97 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | ||
98 | assert_eq_dbg(r#"[]"#, &diagnostics); | ||
99 | } | ||
100 | |||
101 | #[test] | ||
102 | fn test_resolve_parent_module() { | ||
103 | let (analysis, pos) = analysis_and_position( | ||
104 | " | ||
105 | //- /lib.rs | ||
106 | mod foo; | ||
107 | //- /foo.rs | ||
108 | <|>// empty | ||
109 | ", | ||
110 | ); | ||
111 | let symbols = analysis.parent_module(pos).unwrap(); | ||
112 | assert_eq_dbg( | ||
113 | r#"[NavigationTarget { file_id: FileId(1), name: "foo", kind: MODULE, range: [4; 7), ptr: None }]"#, | ||
114 | &symbols, | ||
115 | ); | ||
116 | } | ||
117 | |||
118 | #[test] | ||
119 | fn test_resolve_parent_module_for_inline() { | ||
120 | let (analysis, pos) = analysis_and_position( | ||
121 | " | ||
122 | //- /lib.rs | ||
123 | mod foo { | ||
124 | mod bar { | ||
125 | mod baz { <|> } | ||
126 | } | ||
127 | } | ||
128 | ", | ||
129 | ); | ||
130 | let symbols = analysis.parent_module(pos).unwrap(); | ||
131 | assert_eq_dbg( | ||
132 | r#"[NavigationTarget { file_id: FileId(1), name: "bar", kind: MODULE, range: [18; 21), ptr: None }]"#, | ||
133 | &symbols, | ||
134 | ); | ||
135 | } | ||
136 | |||
137 | #[test] | ||
138 | fn test_resolve_crate_root() { | ||
139 | let mock = MockAnalysis::with_files( | ||
140 | " | ||
141 | //- /lib.rs | ||
142 | mod foo; | ||
143 | //- /foo.rs | ||
144 | // emtpy <|> | ||
145 | ", | ||
146 | ); | ||
147 | let root_file = mock.id_of("/lib.rs"); | ||
148 | let mod_file = mock.id_of("/foo.rs"); | ||
149 | let mut host = mock.analysis_host(); | ||
150 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); | ||
151 | |||
152 | let mut crate_graph = CrateGraph::default(); | ||
153 | let crate_id = crate_graph.add_crate_root(root_file); | ||
154 | let mut change = AnalysisChange::new(); | ||
155 | change.set_crate_graph(crate_graph); | ||
156 | host.apply_change(change); | ||
157 | |||
158 | assert_eq!(host.analysis().crate_for(mod_file).unwrap(), vec![crate_id]); | ||
159 | } | ||
160 | |||
161 | #[test] | ||
162 | fn test_fn_signature_two_args_first() { | ||
163 | let (desc, param) = get_signature( | ||
164 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
165 | fn bar() { foo(<|>3, ); }"#, | ||
166 | ); | ||
167 | |||
168 | assert_eq!(desc.name, "foo".to_string()); | ||
169 | assert_eq!(desc.params, vec!("x".to_string(), "y".to_string())); | ||
170 | assert_eq!(desc.ret_type, Some("-> u32".into())); | ||
171 | assert_eq!(param, Some(0)); | ||
172 | } | ||
173 | |||
174 | #[test] | ||
175 | fn test_fn_signature_two_args_second() { | ||
176 | let (desc, param) = get_signature( | ||
177 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
178 | fn bar() { foo(3, <|>); }"#, | ||
179 | ); | ||
180 | |||
181 | assert_eq!(desc.name, "foo".to_string()); | ||
182 | assert_eq!(desc.params, vec!("x".to_string(), "y".to_string())); | ||
183 | assert_eq!(desc.ret_type, Some("-> u32".into())); | ||
184 | assert_eq!(param, Some(1)); | ||
185 | } | ||
186 | |||
187 | #[test] | ||
188 | fn test_fn_signature_for_impl() { | ||
189 | let (desc, param) = get_signature( | ||
190 | r#"struct F; impl F { pub fn new() { F{}} } | ||
191 | fn bar() {let _ : F = F::new(<|>);}"#, | ||
192 | ); | ||
193 | |||
194 | assert_eq!(desc.name, "new".to_string()); | ||
195 | assert_eq!(desc.params, Vec::<String>::new()); | ||
196 | assert_eq!(desc.ret_type, None); | ||
197 | assert_eq!(param, None); | ||
198 | } | ||
199 | |||
200 | #[test] | ||
201 | fn test_fn_signature_for_method_self() { | ||
202 | let (desc, param) = get_signature( | ||
203 | r#"struct F; | ||
204 | impl F { | ||
205 | pub fn new() -> F{ | ||
206 | F{} | ||
207 | } | ||
208 | |||
209 | pub fn do_it(&self) {} | ||
210 | } | ||
211 | |||
212 | fn bar() { | ||
213 | let f : F = F::new(); | ||
214 | f.do_it(<|>); | ||
215 | }"#, | ||
216 | ); | ||
217 | |||
218 | assert_eq!(desc.name, "do_it".to_string()); | ||
219 | assert_eq!(desc.params, vec!["&self".to_string()]); | ||
220 | assert_eq!(desc.ret_type, None); | ||
221 | assert_eq!(param, None); | ||
222 | } | ||
223 | |||
224 | #[test] | ||
225 | fn test_fn_signature_for_method_with_arg() { | ||
226 | let (desc, param) = get_signature( | ||
227 | r#"struct F; | ||
228 | impl F { | ||
229 | pub fn new() -> F{ | ||
230 | F{} | ||
231 | } | ||
232 | |||
233 | pub fn do_it(&self, x: i32) {} | ||
234 | } | ||
235 | |||
236 | fn bar() { | ||
237 | let f : F = F::new(); | ||
238 | f.do_it(<|>); | ||
239 | }"#, | ||
240 | ); | ||
241 | |||
242 | assert_eq!(desc.name, "do_it".to_string()); | ||
243 | assert_eq!(desc.params, vec!["&self".to_string(), "x".to_string()]); | ||
244 | assert_eq!(desc.ret_type, None); | ||
245 | assert_eq!(param, Some(1)); | ||
246 | } | ||
247 | |||
248 | #[test] | ||
249 | fn test_fn_signature_with_docs_simple() { | ||
250 | let (desc, param) = get_signature( | ||
251 | r#" | ||
252 | // test | ||
253 | fn foo(j: u32) -> u32 { | ||
254 | j | ||
255 | } | ||
256 | |||
257 | fn bar() { | ||
258 | let _ = foo(<|>); | ||
259 | } | ||
260 | "#, | ||
261 | ); | ||
262 | |||
263 | assert_eq!(desc.name, "foo".to_string()); | ||
264 | assert_eq!(desc.params, vec!["j".to_string()]); | ||
265 | assert_eq!(desc.ret_type, Some("-> u32".to_string())); | ||
266 | assert_eq!(param, Some(0)); | ||
267 | assert_eq!(desc.label, "fn foo(j: u32) -> u32".to_string()); | ||
268 | assert_eq!(desc.doc, Some("test".into())); | ||
269 | } | ||
270 | |||
271 | #[test] | ||
272 | fn test_fn_signature_with_docs() { | ||
273 | let (desc, param) = get_signature( | ||
274 | r#" | ||
275 | /// Adds one to the number given. | ||
276 | /// | ||
277 | /// # Examples | ||
278 | /// | ||
279 | /// ``` | ||
280 | /// let five = 5; | ||
281 | /// | ||
282 | /// assert_eq!(6, my_crate::add_one(5)); | ||
283 | /// ``` | ||
284 | pub fn add_one(x: i32) -> i32 { | ||
285 | x + 1 | ||
286 | } | ||
287 | |||
288 | pub fn do() { | ||
289 | add_one(<|> | ||
290 | }"#, | ||
291 | ); | ||
292 | |||
293 | assert_eq!(desc.name, "add_one".to_string()); | ||
294 | assert_eq!(desc.params, vec!["x".to_string()]); | ||
295 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); | ||
296 | assert_eq!(param, Some(0)); | ||
297 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); | ||
298 | assert_eq!( | ||
299 | desc.doc, | ||
300 | Some( | ||
301 | r#"Adds one to the number given. | ||
302 | |||
303 | # Examples | ||
304 | |||
305 | ```rust | ||
306 | let five = 5; | ||
307 | |||
308 | assert_eq!(6, my_crate::add_one(5)); | ||
309 | ```"# | ||
310 | .into() | ||
311 | ) | ||
312 | ); | ||
313 | } | ||
314 | |||
315 | #[test] | ||
316 | fn test_fn_signature_with_docs_impl() { | ||
317 | let (desc, param) = get_signature( | ||
318 | r#" | ||
319 | struct addr; | ||
320 | impl addr { | ||
321 | /// Adds one to the number given. | ||
322 | /// | ||
323 | /// # Examples | ||
324 | /// | ||
325 | /// ``` | ||
326 | /// let five = 5; | ||
327 | /// | ||
328 | /// assert_eq!(6, my_crate::add_one(5)); | ||
329 | /// ``` | ||
330 | pub fn add_one(x: i32) -> i32 { | ||
331 | x + 1 | ||
332 | } | ||
333 | } | ||
334 | |||
335 | pub fn do_it() { | ||
336 | addr {}; | ||
337 | addr::add_one(<|>); | ||
338 | }"#, | ||
339 | ); | ||
340 | |||
341 | assert_eq!(desc.name, "add_one".to_string()); | ||
342 | assert_eq!(desc.params, vec!["x".to_string()]); | ||
343 | assert_eq!(desc.ret_type, Some("-> i32".to_string())); | ||
344 | assert_eq!(param, Some(0)); | ||
345 | assert_eq!(desc.label, "pub fn add_one(x: i32) -> i32".to_string()); | ||
346 | assert_eq!( | ||
347 | desc.doc, | ||
348 | Some( | ||
349 | r#"Adds one to the number given. | ||
350 | |||
351 | # Examples | ||
352 | |||
353 | ```rust | ||
354 | let five = 5; | ||
355 | |||
356 | assert_eq!(6, my_crate::add_one(5)); | ||
357 | ```"# | ||
358 | .into() | ||
359 | ) | ||
360 | ); | ||
361 | } | ||
362 | |||
363 | #[test] | ||
364 | fn test_fn_signature_with_docs_from_actix() { | ||
365 | let (desc, param) = get_signature( | ||
366 | r#" | ||
367 | pub trait WriteHandler<E> | ||
368 | where | ||
369 | Self: Actor, | ||
370 | Self::Context: ActorContext, | ||
371 | { | ||
372 | /// Method is called when writer emits error. | ||
373 | /// | ||
374 | /// If this method returns `ErrorAction::Continue` writer processing | ||
375 | /// continues otherwise stream processing stops. | ||
376 | fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running { | ||
377 | Running::Stop | ||
378 | } | ||
379 | |||
380 | /// Method is called when writer finishes. | ||
381 | /// | ||
382 | /// By default this method stops actor's `Context`. | ||
383 | fn finished(&mut self, ctx: &mut Self::Context) { | ||
384 | ctx.stop() | ||
385 | } | ||
386 | } | ||
387 | |||
388 | pub fn foo() { | ||
389 | WriteHandler r; | ||
390 | r.finished(<|>); | ||
391 | } | ||
392 | |||
393 | "#, | ||
394 | ); | ||
395 | |||
396 | assert_eq!(desc.name, "finished".to_string()); | ||
397 | assert_eq!( | ||
398 | desc.params, | ||
399 | vec!["&mut self".to_string(), "ctx".to_string()] | ||
400 | ); | ||
401 | assert_eq!(desc.ret_type, None); | ||
402 | assert_eq!(param, Some(1)); | ||
403 | assert_eq!( | ||
404 | desc.doc, | ||
405 | Some( | ||
406 | r#"Method is called when writer finishes. | ||
407 | |||
408 | By default this method stops actor's `Context`."# | ||
409 | .into() | ||
410 | ) | ||
411 | ); | ||
412 | } | ||
413 | |||
414 | fn get_all_refs(text: &str) -> Vec<(FileId, TextRange)> { | ||
415 | let (analysis, position) = single_file_with_position(text); | ||
416 | analysis.find_all_refs(position).unwrap() | ||
417 | } | ||
418 | |||
419 | #[test] | ||
420 | fn test_find_all_refs_for_local() { | ||
421 | let code = r#" | ||
422 | fn main() { | ||
423 | let mut i = 1; | ||
424 | let j = 1; | ||
425 | i = i<|> + j; | ||
426 | |||
427 | { | ||
428 | i = 0; | ||
429 | } | ||
430 | |||
431 | i = 5; | ||
432 | }"#; | ||
433 | |||
434 | let refs = get_all_refs(code); | ||
435 | assert_eq!(refs.len(), 5); | ||
436 | } | ||
437 | |||
438 | #[test] | ||
439 | fn test_find_all_refs_for_param_inside() { | ||
440 | let code = r#" | ||
441 | fn foo(i : u32) -> u32 { | ||
442 | i<|> | ||
443 | }"#; | ||
444 | |||
445 | let refs = get_all_refs(code); | ||
446 | assert_eq!(refs.len(), 2); | ||
447 | } | ||
448 | |||
449 | #[test] | ||
450 | fn test_find_all_refs_for_fn_param() { | ||
451 | let code = r#" | ||
452 | fn foo(i<|> : u32) -> u32 { | ||
453 | i | ||
454 | }"#; | ||
455 | |||
456 | let refs = get_all_refs(code); | ||
457 | assert_eq!(refs.len(), 2); | ||
458 | } | ||
459 | #[test] | ||
460 | fn test_rename_for_local() { | ||
461 | test_rename( | ||
462 | r#" | ||
463 | fn main() { | ||
464 | let mut i = 1; | ||
465 | let j = 1; | ||
466 | i = i<|> + j; | ||
467 | |||
468 | { | ||
469 | i = 0; | ||
470 | } | ||
471 | |||
472 | i = 5; | ||
473 | }"#, | ||
474 | "k", | ||
475 | r#" | ||
476 | fn main() { | ||
477 | let mut k = 1; | ||
478 | let j = 1; | ||
479 | k = k + j; | ||
480 | |||
481 | { | ||
482 | k = 0; | ||
483 | } | ||
484 | |||
485 | k = 5; | ||
486 | }"#, | ||
487 | ); | ||
488 | } | ||
489 | |||
490 | #[test] | ||
491 | fn test_rename_for_param_inside() { | ||
492 | test_rename( | ||
493 | r#" | ||
494 | fn foo(i : u32) -> u32 { | ||
495 | i<|> | ||
496 | }"#, | ||
497 | "j", | ||
498 | r#" | ||
499 | fn foo(j : u32) -> u32 { | ||
500 | j | ||
501 | }"#, | ||
502 | ); | ||
503 | } | ||
504 | |||
505 | #[test] | ||
506 | fn test_rename_refs_for_fn_param() { | ||
507 | test_rename( | ||
508 | r#" | ||
509 | fn foo(i<|> : u32) -> u32 { | ||
510 | i | ||
511 | }"#, | ||
512 | "new_name", | ||
513 | r#" | ||
514 | fn foo(new_name : u32) -> u32 { | ||
515 | new_name | ||
516 | }"#, | ||
517 | ); | ||
518 | } | ||
519 | |||
520 | #[test] | ||
521 | fn test_rename_for_mut_param() { | ||
522 | test_rename( | ||
523 | r#" | ||
524 | fn foo(mut i<|> : u32) -> u32 { | ||
525 | i | ||
526 | }"#, | ||
527 | "new_name", | ||
528 | r#" | ||
529 | fn foo(mut new_name : u32) -> u32 { | ||
530 | new_name | ||
531 | }"#, | ||
532 | ); | ||
533 | } | ||
534 | fn test_rename(text: &str, new_name: &str, expected: &str) { | ||
535 | let (analysis, position) = single_file_with_position(text); | ||
536 | let edits = analysis.rename(position, new_name).unwrap(); | ||
537 | let mut text_edit_bulder = ra_text_edit::TextEditBuilder::default(); | ||
538 | let mut file_id: Option<FileId> = None; | ||
539 | for edit in edits { | ||
540 | file_id = Some(edit.file_id); | ||
541 | for atom in edit.edit.as_atoms() { | ||
542 | text_edit_bulder.replace(atom.delete, atom.insert.clone()); | ||
543 | } | ||
544 | } | ||
545 | let result = text_edit_bulder | ||
546 | .finish() | ||
547 | .apply(&*analysis.file_text(file_id.unwrap())); | ||
548 | assert_eq_text!(expected, &*result); | ||
549 | } | ||