]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide/src/signature_help.rs
Rollup merge of #100228 - luqmana:suggestion-ice, r=estebank
[rust.git] / src / tools / rust-analyzer / crates / ide / src / signature_help.rs
1 //! This module provides primitives for showing type and function parameter information when editing
2 //! a call or use-site.
3
4 use std::collections::BTreeSet;
5
6 use either::Either;
7 use hir::{AssocItem, GenericParam, HasAttrs, HirDisplay, Semantics, Trait};
8 use ide_db::{active_parameter::callable_for_node, base_db::FilePosition};
9 use stdx::format_to;
10 use syntax::{
11     algo,
12     ast::{self, HasArgList},
13     match_ast, AstNode, Direction, SyntaxToken, TextRange, TextSize,
14 };
15
16 use crate::RootDatabase;
17
18 /// Contains information about an item signature as seen from a use site.
19 ///
20 /// This includes the "active parameter", which is the parameter whose value is currently being
21 /// edited.
22 #[derive(Debug)]
23 pub struct SignatureHelp {
24     pub doc: Option<String>,
25     pub signature: String,
26     pub active_parameter: Option<usize>,
27     parameters: Vec<TextRange>,
28 }
29
30 impl SignatureHelp {
31     pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ {
32         self.parameters.iter().map(move |&it| &self.signature[it])
33     }
34
35     pub fn parameter_ranges(&self) -> &[TextRange] {
36         &self.parameters
37     }
38
39     fn push_call_param(&mut self, param: &str) {
40         self.push_param('(', param);
41     }
42
43     fn push_generic_param(&mut self, param: &str) {
44         self.push_param('<', param);
45     }
46
47     fn push_param(&mut self, opening_delim: char, param: &str) {
48         if !self.signature.ends_with(opening_delim) {
49             self.signature.push_str(", ");
50         }
51         let start = TextSize::of(&self.signature);
52         self.signature.push_str(param);
53         let end = TextSize::of(&self.signature);
54         self.parameters.push(TextRange::new(start, end))
55     }
56 }
57
58 /// Computes parameter information for the given position.
59 pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Option<SignatureHelp> {
60     let sema = Semantics::new(db);
61     let file = sema.parse(position.file_id);
62     let file = file.syntax();
63     let token = file
64         .token_at_offset(position.offset)
65         .left_biased()
66         // if the cursor is sandwiched between two space tokens and the call is unclosed
67         // this prevents us from leaving the CallExpression
68         .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
69     let token = sema.descend_into_macros_single(token);
70
71     for node in token.parent_ancestors() {
72         match_ast! {
73             match node {
74                 ast::ArgList(arg_list) => {
75                     let cursor_outside = arg_list.r_paren_token().as_ref() == Some(&token);
76                     if cursor_outside {
77                         return None;
78                     }
79                     return signature_help_for_call(&sema, token);
80                 },
81                 ast::GenericArgList(garg_list) => {
82                     let cursor_outside = garg_list.r_angle_token().as_ref() == Some(&token);
83                     if cursor_outside {
84                         return None;
85                     }
86                     return signature_help_for_generics(&sema, token);
87                 },
88                 _ => (),
89             }
90         }
91     }
92
93     None
94 }
95
96 fn signature_help_for_call(
97     sema: &Semantics<'_, RootDatabase>,
98     token: SyntaxToken,
99 ) -> Option<SignatureHelp> {
100     // Find the calling expression and its NameRef
101     let mut node = token.parent()?;
102     let calling_node = loop {
103         if let Some(callable) = ast::CallableExpr::cast(node.clone()) {
104             if callable
105                 .arg_list()
106                 .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
107             {
108                 break callable;
109             }
110         }
111
112         // Stop at multi-line expressions, since the signature of the outer call is not very
113         // helpful inside them.
114         if let Some(expr) = ast::Expr::cast(node.clone()) {
115             if expr.syntax().text().contains_char('\n') {
116                 return None;
117             }
118         }
119
120         node = node.parent()?;
121     };
122
123     let (callable, active_parameter) = callable_for_node(sema, &calling_node, &token)?;
124
125     let mut res =
126         SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter };
127
128     let db = sema.db;
129     let mut fn_params = None;
130     match callable.kind() {
131         hir::CallableKind::Function(func) => {
132             res.doc = func.docs(db).map(|it| it.into());
133             format_to!(res.signature, "fn {}", func.name(db));
134             fn_params = Some(match callable.receiver_param(db) {
135                 Some(_self) => func.params_without_self(db),
136                 None => func.assoc_fn_params(db),
137             });
138         }
139         hir::CallableKind::TupleStruct(strukt) => {
140             res.doc = strukt.docs(db).map(|it| it.into());
141             format_to!(res.signature, "struct {}", strukt.name(db));
142         }
143         hir::CallableKind::TupleEnumVariant(variant) => {
144             res.doc = variant.docs(db).map(|it| it.into());
145             format_to!(
146                 res.signature,
147                 "enum {}::{}",
148                 variant.parent_enum(db).name(db),
149                 variant.name(db)
150             );
151         }
152         hir::CallableKind::Closure | hir::CallableKind::FnPtr => (),
153     }
154
155     res.signature.push('(');
156     {
157         if let Some(self_param) = callable.receiver_param(db) {
158             format_to!(res.signature, "{}", self_param)
159         }
160         let mut buf = String::new();
161         for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
162             buf.clear();
163             if let Some(pat) = pat {
164                 match pat {
165                     Either::Left(_self) => format_to!(buf, "self: "),
166                     Either::Right(pat) => format_to!(buf, "{}: ", pat),
167                 }
168             }
169             // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
170             // in the middle of entering call arguments.
171             // In that case, fall back to render definitions of the respective parameters.
172             // This is overly conservative: we do not substitute known type vars
173             // (see FIXME in tests::impl_trait) and falling back on any unknowns.
174             match (ty.contains_unknown(), fn_params.as_deref()) {
175                 (true, Some(fn_params)) => format_to!(buf, "{}", fn_params[idx].ty().display(db)),
176                 _ => format_to!(buf, "{}", ty.display(db)),
177             }
178             res.push_call_param(&buf);
179         }
180     }
181     res.signature.push(')');
182
183     let mut render = |ret_type: hir::Type| {
184         if !ret_type.is_unit() {
185             format_to!(res.signature, " -> {}", ret_type.display(db));
186         }
187     };
188     match callable.kind() {
189         hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => {
190             render(func.ret_type(db))
191         }
192         hir::CallableKind::Function(_) | hir::CallableKind::Closure | hir::CallableKind::FnPtr => {
193             render(callable.return_type())
194         }
195         hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
196     }
197     Some(res)
198 }
199
200 fn signature_help_for_generics(
201     sema: &Semantics<'_, RootDatabase>,
202     token: SyntaxToken,
203 ) -> Option<SignatureHelp> {
204     let parent = token.parent()?;
205     let arg_list = parent
206         .ancestors()
207         .filter_map(ast::GenericArgList::cast)
208         .find(|list| list.syntax().text_range().contains(token.text_range().start()))?;
209
210     let mut active_parameter = arg_list
211         .generic_args()
212         .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
213         .count();
214
215     let first_arg_is_non_lifetime = arg_list
216         .generic_args()
217         .next()
218         .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
219
220     let mut generics_def = if let Some(path) =
221         arg_list.syntax().ancestors().find_map(ast::Path::cast)
222     {
223         let res = sema.resolve_path(&path)?;
224         let generic_def: hir::GenericDef = match res {
225             hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(),
226             hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
227             hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
228             hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
229             hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(),
230             hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
231             | hir::PathResolution::Def(hir::ModuleDef::Const(_))
232             | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
233             | hir::PathResolution::Def(hir::ModuleDef::Module(_))
234             | hir::PathResolution::Def(hir::ModuleDef::Static(_)) => return None,
235             hir::PathResolution::BuiltinAttr(_)
236             | hir::PathResolution::ToolModule(_)
237             | hir::PathResolution::Local(_)
238             | hir::PathResolution::TypeParam(_)
239             | hir::PathResolution::ConstParam(_)
240             | hir::PathResolution::SelfType(_)
241             | hir::PathResolution::DeriveHelper(_) => return None,
242         };
243
244         generic_def
245     } else if let Some(method_call) = arg_list.syntax().parent().and_then(ast::MethodCallExpr::cast)
246     {
247         // recv.method::<$0>()
248         let method = sema.resolve_method_call(&method_call)?;
249         method.into()
250     } else {
251         return None;
252     };
253
254     let mut res = SignatureHelp {
255         doc: None,
256         signature: String::new(),
257         parameters: vec![],
258         active_parameter: None,
259     };
260
261     let db = sema.db;
262     match generics_def {
263         hir::GenericDef::Function(it) => {
264             res.doc = it.docs(db).map(|it| it.into());
265             format_to!(res.signature, "fn {}", it.name(db));
266         }
267         hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
268             res.doc = it.docs(db).map(|it| it.into());
269             format_to!(res.signature, "enum {}", it.name(db));
270         }
271         hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
272             res.doc = it.docs(db).map(|it| it.into());
273             format_to!(res.signature, "struct {}", it.name(db));
274         }
275         hir::GenericDef::Adt(hir::Adt::Union(it)) => {
276             res.doc = it.docs(db).map(|it| it.into());
277             format_to!(res.signature, "union {}", it.name(db));
278         }
279         hir::GenericDef::Trait(it) => {
280             res.doc = it.docs(db).map(|it| it.into());
281             format_to!(res.signature, "trait {}", it.name(db));
282         }
283         hir::GenericDef::TypeAlias(it) => {
284             res.doc = it.docs(db).map(|it| it.into());
285             format_to!(res.signature, "type {}", it.name(db));
286         }
287         hir::GenericDef::Variant(it) => {
288             // In paths, generics of an enum can be specified *after* one of its variants.
289             // eg. `None::<u8>`
290             // We'll use the signature of the enum, but include the docs of the variant.
291             res.doc = it.docs(db).map(|it| it.into());
292             let it = it.parent_enum(db);
293             format_to!(res.signature, "enum {}", it.name(db));
294             generics_def = it.into();
295         }
296         // These don't have generic args that can be specified
297         hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
298     }
299
300     let params = generics_def.params(sema.db);
301     let num_lifetime_params =
302         params.iter().take_while(|param| matches!(param, GenericParam::LifetimeParam(_))).count();
303     if first_arg_is_non_lifetime {
304         // Lifetime parameters were omitted.
305         active_parameter += num_lifetime_params;
306     }
307     res.active_parameter = Some(active_parameter);
308
309     res.signature.push('<');
310     let mut buf = String::new();
311     for param in params {
312         if let hir::GenericParam::TypeParam(ty) = param {
313             if ty.is_implicit(db) {
314                 continue;
315             }
316         }
317
318         buf.clear();
319         format_to!(buf, "{}", param.display(db));
320         res.push_generic_param(&buf);
321     }
322     if let hir::GenericDef::Trait(tr) = generics_def {
323         add_assoc_type_bindings(db, &mut res, tr, arg_list);
324     }
325     res.signature.push('>');
326
327     Some(res)
328 }
329
330 fn add_assoc_type_bindings(
331     db: &RootDatabase,
332     res: &mut SignatureHelp,
333     tr: Trait,
334     args: ast::GenericArgList,
335 ) {
336     if args.syntax().ancestors().find_map(ast::TypeBound::cast).is_none() {
337         // Assoc type bindings are only valid in type bound position.
338         return;
339     }
340
341     let present_bindings = args
342         .generic_args()
343         .filter_map(|arg| match arg {
344             ast::GenericArg::AssocTypeArg(arg) => arg.name_ref().map(|n| n.to_string()),
345             _ => None,
346         })
347         .collect::<BTreeSet<_>>();
348
349     let mut buf = String::new();
350     for binding in &present_bindings {
351         buf.clear();
352         format_to!(buf, "{} = …", binding);
353         res.push_generic_param(&buf);
354     }
355
356     for item in tr.items_with_supertraits(db) {
357         if let AssocItem::TypeAlias(ty) = item {
358             let name = ty.name(db).to_smol_str();
359             if !present_bindings.contains(&*name) {
360                 buf.clear();
361                 format_to!(buf, "{} = …", name);
362                 res.push_generic_param(&buf);
363             }
364         }
365     }
366 }
367
368 #[cfg(test)]
369 mod tests {
370     use std::iter;
371
372     use expect_test::{expect, Expect};
373     use ide_db::base_db::{fixture::ChangeFixture, FilePosition};
374     use stdx::format_to;
375
376     use crate::RootDatabase;
377
378     /// Creates analysis from a multi-file fixture, returns positions marked with $0.
379     pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
380         let change_fixture = ChangeFixture::parse(ra_fixture);
381         let mut database = RootDatabase::default();
382         database.apply_change(change_fixture.change);
383         let (file_id, range_or_offset) =
384             change_fixture.file_position.expect("expected a marker ($0)");
385         let offset = range_or_offset.expect_offset();
386         (database, FilePosition { file_id, offset })
387     }
388
389     fn check(ra_fixture: &str, expect: Expect) {
390         // Implicitly add `Sized` to avoid noisy `T: ?Sized` in the results.
391         let fixture = format!(
392             r#"
393 #[lang = "sized"] trait Sized {{}}
394 {ra_fixture}
395             "#
396         );
397         let (db, position) = position(&fixture);
398         let sig_help = crate::signature_help::signature_help(&db, position);
399         let actual = match sig_help {
400             Some(sig_help) => {
401                 let mut rendered = String::new();
402                 if let Some(docs) = &sig_help.doc {
403                     format_to!(rendered, "{}\n------\n", docs.as_str());
404                 }
405                 format_to!(rendered, "{}\n", sig_help.signature);
406                 let mut offset = 0;
407                 for (i, range) in sig_help.parameter_ranges().iter().enumerate() {
408                     let is_active = sig_help.active_parameter == Some(i);
409
410                     let start = u32::from(range.start());
411                     let gap = start.checked_sub(offset).unwrap_or_else(|| {
412                         panic!("parameter ranges out of order: {:?}", sig_help.parameter_ranges())
413                     });
414                     rendered.extend(iter::repeat(' ').take(gap as usize));
415                     let param_text = &sig_help.signature[*range];
416                     let width = param_text.chars().count(); // …
417                     let marker = if is_active { '^' } else { '-' };
418                     rendered.extend(iter::repeat(marker).take(width));
419                     offset += gap + u32::from(range.len());
420                 }
421                 if !sig_help.parameter_ranges().is_empty() {
422                     format_to!(rendered, "\n");
423                 }
424                 rendered
425             }
426             None => String::new(),
427         };
428         expect.assert_eq(&actual);
429     }
430
431     #[test]
432     fn test_fn_signature_two_args() {
433         check(
434             r#"
435 fn foo(x: u32, y: u32) -> u32 {x + y}
436 fn bar() { foo($03, ); }
437 "#,
438             expect![[r#"
439                 fn foo(x: u32, y: u32) -> u32
440                        ^^^^^^  ------
441             "#]],
442         );
443         check(
444             r#"
445 fn foo(x: u32, y: u32) -> u32 {x + y}
446 fn bar() { foo(3$0, ); }
447 "#,
448             expect![[r#"
449                 fn foo(x: u32, y: u32) -> u32
450                        ^^^^^^  ------
451             "#]],
452         );
453         check(
454             r#"
455 fn foo(x: u32, y: u32) -> u32 {x + y}
456 fn bar() { foo(3,$0 ); }
457 "#,
458             expect![[r#"
459                 fn foo(x: u32, y: u32) -> u32
460                        ------  ^^^^^^
461             "#]],
462         );
463         check(
464             r#"
465 fn foo(x: u32, y: u32) -> u32 {x + y}
466 fn bar() { foo(3, $0); }
467 "#,
468             expect![[r#"
469                 fn foo(x: u32, y: u32) -> u32
470                        ------  ^^^^^^
471             "#]],
472         );
473     }
474
475     #[test]
476     fn test_fn_signature_two_args_empty() {
477         check(
478             r#"
479 fn foo(x: u32, y: u32) -> u32 {x + y}
480 fn bar() { foo($0); }
481 "#,
482             expect![[r#"
483                 fn foo(x: u32, y: u32) -> u32
484                        ^^^^^^  ------
485             "#]],
486         );
487     }
488
489     #[test]
490     fn test_fn_signature_two_args_first_generics() {
491         check(
492             r#"
493 fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
494     where T: Copy + Display, U: Debug
495 { x + y }
496
497 fn bar() { foo($03, ); }
498 "#,
499             expect![[r#"
500                 fn foo(x: i32, y: U) -> u32
501                        ^^^^^^  ----
502             "#]],
503         );
504     }
505
506     #[test]
507     fn test_fn_signature_no_params() {
508         check(
509             r#"
510 fn foo<T>() -> T where T: Copy + Display {}
511 fn bar() { foo($0); }
512 "#,
513             expect![[r#"
514                 fn foo() -> T
515             "#]],
516         );
517     }
518
519     #[test]
520     fn test_fn_signature_for_impl() {
521         check(
522             r#"
523 struct F;
524 impl F { pub fn new() { } }
525 fn bar() {
526     let _ : F = F::new($0);
527 }
528 "#,
529             expect![[r#"
530                 fn new()
531             "#]],
532         );
533     }
534
535     #[test]
536     fn test_fn_signature_for_method_self() {
537         check(
538             r#"
539 struct S;
540 impl S { pub fn do_it(&self) {} }
541
542 fn bar() {
543     let s: S = S;
544     s.do_it($0);
545 }
546 "#,
547             expect![[r#"
548                 fn do_it(&self)
549             "#]],
550         );
551     }
552
553     #[test]
554     fn test_fn_signature_for_method_with_arg() {
555         check(
556             r#"
557 struct S;
558 impl S {
559     fn foo(&self, x: i32) {}
560 }
561
562 fn main() { S.foo($0); }
563 "#,
564             expect![[r#"
565                 fn foo(&self, x: i32)
566                               ^^^^^^
567             "#]],
568         );
569     }
570
571     #[test]
572     fn test_fn_signature_for_generic_method() {
573         check(
574             r#"
575 struct S<T>(T);
576 impl<T> S<T> {
577     fn foo(&self, x: T) {}
578 }
579
580 fn main() { S(1u32).foo($0); }
581 "#,
582             expect![[r#"
583                 fn foo(&self, x: u32)
584                               ^^^^^^
585             "#]],
586         );
587     }
588
589     #[test]
590     fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
591         check(
592             r#"
593 struct S;
594 impl S {
595     fn foo(&self, x: i32) {}
596 }
597
598 fn main() { S::foo($0); }
599 "#,
600             expect![[r#"
601                 fn foo(self: &S, x: i32)
602                        ^^^^^^^^  ------
603             "#]],
604         );
605     }
606
607     #[test]
608     fn test_fn_signature_with_docs_simple() {
609         check(
610             r#"
611 /// test
612 // non-doc-comment
613 fn foo(j: u32) -> u32 {
614     j
615 }
616
617 fn bar() {
618     let _ = foo($0);
619 }
620 "#,
621             expect![[r#"
622                 test
623                 ------
624                 fn foo(j: u32) -> u32
625                        ^^^^^^
626             "#]],
627         );
628     }
629
630     #[test]
631     fn test_fn_signature_with_docs() {
632         check(
633             r#"
634 /// Adds one to the number given.
635 ///
636 /// # Examples
637 ///
638 /// ```
639 /// let five = 5;
640 ///
641 /// assert_eq!(6, my_crate::add_one(5));
642 /// ```
643 pub fn add_one(x: i32) -> i32 {
644     x + 1
645 }
646
647 pub fn do() {
648     add_one($0
649 }"#,
650             expect![[r##"
651                 Adds one to the number given.
652
653                 # Examples
654
655                 ```
656                 let five = 5;
657
658                 assert_eq!(6, my_crate::add_one(5));
659                 ```
660                 ------
661                 fn add_one(x: i32) -> i32
662                            ^^^^^^
663             "##]],
664         );
665     }
666
667     #[test]
668     fn test_fn_signature_with_docs_impl() {
669         check(
670             r#"
671 struct addr;
672 impl addr {
673     /// Adds one to the number given.
674     ///
675     /// # Examples
676     ///
677     /// ```
678     /// let five = 5;
679     ///
680     /// assert_eq!(6, my_crate::add_one(5));
681     /// ```
682     pub fn add_one(x: i32) -> i32 {
683         x + 1
684     }
685 }
686
687 pub fn do_it() {
688     addr {};
689     addr::add_one($0);
690 }
691 "#,
692             expect![[r##"
693                 Adds one to the number given.
694
695                 # Examples
696
697                 ```
698                 let five = 5;
699
700                 assert_eq!(6, my_crate::add_one(5));
701                 ```
702                 ------
703                 fn add_one(x: i32) -> i32
704                            ^^^^^^
705             "##]],
706         );
707     }
708
709     #[test]
710     fn test_fn_signature_with_docs_from_actix() {
711         check(
712             r#"
713 trait Actor {
714     /// Actor execution context type
715     type Context;
716 }
717 trait WriteHandler<E>
718 where
719     Self: Actor
720 {
721     /// Method is called when writer finishes.
722     ///
723     /// By default this method stops actor's `Context`.
724     fn finished(&mut self, ctx: &mut Self::Context) {}
725 }
726
727 fn foo(mut r: impl WriteHandler<()>) {
728     r.finished($0);
729 }
730 "#,
731             expect![[r#"
732                 Method is called when writer finishes.
733
734                 By default this method stops actor's `Context`.
735                 ------
736                 fn finished(&mut self, ctx: &mut <impl WriteHandler<()> as Actor>::Context)
737                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
738             "#]],
739         );
740     }
741
742     #[test]
743     fn call_info_bad_offset() {
744         check(
745             r#"
746 fn foo(x: u32, y: u32) -> u32 {x + y}
747 fn bar() { foo $0 (3, ); }
748 "#,
749             expect![[""]],
750         );
751     }
752
753     #[test]
754     fn outside_of_arg_list() {
755         check(
756             r#"
757 fn foo(a: u8) {}
758 fn f() {
759     foo(123)$0
760 }
761 "#,
762             expect![[]],
763         );
764         check(
765             r#"
766 fn foo<T>(a: u8) {}
767 fn f() {
768     foo::<u32>$0()
769 }
770 "#,
771             expect![[]],
772         );
773     }
774
775     #[test]
776     fn test_nested_method_in_lambda() {
777         check(
778             r#"
779 struct Foo;
780 impl Foo { fn bar(&self, _: u32) { } }
781
782 fn bar(_: u32) { }
783
784 fn main() {
785     let foo = Foo;
786     std::thread::spawn(move || foo.bar($0));
787 }
788 "#,
789             expect![[r#"
790                 fn bar(&self, _: u32)
791                               ^^^^^^
792             "#]],
793         );
794     }
795
796     #[test]
797     fn works_for_tuple_structs() {
798         check(
799             r#"
800 /// A cool tuple struct
801 struct S(u32, i32);
802 fn main() {
803     let s = S(0, $0);
804 }
805 "#,
806             expect![[r#"
807                 A cool tuple struct
808                 ------
809                 struct S(u32, i32)
810                          ---  ^^^
811             "#]],
812         );
813     }
814
815     #[test]
816     fn generic_struct() {
817         check(
818             r#"
819 struct S<T>(T);
820 fn main() {
821     let s = S($0);
822 }
823 "#,
824             expect![[r#"
825                 struct S({unknown})
826                          ^^^^^^^^^
827             "#]],
828         );
829     }
830
831     #[test]
832     fn works_for_enum_variants() {
833         check(
834             r#"
835 enum E {
836     /// A Variant
837     A(i32),
838     /// Another
839     B,
840     /// And C
841     C { a: i32, b: i32 }
842 }
843
844 fn main() {
845     let a = E::A($0);
846 }
847 "#,
848             expect![[r#"
849                 A Variant
850                 ------
851                 enum E::A(i32)
852                           ^^^
853             "#]],
854         );
855     }
856
857     #[test]
858     fn cant_call_struct_record() {
859         check(
860             r#"
861 struct S { x: u32, y: i32 }
862 fn main() {
863     let s = S($0);
864 }
865 "#,
866             expect![[""]],
867         );
868     }
869
870     #[test]
871     fn cant_call_enum_record() {
872         check(
873             r#"
874 enum E {
875     /// A Variant
876     A(i32),
877     /// Another
878     B,
879     /// And C
880     C { a: i32, b: i32 }
881 }
882
883 fn main() {
884     let a = E::C($0);
885 }
886 "#,
887             expect![[""]],
888         );
889     }
890
891     #[test]
892     fn fn_signature_for_call_in_macro() {
893         check(
894             r#"
895 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
896 fn foo() { }
897 id! {
898     fn bar() { foo($0); }
899 }
900 "#,
901             expect![[r#"
902                 fn foo()
903             "#]],
904         );
905     }
906
907     #[test]
908     fn call_info_for_lambdas() {
909         check(
910             r#"
911 struct S;
912 fn foo(s: S) -> i32 { 92 }
913 fn main() {
914     (|s| foo(s))($0)
915 }
916         "#,
917             expect![[r#"
918                 (s: S) -> i32
919                  ^^^^
920             "#]],
921         )
922     }
923
924     #[test]
925     fn call_info_for_fn_ptr() {
926         check(
927             r#"
928 fn main(f: fn(i32, f64) -> char) {
929     f(0, $0)
930 }
931         "#,
932             expect![[r#"
933                 (i32, f64) -> char
934                  ---  ^^^
935             "#]],
936         )
937     }
938
939     #[test]
940     fn call_info_for_unclosed_call() {
941         check(
942             r#"
943 fn foo(foo: u32, bar: u32) {}
944 fn main() {
945     foo($0
946 }"#,
947             expect![[r#"
948                 fn foo(foo: u32, bar: u32)
949                        ^^^^^^^^  --------
950             "#]],
951         );
952         // check with surrounding space
953         check(
954             r#"
955 fn foo(foo: u32, bar: u32) {}
956 fn main() {
957     foo( $0
958 }"#,
959             expect![[r#"
960                 fn foo(foo: u32, bar: u32)
961                        ^^^^^^^^  --------
962             "#]],
963         )
964     }
965
966     #[test]
967     fn test_multiline_argument() {
968         check(
969             r#"
970 fn callee(a: u8, b: u8) {}
971 fn main() {
972     callee(match 0 {
973         0 => 1,$0
974     })
975 }"#,
976             expect![[r#""#]],
977         );
978         check(
979             r#"
980 fn callee(a: u8, b: u8) {}
981 fn main() {
982     callee(match 0 {
983         0 => 1,
984     },$0)
985 }"#,
986             expect![[r#"
987                 fn callee(a: u8, b: u8)
988                           -----  ^^^^^
989             "#]],
990         );
991         check(
992             r#"
993 fn callee(a: u8, b: u8) {}
994 fn main() {
995     callee($0match 0 {
996         0 => 1,
997     })
998 }"#,
999             expect![[r#"
1000                 fn callee(a: u8, b: u8)
1001                           ^^^^^  -----
1002             "#]],
1003         );
1004     }
1005
1006     #[test]
1007     fn test_generics_simple() {
1008         check(
1009             r#"
1010 /// Option docs.
1011 enum Option<T> {
1012     Some(T),
1013     None,
1014 }
1015
1016 fn f() {
1017     let opt: Option<$0
1018 }
1019         "#,
1020             expect![[r#"
1021                 Option docs.
1022                 ------
1023                 enum Option<T>
1024                             ^
1025             "#]],
1026         );
1027     }
1028
1029     #[test]
1030     fn test_generics_on_variant() {
1031         check(
1032             r#"
1033 /// Option docs.
1034 enum Option<T> {
1035     /// Some docs.
1036     Some(T),
1037     /// None docs.
1038     None,
1039 }
1040
1041 use Option::*;
1042
1043 fn f() {
1044     None::<$0
1045 }
1046         "#,
1047             expect![[r#"
1048                 None docs.
1049                 ------
1050                 enum Option<T>
1051                             ^
1052             "#]],
1053         );
1054     }
1055
1056     #[test]
1057     fn test_lots_of_generics() {
1058         check(
1059             r#"
1060 trait Tr<T> {}
1061
1062 struct S<T>(T);
1063
1064 impl<T> S<T> {
1065     fn f<G, H>(g: G, h: impl Tr<G>) where G: Tr<()> {}
1066 }
1067
1068 fn f() {
1069     S::<u8>::f::<(), $0
1070 }
1071         "#,
1072             expect![[r#"
1073                 fn f<G: Tr<()>, H>
1074                      ---------  ^
1075             "#]],
1076         );
1077     }
1078
1079     #[test]
1080     fn test_generics_in_trait_ufcs() {
1081         check(
1082             r#"
1083 trait Tr {
1084     fn f<T: Tr, U>() {}
1085 }
1086
1087 struct S;
1088
1089 impl Tr for S {}
1090
1091 fn f() {
1092     <S as Tr>::f::<$0
1093 }
1094         "#,
1095             expect![[r#"
1096                 fn f<T: Tr, U>
1097                      ^^^^^  -
1098             "#]],
1099         );
1100     }
1101
1102     #[test]
1103     fn test_generics_in_method_call() {
1104         check(
1105             r#"
1106 struct S;
1107
1108 impl S {
1109     fn f<T>(&self) {}
1110 }
1111
1112 fn f() {
1113     S.f::<$0
1114 }
1115         "#,
1116             expect![[r#"
1117                 fn f<T>
1118                      ^
1119             "#]],
1120         );
1121     }
1122
1123     #[test]
1124     fn test_generic_param_in_method_call() {
1125         check(
1126             r#"
1127 struct Foo;
1128 impl Foo {
1129     fn test<V>(&mut self, val: V) {}
1130 }
1131 fn sup() {
1132     Foo.test($0)
1133 }
1134 "#,
1135             expect![[r#"
1136                 fn test(&mut self, val: V)
1137                                    ^^^^^^
1138             "#]],
1139         );
1140     }
1141
1142     #[test]
1143     fn test_generic_kinds() {
1144         check(
1145             r#"
1146 fn callee<'a, const A: u8, T, const C: u8>() {}
1147
1148 fn f() {
1149     callee::<'static, $0
1150 }
1151         "#,
1152             expect![[r#"
1153                 fn callee<'a, const A: u8, T, const C: u8>
1154                           --  ^^^^^^^^^^^  -  -----------
1155             "#]],
1156         );
1157         check(
1158             r#"
1159 fn callee<'a, const A: u8, T, const C: u8>() {}
1160
1161 fn f() {
1162     callee::<NON_LIFETIME$0
1163 }
1164         "#,
1165             expect![[r#"
1166                 fn callee<'a, const A: u8, T, const C: u8>
1167                           --  ^^^^^^^^^^^  -  -----------
1168             "#]],
1169         );
1170     }
1171
1172     #[test]
1173     fn test_trait_assoc_types() {
1174         check(
1175             r#"
1176 trait Trait<'a, T> {
1177     type Assoc;
1178 }
1179 fn f() -> impl Trait<(), $0
1180             "#,
1181             expect![[r#"
1182                 trait Trait<'a, T, Assoc = …>
1183                             --  -  ^^^^^^^^^
1184             "#]],
1185         );
1186         check(
1187             r#"
1188 trait Iterator {
1189     type Item;
1190 }
1191 fn f() -> impl Iterator<$0
1192             "#,
1193             expect![[r#"
1194                 trait Iterator<Item = …>
1195                                ^^^^^^^^
1196             "#]],
1197         );
1198         check(
1199             r#"
1200 trait Iterator {
1201     type Item;
1202 }
1203 fn f() -> impl Iterator<Item = $0
1204             "#,
1205             expect![[r#"
1206                 trait Iterator<Item = …>
1207                                ^^^^^^^^
1208             "#]],
1209         );
1210         check(
1211             r#"
1212 trait Tr {
1213     type A;
1214     type B;
1215 }
1216 fn f() -> impl Tr<$0
1217             "#,
1218             expect![[r#"
1219                 trait Tr<A = …, B = …>
1220                          ^^^^^  -----
1221             "#]],
1222         );
1223         check(
1224             r#"
1225 trait Tr {
1226     type A;
1227     type B;
1228 }
1229 fn f() -> impl Tr<B$0
1230             "#,
1231             expect![[r#"
1232                 trait Tr<A = …, B = …>
1233                          ^^^^^  -----
1234             "#]],
1235         );
1236         check(
1237             r#"
1238 trait Tr {
1239     type A;
1240     type B;
1241 }
1242 fn f() -> impl Tr<B = $0
1243             "#,
1244             expect![[r#"
1245                 trait Tr<B = …, A = …>
1246                          ^^^^^  -----
1247             "#]],
1248         );
1249         check(
1250             r#"
1251 trait Tr {
1252     type A;
1253     type B;
1254 }
1255 fn f() -> impl Tr<B = (), $0
1256             "#,
1257             expect![[r#"
1258                 trait Tr<B = …, A = …>
1259                          -----  ^^^^^
1260             "#]],
1261         );
1262     }
1263
1264     #[test]
1265     fn test_supertrait_assoc() {
1266         check(
1267             r#"
1268 trait Super {
1269     type SuperTy;
1270 }
1271 trait Sub: Super + Super {
1272     type SubTy;
1273 }
1274 fn f() -> impl Sub<$0
1275             "#,
1276             expect![[r#"
1277                 trait Sub<SubTy = …, SuperTy = …>
1278                           ^^^^^^^^^  -----------
1279             "#]],
1280         );
1281     }
1282
1283     #[test]
1284     fn no_assoc_types_outside_type_bounds() {
1285         check(
1286             r#"
1287 trait Tr<T> {
1288     type Assoc;
1289 }
1290
1291 impl Tr<$0
1292         "#,
1293             expect![[r#"
1294             trait Tr<T>
1295                      ^
1296         "#]],
1297         );
1298     }
1299
1300     #[test]
1301     fn impl_trait() {
1302         // FIXME: Substitute type vars in impl trait (`U` -> `i8`)
1303         check(
1304             r#"
1305 trait Trait<T> {}
1306 struct Wrap<T>(T);
1307 fn foo<U>(x: Wrap<impl Trait<U>>) {}
1308 fn f() {
1309     foo::<i8>($0)
1310 }
1311 "#,
1312             expect![[r#"
1313                 fn foo(x: Wrap<impl Trait<U>>)
1314                        ^^^^^^^^^^^^^^^^^^^^^^
1315             "#]],
1316         );
1317     }
1318
1319     #[test]
1320     fn fully_qualified_syntax() {
1321         check(
1322             r#"
1323 fn f() {
1324     trait A { fn foo(&self, other: Self); }
1325     A::foo(&self$0, other);
1326 }
1327 "#,
1328             expect![[r#"
1329                 fn foo(self: &Self, other: Self)
1330                        ^^^^^^^^^^^  -----------
1331             "#]],
1332         );
1333     }
1334 }