aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/call_info/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db/src/call_info/tests.rs')
-rw-r--r--crates/ide_db/src/call_info/tests.rs523
1 files changed, 523 insertions, 0 deletions
diff --git a/crates/ide_db/src/call_info/tests.rs b/crates/ide_db/src/call_info/tests.rs
new file mode 100644
index 000000000..9335aeaa5
--- /dev/null
+++ b/crates/ide_db/src/call_info/tests.rs
@@ -0,0 +1,523 @@
1use crate::RootDatabase;
2use base_db::{fixture::ChangeFixture, FilePosition};
3use expect_test::{expect, Expect};
4use test_utils::{mark, RangeOrOffset};
5
6/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
7pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
8 let change_fixture = ChangeFixture::parse(ra_fixture);
9 let mut database = RootDatabase::default();
10 database.apply_change(change_fixture.change);
11 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
12 let offset = match range_or_offset {
13 RangeOrOffset::Range(_) => panic!(),
14 RangeOrOffset::Offset(it) => it,
15 };
16 (database, FilePosition { file_id, offset })
17}
18
19fn check(ra_fixture: &str, expect: Expect) {
20 let (db, position) = position(ra_fixture);
21 let call_info = crate::call_info::call_info(&db, position);
22 let actual = match call_info {
23 Some(call_info) => {
24 let docs = match &call_info.doc {
25 None => "".to_string(),
26 Some(docs) => format!("{}\n------\n", docs.as_str()),
27 };
28 let params = call_info
29 .parameter_labels()
30 .enumerate()
31 .map(|(i, param)| {
32 if Some(i) == call_info.active_parameter {
33 format!("<{}>", param)
34 } else {
35 param.to_string()
36 }
37 })
38 .collect::<Vec<_>>()
39 .join(", ");
40 format!("{}{}\n({})\n", docs, call_info.signature, params)
41 }
42 None => String::new(),
43 };
44 expect.assert_eq(&actual);
45}
46
47#[test]
48fn test_fn_signature_two_args() {
49 check(
50 r#"
51fn foo(x: u32, y: u32) -> u32 {x + y}
52fn bar() { foo(<|>3, ); }
53"#,
54 expect![[r#"
55 fn foo(x: u32, y: u32) -> u32
56 (<x: u32>, y: u32)
57 "#]],
58 );
59 check(
60 r#"
61fn foo(x: u32, y: u32) -> u32 {x + y}
62fn bar() { foo(3<|>, ); }
63"#,
64 expect![[r#"
65 fn foo(x: u32, y: u32) -> u32
66 (<x: u32>, y: u32)
67 "#]],
68 );
69 check(
70 r#"
71fn foo(x: u32, y: u32) -> u32 {x + y}
72fn bar() { foo(3,<|> ); }
73"#,
74 expect![[r#"
75 fn foo(x: u32, y: u32) -> u32
76 (x: u32, <y: u32>)
77 "#]],
78 );
79 check(
80 r#"
81fn foo(x: u32, y: u32) -> u32 {x + y}
82fn bar() { foo(3, <|>); }
83"#,
84 expect![[r#"
85 fn foo(x: u32, y: u32) -> u32
86 (x: u32, <y: u32>)
87 "#]],
88 );
89}
90
91#[test]
92fn test_fn_signature_two_args_empty() {
93 check(
94 r#"
95fn foo(x: u32, y: u32) -> u32 {x + y}
96fn bar() { foo(<|>); }
97"#,
98 expect![[r#"
99 fn foo(x: u32, y: u32) -> u32
100 (<x: u32>, y: u32)
101 "#]],
102 );
103}
104
105#[test]
106fn test_fn_signature_two_args_first_generics() {
107 check(
108 r#"
109fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
110 where T: Copy + Display, U: Debug
111{ x + y }
112
113fn bar() { foo(<|>3, ); }
114"#,
115 expect![[r#"
116 fn foo(x: i32, y: {unknown}) -> u32
117 (<x: i32>, y: {unknown})
118 "#]],
119 );
120}
121
122#[test]
123fn test_fn_signature_no_params() {
124 check(
125 r#"
126fn foo<T>() -> T where T: Copy + Display {}
127fn bar() { foo(<|>); }
128"#,
129 expect![[r#"
130 fn foo() -> {unknown}
131 ()
132 "#]],
133 );
134}
135
136#[test]
137fn test_fn_signature_for_impl() {
138 check(
139 r#"
140struct F;
141impl F { pub fn new() { } }
142fn bar() {
143 let _ : F = F::new(<|>);
144}
145"#,
146 expect![[r#"
147 fn new()
148 ()
149 "#]],
150 );
151}
152
153#[test]
154fn test_fn_signature_for_method_self() {
155 check(
156 r#"
157struct S;
158impl S { pub fn do_it(&self) {} }
159
160fn bar() {
161 let s: S = S;
162 s.do_it(<|>);
163}
164"#,
165 expect![[r#"
166 fn do_it(&self)
167 ()
168 "#]],
169 );
170}
171
172#[test]
173fn test_fn_signature_for_method_with_arg() {
174 check(
175 r#"
176struct S;
177impl S {
178 fn foo(&self, x: i32) {}
179}
180
181fn main() { S.foo(<|>); }
182"#,
183 expect![[r#"
184 fn foo(&self, x: i32)
185 (<x: i32>)
186 "#]],
187 );
188}
189
190#[test]
191fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
192 check(
193 r#"
194struct S;
195impl S {
196 fn foo(&self, x: i32) {}
197}
198
199fn main() { S::foo(<|>); }
200"#,
201 expect![[r#"
202 fn foo(self: &S, x: i32)
203 (<self: &S>, x: i32)
204 "#]],
205 );
206}
207
208#[test]
209fn test_fn_signature_with_docs_simple() {
210 check(
211 r#"
212/// test
213// non-doc-comment
214fn foo(j: u32) -> u32 {
215 j
216}
217
218fn bar() {
219 let _ = foo(<|>);
220}
221"#,
222 expect![[r#"
223 test
224 ------
225 fn foo(j: u32) -> u32
226 (<j: u32>)
227 "#]],
228 );
229}
230
231#[test]
232fn test_fn_signature_with_docs() {
233 check(
234 r#"
235/// Adds one to the number given.
236///
237/// # Examples
238///
239/// ```
240/// let five = 5;
241///
242/// assert_eq!(6, my_crate::add_one(5));
243/// ```
244pub fn add_one(x: i32) -> i32 {
245 x + 1
246}
247
248pub fn do() {
249 add_one(<|>
250}"#,
251 expect![[r##"
252 Adds one to the number given.
253
254 # Examples
255
256 ```
257 let five = 5;
258
259 assert_eq!(6, my_crate::add_one(5));
260 ```
261 ------
262 fn add_one(x: i32) -> i32
263 (<x: i32>)
264 "##]],
265 );
266}
267
268#[test]
269fn test_fn_signature_with_docs_impl() {
270 check(
271 r#"
272struct addr;
273impl addr {
274 /// Adds one to the number given.
275 ///
276 /// # Examples
277 ///
278 /// ```
279 /// let five = 5;
280 ///
281 /// assert_eq!(6, my_crate::add_one(5));
282 /// ```
283 pub fn add_one(x: i32) -> i32 {
284 x + 1
285 }
286}
287
288pub fn do_it() {
289 addr {};
290 addr::add_one(<|>);
291}
292"#,
293 expect![[r##"
294 Adds one to the number given.
295
296 # Examples
297
298 ```
299 let five = 5;
300
301 assert_eq!(6, my_crate::add_one(5));
302 ```
303 ------
304 fn add_one(x: i32) -> i32
305 (<x: i32>)
306 "##]],
307 );
308}
309
310#[test]
311fn test_fn_signature_with_docs_from_actix() {
312 check(
313 r#"
314struct WriteHandler<E>;
315
316impl<E> WriteHandler<E> {
317 /// Method is called when writer emits error.
318 ///
319 /// If this method returns `ErrorAction::Continue` writer processing
320 /// continues otherwise stream processing stops.
321 fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
322 Running::Stop
323 }
324
325 /// Method is called when writer finishes.
326 ///
327 /// By default this method stops actor's `Context`.
328 fn finished(&mut self, ctx: &mut Self::Context) {
329 ctx.stop()
330 }
331}
332
333pub fn foo(mut r: WriteHandler<()>) {
334 r.finished(<|>);
335}
336"#,
337 expect![[r#"
338 Method is called when writer finishes.
339
340 By default this method stops actor's `Context`.
341 ------
342 fn finished(&mut self, ctx: &mut {unknown})
343 (<ctx: &mut {unknown}>)
344 "#]],
345 );
346}
347
348#[test]
349fn call_info_bad_offset() {
350 mark::check!(call_info_bad_offset);
351 check(
352 r#"
353fn foo(x: u32, y: u32) -> u32 {x + y}
354fn bar() { foo <|> (3, ); }
355"#,
356 expect![[""]],
357 );
358}
359
360#[test]
361fn test_nested_method_in_lambda() {
362 check(
363 r#"
364struct Foo;
365impl Foo { fn bar(&self, _: u32) { } }
366
367fn bar(_: u32) { }
368
369fn main() {
370 let foo = Foo;
371 std::thread::spawn(move || foo.bar(<|>));
372}
373"#,
374 expect![[r#"
375 fn bar(&self, _: u32)
376 (<_: u32>)
377 "#]],
378 );
379}
380
381#[test]
382fn works_for_tuple_structs() {
383 check(
384 r#"
385/// A cool tuple struct
386struct S(u32, i32);
387fn main() {
388 let s = S(0, <|>);
389}
390"#,
391 expect![[r#"
392 A cool tuple struct
393 ------
394 struct S(u32, i32)
395 (u32, <i32>)
396 "#]],
397 );
398}
399
400#[test]
401fn generic_struct() {
402 check(
403 r#"
404struct S<T>(T);
405fn main() {
406 let s = S(<|>);
407}
408"#,
409 expect![[r#"
410 struct S({unknown})
411 (<{unknown}>)
412 "#]],
413 );
414}
415
416#[test]
417fn works_for_enum_variants() {
418 check(
419 r#"
420enum E {
421 /// A Variant
422 A(i32),
423 /// Another
424 B,
425 /// And C
426 C { a: i32, b: i32 }
427}
428
429fn main() {
430 let a = E::A(<|>);
431}
432"#,
433 expect![[r#"
434 A Variant
435 ------
436 enum E::A(i32)
437 (<i32>)
438 "#]],
439 );
440}
441
442#[test]
443fn cant_call_struct_record() {
444 check(
445 r#"
446struct S { x: u32, y: i32 }
447fn main() {
448 let s = S(<|>);
449}
450"#,
451 expect![[""]],
452 );
453}
454
455#[test]
456fn cant_call_enum_record() {
457 check(
458 r#"
459enum E {
460 /// A Variant
461 A(i32),
462 /// Another
463 B,
464 /// And C
465 C { a: i32, b: i32 }
466}
467
468fn main() {
469 let a = E::C(<|>);
470}
471"#,
472 expect![[""]],
473 );
474}
475
476#[test]
477fn fn_signature_for_call_in_macro() {
478 check(
479 r#"
480macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
481fn foo() { }
482id! {
483 fn bar() { foo(<|>); }
484}
485"#,
486 expect![[r#"
487 fn foo()
488 ()
489 "#]],
490 );
491}
492
493#[test]
494fn call_info_for_lambdas() {
495 check(
496 r#"
497struct S;
498fn foo(s: S) -> i32 { 92 }
499fn main() {
500 (|s| foo(s))(<|>)
501}
502 "#,
503 expect![[r#"
504 (S) -> i32
505 (<S>)
506 "#]],
507 )
508}
509
510#[test]
511fn call_info_for_fn_ptr() {
512 check(
513 r#"
514fn main(f: fn(i32, f64) -> char) {
515 f(0, <|>)
516}
517 "#,
518 expect![[r#"
519 (i32, f64) -> char
520 (i32, <f64>)
521 "#]],
522 )
523}