aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/tests/test/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/tests/test/main.rs')
-rw-r--r--crates/ra_analysis/tests/test/main.rs549
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 @@
1mod runnables;
2mod type_of;
3
4use ra_syntax::TextRange;
5use test_utils::{assert_eq_dbg, assert_eq_text};
6
7use ra_analysis::{
8 mock_analysis::{analysis_and_position, single_file, single_file_with_position, MockAnalysis},
9 AnalysisChange, CrateGraph, FileId, FnSignatureInfo,
10};
11
12fn 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]
18fn 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]
38fn 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]
77fn 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]
95fn 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]
102fn 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]
119fn 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]
138fn 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]
162fn test_fn_signature_two_args_first() {
163 let (desc, param) = get_signature(
164 r#"fn foo(x: u32, y: u32) -> u32 {x + y}
165fn 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]
175fn test_fn_signature_two_args_second() {
176 let (desc, param) = get_signature(
177 r#"fn foo(x: u32, y: u32) -> u32 {x + y}
178fn 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]
188fn test_fn_signature_for_impl() {
189 let (desc, param) = get_signature(
190 r#"struct F; impl F { pub fn new() { F{}} }
191fn 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]
201fn test_fn_signature_for_method_self() {
202 let (desc, param) = get_signature(
203 r#"struct F;
204impl F {
205 pub fn new() -> F{
206 F{}
207 }
208
209 pub fn do_it(&self) {}
210}
211
212fn 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]
225fn test_fn_signature_for_method_with_arg() {
226 let (desc, param) = get_signature(
227 r#"struct F;
228impl F {
229 pub fn new() -> F{
230 F{}
231 }
232
233 pub fn do_it(&self, x: i32) {}
234}
235
236fn 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]
249fn test_fn_signature_with_docs_simple() {
250 let (desc, param) = get_signature(
251 r#"
252// test
253fn foo(j: u32) -> u32 {
254 j
255}
256
257fn 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]
272fn 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/// ```
284pub fn add_one(x: i32) -> i32 {
285 x + 1
286}
287
288pub 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
306let five = 5;
307
308assert_eq!(6, my_crate::add_one(5));
309```"#
310 .into()
311 )
312 );
313}
314
315#[test]
316fn test_fn_signature_with_docs_impl() {
317 let (desc, param) = get_signature(
318 r#"
319struct addr;
320impl 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
335pub 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
354let five = 5;
355
356assert_eq!(6, my_crate::add_one(5));
357```"#
358 .into()
359 )
360 );
361}
362
363#[test]
364fn test_fn_signature_with_docs_from_actix() {
365 let (desc, param) = get_signature(
366 r#"
367pub trait WriteHandler<E>
368where
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
388pub 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
408By default this method stops actor's `Context`."#
409 .into()
410 )
411 );
412}
413
414fn 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]
420fn 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]
439fn 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]
450fn 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]
460fn 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]
491fn 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]
506fn 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]
521fn 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}
534fn 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}