1 //! This module provides primitives for showing type and function parameter information when editing
2 //! a call or use-site.
4 use std
::collections
::BTreeSet
;
8 AssocItem
, DescendPreference
, GenericParam
, HirDisplay
, ModuleDef
, PathResolution
, Semantics
,
12 active_parameter
::{callable_for_node, generic_def_for_node}
,
13 base_db
::FilePosition
,
14 documentation
::{Documentation, HasDocs}
,
20 ast
::{self, AstChildren, HasArgList}
,
21 match_ast
, AstNode
, Direction
, NodeOrToken
, SyntaxElementChildren
, SyntaxNode
, SyntaxToken
,
22 TextRange
, TextSize
, T
,
25 use crate::RootDatabase
;
27 /// Contains information about an item signature as seen from a use site.
29 /// This includes the "active parameter", which is the parameter whose value is currently being
32 pub struct SignatureHelp
{
33 pub doc
: Option
<Documentation
>,
34 pub signature
: String
,
35 pub active_parameter
: Option
<usize>,
36 parameters
: Vec
<TextRange
>,
40 pub fn parameter_labels(&self) -> impl Iterator
<Item
= &str> + '_
{
41 self.parameters
.iter().map(move |&it
| &self.signature
[it
])
44 pub fn parameter_ranges(&self) -> &[TextRange
] {
48 fn push_call_param(&mut self, param
: &str) {
49 self.push_param("(", param
);
52 fn push_generic_param(&mut self, param
: &str) {
53 self.push_param("<", param
);
56 fn push_record_field(&mut self, param
: &str) {
57 self.push_param("{ ", param
);
60 fn push_param(&mut self, opening_delim
: &str, param
: &str) {
61 if !self.signature
.ends_with(opening_delim
) {
62 self.signature
.push_str(", ");
64 let start
= TextSize
::of(&self.signature
);
65 self.signature
.push_str(param
);
66 let end
= TextSize
::of(&self.signature
);
67 self.parameters
.push(TextRange
::new(start
, end
))
71 /// Computes parameter information for the given position.
72 pub(crate) fn signature_help(
74 FilePosition { file_id, offset }
: FilePosition
,
75 ) -> Option
<SignatureHelp
> {
76 let sema
= Semantics
::new(db
);
77 let file
= sema
.parse(file_id
);
78 let file
= file
.syntax();
80 .token_at_offset(offset
)
82 // if the cursor is sandwiched between two space tokens and the call is unclosed
83 // this prevents us from leaving the CallExpression
84 .and_then(|tok
| algo
::skip_trivia_token(tok
, Direction
::Prev
))?
;
85 let token
= sema
.descend_into_macros_single(DescendPreference
::None
, token
);
87 for node
in token
.parent_ancestors() {
90 ast
::ArgList(arg_list
) => {
91 let cursor_outside
= arg_list
.r_paren_token().as_ref() == Some(&token
);
95 return signature_help_for_call(&sema
, arg_list
, token
);
97 ast
::GenericArgList(garg_list
) => {
98 let cursor_outside
= garg_list
.r_angle_token().as_ref() == Some(&token
);
102 return signature_help_for_generics(&sema
, garg_list
, token
);
104 ast
::RecordExpr(record
) => {
105 let cursor_outside
= record
.record_expr_field_list().and_then(|list
| list
.r_curly_token()).as_ref() == Some(&token
);
109 return signature_help_for_record_lit(&sema
, record
, token
);
111 ast
::RecordPat(record
) => {
112 let cursor_outside
= record
.record_pat_field_list().and_then(|list
| list
.r_curly_token()).as_ref() == Some(&token
);
116 return signature_help_for_record_pat(&sema
, record
, token
);
118 ast
::TupleStructPat(tuple_pat
) => {
119 let cursor_outside
= tuple_pat
.r_paren_token().as_ref() == Some(&token
);
123 return signature_help_for_tuple_struct_pat(&sema
, tuple_pat
, token
);
125 ast
::TuplePat(tuple_pat
) => {
126 let cursor_outside
= tuple_pat
.r_paren_token().as_ref() == Some(&token
);
130 return signature_help_for_tuple_pat(&sema
, tuple_pat
, token
);
132 ast
::TupleExpr(tuple_expr
) => {
133 let cursor_outside
= tuple_expr
.r_paren_token().as_ref() == Some(&token
);
137 return signature_help_for_tuple_expr(&sema
, tuple_expr
, token
);
143 // Stop at multi-line expressions, since the signature of the outer call is not very
144 // helpful inside them.
145 if let Some(expr
) = ast
::Expr
::cast(node
.clone()) {
146 if !matches
!(expr
, ast
::Expr
::RecordExpr(..))
147 && expr
.syntax().text().contains_char('
\n'
)
157 fn signature_help_for_call(
158 sema
: &Semantics
<'_
, RootDatabase
>,
159 arg_list
: ast
::ArgList
,
161 ) -> Option
<SignatureHelp
> {
162 // Find the calling expression and its NameRef
163 let mut nodes
= arg_list
.syntax().ancestors().skip(1);
164 let calling_node
= loop {
165 if let Some(callable
) = ast
::CallableExpr
::cast(nodes
.next()?
) {
166 let inside_callable
= callable
168 .map_or(false, |it
| it
.syntax().text_range().contains(token
.text_range().start()));
175 let (callable
, active_parameter
) = callable_for_node(sema
, &calling_node
, &token
)?
;
178 SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter }
;
181 let mut fn_params
= None
;
182 match callable
.kind() {
183 hir
::CallableKind
::Function(func
) => {
184 res
.doc
= func
.docs(db
);
185 format_to
!(res
.signature
, "fn {}", func
.name(db
).display(db
));
186 fn_params
= Some(match callable
.receiver_param(db
) {
187 Some(_self
) => func
.params_without_self(db
),
188 None
=> func
.assoc_fn_params(db
),
191 hir
::CallableKind
::TupleStruct(strukt
) => {
192 res
.doc
= strukt
.docs(db
);
193 format_to
!(res
.signature
, "struct {}", strukt
.name(db
).display(db
));
195 hir
::CallableKind
::TupleEnumVariant(variant
) => {
196 res
.doc
= variant
.docs(db
);
200 variant
.parent_enum(db
).name(db
).display(db
),
201 variant
.name(db
).display(db
)
204 hir
::CallableKind
::Closure
| hir
::CallableKind
::FnPtr
| hir
::CallableKind
::Other
=> (),
207 res
.signature
.push('
('
);
209 if let Some((self_param
, _
)) = callable
.receiver_param(db
) {
210 format_to
!(res
.signature
, "{}", self_param
.display(db
))
212 let mut buf
= String
::new();
213 for (idx
, (pat
, ty
)) in callable
.params(db
).into_iter().enumerate() {
215 if let Some(pat
) = pat
{
217 Either
::Left(_self
) => format_to
!(buf
, "self: "),
218 Either
::Right(pat
) => format_to
!(buf
, "{}: ", pat
),
221 // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
222 // in the middle of entering call arguments.
223 // In that case, fall back to render definitions of the respective parameters.
224 // This is overly conservative: we do not substitute known type vars
225 // (see FIXME in tests::impl_trait) and falling back on any unknowns.
226 match (ty
.contains_unknown(), fn_params
.as_deref()) {
227 (true, Some(fn_params
)) => format_to
!(buf
, "{}", fn_params
[idx
].ty().display(db
)),
228 _
=> format_to
!(buf
, "{}", ty
.display(db
)),
230 res
.push_call_param(&buf
);
233 res
.signature
.push('
)'
);
235 let mut render
= |ret_type
: hir
::Type
| {
236 if !ret_type
.is_unit() {
237 format_to
!(res
.signature
, " -> {}", ret_type
.display(db
));
240 match callable
.kind() {
241 hir
::CallableKind
::Function(func
) if callable
.return_type().contains_unknown() => {
242 render(func
.ret_type(db
))
244 hir
::CallableKind
::Function(_
)
245 | hir
::CallableKind
::Closure
246 | hir
::CallableKind
::FnPtr
247 | hir
::CallableKind
::Other
=> render(callable
.return_type()),
248 hir
::CallableKind
::TupleStruct(_
) | hir
::CallableKind
::TupleEnumVariant(_
) => {}
253 fn signature_help_for_generics(
254 sema
: &Semantics
<'_
, RootDatabase
>,
255 arg_list
: ast
::GenericArgList
,
257 ) -> Option
<SignatureHelp
> {
258 let (mut generics_def
, mut active_parameter
, first_arg_is_non_lifetime
) =
259 generic_def_for_node(sema
, &arg_list
, &token
)?
;
260 let mut res
= SignatureHelp
{
262 signature
: String
::new(),
264 active_parameter
: None
,
269 hir
::GenericDef
::Function(it
) => {
270 res
.doc
= it
.docs(db
);
271 format_to
!(res
.signature
, "fn {}", it
.name(db
).display(db
));
273 hir
::GenericDef
::Adt(hir
::Adt
::Enum(it
)) => {
274 res
.doc
= it
.docs(db
);
275 format_to
!(res
.signature
, "enum {}", it
.name(db
).display(db
));
277 hir
::GenericDef
::Adt(hir
::Adt
::Struct(it
)) => {
278 res
.doc
= it
.docs(db
);
279 format_to
!(res
.signature
, "struct {}", it
.name(db
).display(db
));
281 hir
::GenericDef
::Adt(hir
::Adt
::Union(it
)) => {
282 res
.doc
= it
.docs(db
);
283 format_to
!(res
.signature
, "union {}", it
.name(db
).display(db
));
285 hir
::GenericDef
::Trait(it
) => {
286 res
.doc
= it
.docs(db
);
287 format_to
!(res
.signature
, "trait {}", it
.name(db
).display(db
));
289 hir
::GenericDef
::TraitAlias(it
) => {
290 res
.doc
= it
.docs(db
);
291 format_to
!(res
.signature
, "trait {}", it
.name(db
).display(db
));
293 hir
::GenericDef
::TypeAlias(it
) => {
294 res
.doc
= it
.docs(db
);
295 format_to
!(res
.signature
, "type {}", it
.name(db
).display(db
));
297 hir
::GenericDef
::Variant(it
) => {
298 // In paths, generics of an enum can be specified *after* one of its variants.
300 // We'll use the signature of the enum, but include the docs of the variant.
301 res
.doc
= it
.docs(db
);
302 let enum_
= it
.parent_enum(db
);
303 format_to
!(res
.signature
, "enum {}", enum_
.name(db
).display(db
));
304 generics_def
= enum_
.into();
306 // These don't have generic args that can be specified
307 hir
::GenericDef
::Impl(_
) | hir
::GenericDef
::Const(_
) => return None
,
310 let params
= generics_def
.params(sema
.db
);
311 let num_lifetime_params
=
312 params
.iter().take_while(|param
| matches
!(param
, GenericParam
::LifetimeParam(_
))).count();
313 if first_arg_is_non_lifetime
{
314 // Lifetime parameters were omitted.
315 active_parameter
+= num_lifetime_params
;
317 res
.active_parameter
= Some(active_parameter
);
319 res
.signature
.push('
<'
);
320 let mut buf
= String
::new();
321 for param
in params
{
322 if let hir
::GenericParam
::TypeParam(ty
) = param
{
323 if ty
.is_implicit(db
) {
329 format_to
!(buf
, "{}", param
.display(db
));
330 res
.push_generic_param(&buf
);
332 if let hir
::GenericDef
::Trait(tr
) = generics_def
{
333 add_assoc_type_bindings(db
, &mut res
, tr
, arg_list
);
335 res
.signature
.push('
>'
);
340 fn add_assoc_type_bindings(
342 res
: &mut SignatureHelp
,
344 args
: ast
::GenericArgList
,
346 if args
.syntax().ancestors().find_map(ast
::TypeBound
::cast
).is_none() {
347 // Assoc type bindings are only valid in type bound position.
351 let present_bindings
= args
353 .filter_map(|arg
| match arg
{
354 ast
::GenericArg
::AssocTypeArg(arg
) => arg
.name_ref().map(|n
| n
.to_string()),
357 .collect
::<BTreeSet
<_
>>();
359 let mut buf
= String
::new();
360 for binding
in &present_bindings
{
362 format_to
!(buf
, "{} = …", binding
);
363 res
.push_generic_param(&buf
);
366 for item
in tr
.items_with_supertraits(db
) {
367 if let AssocItem
::TypeAlias(ty
) = item
{
368 let name
= ty
.name(db
).to_smol_str();
369 if !present_bindings
.contains(&*name
) {
371 format_to
!(buf
, "{} = …", name
);
372 res
.push_generic_param(&buf
);
378 fn signature_help_for_record_lit(
379 sema
: &Semantics
<'_
, RootDatabase
>,
380 record
: ast
::RecordExpr
,
382 ) -> Option
<SignatureHelp
> {
383 signature_help_for_record_(
385 record
.record_expr_field_list()?
.syntax().children_with_tokens(),
388 .record_expr_field_list()?
390 .filter_map(|field
| sema
.resolve_record_field(&field
))
391 .map(|(field
, _
, ty
)| (field
, ty
)),
396 fn signature_help_for_record_pat(
397 sema
: &Semantics
<'_
, RootDatabase
>,
398 record
: ast
::RecordPat
,
400 ) -> Option
<SignatureHelp
> {
401 signature_help_for_record_(
403 record
.record_pat_field_list()?
.syntax().children_with_tokens(),
406 .record_pat_field_list()?
408 .filter_map(|field
| sema
.resolve_record_pat_field(&field
)),
413 fn signature_help_for_tuple_struct_pat(
414 sema
: &Semantics
<'_
, RootDatabase
>,
415 pat
: ast
::TupleStructPat
,
417 ) -> Option
<SignatureHelp
> {
418 let path
= pat
.path()?
;
419 let path_res
= sema
.resolve_path(&path
)?
;
420 let mut res
= SignatureHelp
{
422 signature
: String
::new(),
424 active_parameter
: None
,
428 let fields
: Vec
<_
> = if let PathResolution
::Def(ModuleDef
::Variant(variant
)) = path_res
{
429 let en
= variant
.parent_enum(db
);
431 res
.doc
= en
.docs(db
).map(|it
| it
.into());
435 en
.name(db
).display(db
),
436 variant
.name(db
).display(db
)
440 let adt
= match path_res
{
441 PathResolution
::SelfType(imp
) => imp
.self_ty(db
).as_adt()?
,
442 PathResolution
::Def(ModuleDef
::Adt(adt
)) => adt
,
447 hir
::Adt
::Struct(it
) => {
448 res
.doc
= it
.docs(db
).map(|it
| it
.into());
449 format_to
!(res
.signature
, "struct {} (", it
.name(db
).display(db
));
455 Some(signature_help_for_tuple_pat_ish(
461 fields
.into_iter().map(|it
| it
.ty(db
)),
465 fn signature_help_for_tuple_pat(
466 sema
: &Semantics
<'_
, RootDatabase
>,
469 ) -> Option
<SignatureHelp
> {
471 let field_pats
= pat
.fields();
472 let pat
= pat
.into();
473 let ty
= sema
.type_of_pat(&pat
)?
;
474 let fields
= ty
.original
.tuple_fields(db
);
476 Some(signature_help_for_tuple_pat_ish(
480 signature
: String
::from('
('
),
482 active_parameter
: None
,
491 fn signature_help_for_tuple_expr(
492 sema
: &Semantics
<'_
, RootDatabase
>,
493 expr
: ast
::TupleExpr
,
495 ) -> Option
<SignatureHelp
> {
496 let active_parameter
= Some(
498 .children_with_tokens()
499 .filter_map(NodeOrToken
::into_token
)
500 .filter(|t
| t
.kind() == T
![,])
501 .take_while(|t
| t
.text_range().start() <= token
.text_range().start())
506 let mut res
= SignatureHelp
{
508 signature
: String
::from('
('
),
512 let expr
= sema
.type_of_expr(&expr
.into())?
;
513 let fields
= expr
.original
.tuple_fields(db
);
514 let mut buf
= String
::new();
516 format_to
!(buf
, "{}", ty
.display_truncated(db
, Some(20)));
517 res
.push_call_param(&buf
);
520 res
.signature
.push('
)'
);
524 fn signature_help_for_record_(
525 sema
: &Semantics
<'_
, RootDatabase
>,
526 field_list_children
: SyntaxElementChildren
,
528 fields2
: impl Iterator
<Item
= (hir
::Field
, hir
::Type
)>,
530 ) -> Option
<SignatureHelp
> {
531 let active_parameter
= field_list_children
532 .filter_map(NodeOrToken
::into_token
)
533 .filter(|t
| t
.kind() == T
![,])
534 .take_while(|t
| t
.text_range().start() <= token
.text_range().start())
537 let mut res
= SignatureHelp
{
539 signature
: String
::new(),
541 active_parameter
: Some(active_parameter
),
547 let path_res
= sema
.resolve_path(path
)?
;
548 if let PathResolution
::Def(ModuleDef
::Variant(variant
)) = path_res
{
549 fields
= variant
.fields(db
);
550 let en
= variant
.parent_enum(db
);
552 res
.doc
= en
.docs(db
).map(|it
| it
.into());
556 en
.name(db
).display(db
),
557 variant
.name(db
).display(db
)
560 let adt
= match path_res
{
561 PathResolution
::SelfType(imp
) => imp
.self_ty(db
).as_adt()?
,
562 PathResolution
::Def(ModuleDef
::Adt(adt
)) => adt
,
567 hir
::Adt
::Struct(it
) => {
568 fields
= it
.fields(db
);
569 res
.doc
= it
.docs(db
).map(|it
| it
.into());
570 format_to
!(res
.signature
, "struct {} {{ ", it
.name(db
).display(db
));
572 hir
::Adt
::Union(it
) => {
573 fields
= it
.fields(db
);
574 res
.doc
= it
.docs(db
).map(|it
| it
.into());
575 format_to
!(res
.signature
, "union {} {{ ", it
.name(db
).display(db
));
582 fields
.into_iter().map(|field
| (field
.name(db
), Some(field
))).collect
::<FxIndexMap
<_
, _
>>();
583 let mut buf
= String
::new();
584 for (field
, ty
) in fields2
{
585 let name
= field
.name(db
);
586 format_to
!(buf
, "{}: {}", name
.display(db
), ty
.display_truncated(db
, Some(20)));
587 res
.push_record_field(&buf
);
590 if let Some(field
) = fields
.get_mut(&name
) {
594 for (name
, field
) in fields
{
595 let Some(field
) = field
else { continue }
;
596 format_to
!(buf
, "{}: {}", name
.display(db
), field
.ty(db
).display_truncated(db
, Some(20)));
597 res
.push_record_field(&buf
);
600 res
.signature
.push_str(" }");
604 fn signature_help_for_tuple_pat_ish(
606 mut res
: SignatureHelp
,
609 mut field_pats
: AstChildren
<ast
::Pat
>,
610 fields
: impl ExactSizeIterator
<Item
= hir
::Type
>,
612 let rest_pat
= field_pats
.find(|it
| matches
!(it
, ast
::Pat
::RestPat(_
)));
613 let is_left_of_rest_pat
=
614 rest_pat
.map_or(true, |it
| token
.text_range().start() < it
.syntax().text_range().end());
617 .children_with_tokens()
618 .filter_map(NodeOrToken
::into_token
)
619 .filter(|t
| t
.kind() == T
![,]);
621 res
.active_parameter
= {
622 Some(if is_left_of_rest_pat
{
623 commas
.take_while(|t
| t
.text_range().start() <= token
.text_range().start()).count()
625 let n_commas
= commas
629 .take_while(|t
| t
.text_range().start() > token
.text_range().start())
631 fields
.len().saturating_sub(1).saturating_sub(n_commas
)
635 let mut buf
= String
::new();
637 format_to
!(buf
, "{}", ty
.display_truncated(db
, Some(20)));
638 res
.push_call_param(&buf
);
641 res
.signature
.push_str(")");
648 use expect_test
::{expect, Expect}
;
649 use ide_db
::base_db
::{fixture::ChangeFixture, FilePosition}
;
652 use crate::RootDatabase
;
654 /// Creates analysis from a multi-file fixture, returns positions marked with $0.
655 pub(crate) fn position(ra_fixture
: &str) -> (RootDatabase
, FilePosition
) {
656 let change_fixture
= ChangeFixture
::parse(ra_fixture
);
657 let mut database
= RootDatabase
::default();
658 database
.apply_change(change_fixture
.change
);
659 let (file_id
, range_or_offset
) =
660 change_fixture
.file_position
.expect("expected a marker ($0)");
661 let offset
= range_or_offset
.expect_offset();
662 (database
, FilePosition { file_id, offset }
)
666 fn check(ra_fixture
: &str, expect
: Expect
) {
667 let fixture
= format
!(
669 //- minicore: sized, fn
673 let (db
, position
) = position(&fixture
);
674 let sig_help
= crate::signature_help
::signature_help(&db
, position
);
675 let actual
= match sig_help
{
677 let mut rendered
= String
::new();
678 if let Some(docs
) = &sig_help
.doc
{
679 format_to
!(rendered
, "{}\n------\n", docs
.as_str());
681 format_to
!(rendered
, "{}\n", sig_help
.signature
);
683 for (i
, range
) in sig_help
.parameter_ranges().iter().enumerate() {
684 let is_active
= sig_help
.active_parameter
== Some(i
);
686 let start
= u32::from(range
.start());
687 let gap
= start
.checked_sub(offset
).unwrap_or_else(|| {
688 panic
!("parameter ranges out of order: {:?}", sig_help
.parameter_ranges())
690 rendered
.extend(iter
::repeat(' '
).take(gap
as usize));
691 let param_text
= &sig_help
.signature
[*range
];
692 let width
= param_text
.chars().count(); // …
693 let marker
= if is_active { '^' }
else { '-' }
;
694 rendered
.extend(iter
::repeat(marker
).take(width
));
695 offset
+= gap
+ u32::from(range
.len());
697 if !sig_help
.parameter_ranges().is_empty() {
698 format_to
!(rendered
, "\n");
702 None
=> String
::new(),
704 expect
.assert_eq(&actual
);
708 fn test_fn_signature_two_args() {
711 fn foo(x: u32, y: u32) -> u32 {x + y}
712 fn bar() { foo($03, ); }
715 fn foo(x: u32, y: u32) -> u32
721 fn foo(x: u32, y: u32) -> u32 {x + y}
722 fn bar() { foo(3$0, ); }
725 fn foo(x: u32, y: u32) -> u32
731 fn foo(x: u32, y: u32) -> u32 {x + y}
732 fn bar() { foo(3,$0 ); }
735 fn foo(x: u32, y: u32) -> u32
741 fn foo(x: u32, y: u32) -> u32 {x + y}
742 fn bar() { foo(3, $0); }
745 fn foo(x: u32, y: u32) -> u32
752 fn test_fn_signature_two_args_empty() {
755 fn foo(x: u32, y: u32) -> u32 {x + y}
756 fn bar() { foo($0); }
759 fn foo(x: u32, y: u32) -> u32
766 fn test_fn_signature_two_args_first_generics() {
769 fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
770 where T: Copy + Display, U: Debug
773 fn bar() { foo($03, ); }
776 fn foo(x: i32, y: U) -> u32
783 fn test_fn_signature_no_params() {
786 fn foo<T>() -> T where T: Copy + Display {}
787 fn bar() { foo($0); }
796 fn test_fn_signature_for_impl() {
800 impl F { pub fn new() { } }
802 let _ : F = F::new($0);
812 fn test_fn_signature_for_method_self() {
816 impl S { pub fn do_it(&self) {} }
830 fn test_fn_signature_for_method_with_arg() {
835 fn foo(&self, x: i32) {}
838 fn main() { S.foo($0); }
841 fn foo(&self, x: i32)
848 fn test_fn_signature_for_generic_method() {
853 fn foo(&self, x: T) {}
856 fn main() { S(1u32).foo($0); }
859 fn foo(&self, x: u32)
866 fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
871 fn foo(&self, x: i32) {}
874 fn main() { S::foo($0); }
877 fn foo(self: &S, x: i32)
884 fn test_fn_signature_with_docs_simple() {
889 fn foo(j: u32) -> u32 {
900 fn foo(j: u32) -> u32
907 fn test_fn_signature_with_docs() {
910 /// Adds one to the number given.
917 /// assert_eq!(6, my_crate::add_one(5));
919 pub fn add_one(x: i32) -> i32 {
927 Adds one to the number given.
934 assert_eq!(6, my_crate::add_one(5));
937 fn add_one(x: i32) -> i32
944 fn test_fn_signature_with_docs_impl() {
949 /// Adds one to the number given.
956 /// assert_eq!(6, my_crate::add_one(5));
958 pub fn add_one(x: i32) -> i32 {
969 Adds one to the number given.
976 assert_eq!(6, my_crate::add_one(5));
979 fn add_one(x: i32) -> i32
986 fn test_fn_signature_with_docs_from_actix() {
990 /// Actor execution context type
993 trait WriteHandler<E>
997 /// Method is called when writer finishes.
999 /// By default this method stops actor's `Context`.
1000 fn finished(&mut self, ctx: &mut Self::Context) {}
1003 fn foo(mut r: impl WriteHandler<()>) {
1008 Method is called when writer finishes.
1010 By default this method stops actor's `Context`.
1012 fn finished(&mut self, ctx: &mut <impl WriteHandler<()> as Actor>::Context)
1013 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1019 fn call_info_bad_offset() {
1022 fn foo(x: u32, y: u32) -> u32 {x + y}
1023 fn bar() { foo $0 (3, ); }
1030 fn outside_of_arg_list() {
1051 fn foo(a: u8) -> u8 {a}
1052 fn bar(a: u8) -> u8 {a}
1067 let _: Vec2<Vec<u8>$0>
1078 fn test_nested_method_in_lambda() {
1082 impl Foo { fn bar(&self, _: u32) { } }
1088 std::thread::spawn(move || foo.bar($0));
1092 fn bar(&self, _: u32)
1099 fn works_for_tuple_structs() {
1102 /// A cool tuple struct
1118 fn tuple_struct_pat() {
1121 /// A cool tuple struct
1137 fn tuple_struct_pat_rest() {
1140 /// A cool tuple struct
1141 struct S(u32, i32, f32, u16);
1149 struct S (u32, i32, f32, u16)
1155 /// A cool tuple struct
1156 struct S(u32, i32, f32, u16, u8);
1158 let S(0, .., $0, 0);
1164 struct S (u32, i32, f32, u16, u8)
1170 /// A cool tuple struct
1171 struct S(u32, i32, f32, u16);
1179 struct S (u32, i32, f32, u16)
1185 /// A cool tuple struct
1186 struct S(u32, i32, f32, u16, u8);
1188 let S(1, .., 1, $0, 2);
1194 struct S (u32, i32, f32, u16, u8)
1200 /// A cool tuple struct
1201 struct S(u32, i32, f32, u16);
1209 struct S (u32, i32, f32, u16)
1215 /// A cool tuple struct
1216 struct S(u32, i32, f32, u16);
1224 struct S (u32, i32, f32, u16)
1231 fn generic_struct() {
1247 fn works_for_enum_variants() {
1256 C { a: i32, b: i32 }
1273 fn cant_call_struct_record() {
1276 struct S { x: u32, y: i32 }
1286 fn cant_call_enum_record() {
1295 C { a: i32, b: i32 }
1307 fn fn_signature_for_call_in_macro() {
1310 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1313 fn bar() { foo($0); }
1323 fn fn_signature_for_method_call_defined_in_macro() {
1326 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1330 fn foo<'a>(&'a mut self) {}
1333 fn test() { S.foo($0); }
1336 fn foo(&'a mut self)
1342 fn call_info_for_lambdas() {
1346 fn foo(s: S) -> i32 { 92 }
1359 fn call_info_for_fn_def_over_reference() {
1363 fn foo(s: S) -> i32 { 92 }
1377 fn call_info_for_fn_ptr() {
1380 fn main(f: fn(i32, f64) -> char) {
1392 fn call_info_for_unclosed_call() {
1395 fn foo(foo: u32, bar: u32) {}
1400 fn foo(foo: u32, bar: u32)
1404 // check with surrounding space
1407 fn foo(foo: u32, bar: u32) {}
1412 fn foo(foo: u32, bar: u32)
1419 fn test_multiline_argument() {
1422 fn callee(a: u8, b: u8) {}
1432 fn callee(a: u8, b: u8) {}
1439 fn callee(a: u8, b: u8)
1445 fn callee(a: u8, b: u8) {}
1452 fn callee(a: u8, b: u8)
1459 fn test_generics_simple() {
1482 fn test_generics_on_variant() {
1509 fn test_lots_of_generics() {
1517 fn f<G, H>(g: G, h: impl Tr<G>) where G: Tr<()> {}
1532 fn test_generics_in_trait_ufcs() {
1555 fn test_generics_in_method_call() {
1576 fn test_generic_param_in_method_call() {
1581 fn test<V>(&mut self, val: V) {}
1588 fn test(&mut self, val: V)
1595 fn test_generic_kinds() {
1598 fn callee<'a, const A: u8, T, const C: u8>() {}
1601 callee::<'static, $0
1605 fn callee<'a, const A: u8, T, const C: u8>
1606 -- ^^^^^^^^^^^ - -----------
1611 fn callee<'a, const A: u8, T, const C: u8>() {}
1614 callee::<NON_LIFETIME$0
1618 fn callee<'a, const A: u8, T, const C: u8>
1619 -- ^^^^^^^^^^^ - -----------
1625 fn test_trait_assoc_types() {
1628 trait Trait<'a, T> {
1631 fn f() -> impl Trait<(), $0
1634 trait Trait<'a, T, Assoc = …>
1643 fn f() -> impl Iterator<$0
1646 trait Iterator<Item = …>
1655 fn f() -> impl Iterator<Item = $0
1658 trait Iterator<Item = …>
1668 fn f() -> impl Tr<$0
1671 trait Tr<A = …, B = …>
1681 fn f() -> impl Tr<B$0
1684 trait Tr<A = …, B = …>
1694 fn f() -> impl Tr<B = $0
1697 trait Tr<B = …, A = …>
1707 fn f() -> impl Tr<B = (), $0
1710 trait Tr<B = …, A = …>
1717 fn test_supertrait_assoc() {
1723 trait Sub: Super + Super {
1726 fn f() -> impl Sub<$0
1729 trait Sub<SubTy = …, SuperTy = …>
1730 ^^^^^^^^^ -----------
1736 fn no_assoc_types_outside_type_bounds() {
1754 // FIXME: Substitute type vars in impl trait (`U` -> `i8`)
1759 fn foo<U>(x: Wrap<impl Trait<U>>) {}
1765 fn foo(x: Wrap<impl Trait<U>>)
1766 ^^^^^^^^^^^^^^^^^^^^^^
1772 fn fully_qualified_syntax() {
1776 trait A { fn foo(&self, other: Self); }
1777 A::foo(&self$0, other);
1781 fn foo(self: &Self, other: Self)
1782 ^^^^^^^^^^^ -----------
1788 fn help_for_generic_call() {
1791 fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
1802 fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
1814 fn regression_13579() {
1823 ) -> impl Fn() -> C {
1834 fn record_literal() {
1837 struct Strukt<T, U = ()> {
1850 struct Strukt { u: i32, t: T, unit: () }
1851 ------ ^^^^ --------
1857 fn record_literal_nonexistent_field() {
1871 struct Strukt { a: u8 }
1878 fn tuple_variant_record_literal() {
1889 enum Opt::Some { 0: u8 }
1903 enum Opt::Some { 0: u8 }
1910 fn record_literal_self() {
1931 struct Strukt<T, U = ()> {
1944 struct Strukt { u: i32, t: T, unit: () }
1945 ------ ^^^^ --------
1951 fn test_enum_in_nested_method_in_lambda() {
1963 std::thread::spawn(move || { bar(A:$0) } );
1974 fn test_tuple_expr_free() {
2022 fn test_tuple_expr_expected() {
2026 let _: (&str, u32, u32)= ($0, 1, 3);
2034 // FIXME: Should typeck report a 4-ary tuple for the expression here?
2038 let _: (&str, u32, u32, u32) = ($0, 1, 3);
2049 let _: (&str, u32, u32)= ($0, 1, 3, 5);
2053 (&str, u32, u32, i32)
2060 fn test_tuple_pat_free() {
2068 ({unknown}, i32, i32)
2133 // FIXME: This is wrong, this should not mark the last as active
2142 fn test_tuple_pat_expected() {
2146 let (0$0, 1, 3): (i32, i32, i32);
2157 let ($0, 1, 3): (i32, i32, i32);
2168 let (1, 3 $0): (i32,);
2179 let (1, 3 $0, ..): (i32, i32, i32, i32);
2183 (i32, i32, i32, i32)
2190 let (1, 3, .., $0): (i32, i32, i32);
2200 fn test_tuple_pat_expected_inferred() {
2204 let (0$0, 1, 3) = (1, 2 ,3);
2215 let ($0 1, 3) = (1, 2, 3);
2218 // FIXME: Should typeck report a 3-ary tuple for the pattern here?
2227 let (1, 3 $0) = (1,);
2238 let (1, 3 $0, ..) = (1, 2, 3, 4);
2242 (i32, i32, i32, i32)
2249 let (1, 3, .., $0) = (1, 2, 3);