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
;
7 use hir
::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait}
;
9 active_parameter
::{callable_for_node, generic_def_for_node}
,
10 base_db
::FilePosition
,
11 documentation
::{Documentation, HasDocs}
,
17 ast
::{self, AstChildren, HasArgList}
,
18 match_ast
, AstNode
, Direction
, NodeOrToken
, SyntaxElementChildren
, SyntaxNode
, SyntaxToken
,
19 TextRange
, TextSize
, T
,
22 use crate::RootDatabase
;
24 /// Contains information about an item signature as seen from a use site.
26 /// This includes the "active parameter", which is the parameter whose value is currently being
29 pub struct SignatureHelp
{
30 pub doc
: Option
<Documentation
>,
31 pub signature
: String
,
32 pub active_parameter
: Option
<usize>,
33 parameters
: Vec
<TextRange
>,
37 pub fn parameter_labels(&self) -> impl Iterator
<Item
= &str> + '_
{
38 self.parameters
.iter().map(move |&it
| &self.signature
[it
])
41 pub fn parameter_ranges(&self) -> &[TextRange
] {
45 fn push_call_param(&mut self, param
: &str) {
46 self.push_param("(", param
);
49 fn push_generic_param(&mut self, param
: &str) {
50 self.push_param("<", param
);
53 fn push_record_field(&mut self, param
: &str) {
54 self.push_param("{ ", param
);
57 fn push_param(&mut self, opening_delim
: &str, param
: &str) {
58 if !self.signature
.ends_with(opening_delim
) {
59 self.signature
.push_str(", ");
61 let start
= TextSize
::of(&self.signature
);
62 self.signature
.push_str(param
);
63 let end
= TextSize
::of(&self.signature
);
64 self.parameters
.push(TextRange
::new(start
, end
))
68 /// Computes parameter information for the given position.
69 pub(crate) fn signature_help(
71 FilePosition { file_id, offset }
: FilePosition
,
72 ) -> Option
<SignatureHelp
> {
73 let sema
= Semantics
::new(db
);
74 let file
= sema
.parse(file_id
);
75 let file
= file
.syntax();
77 .token_at_offset(offset
)
79 // if the cursor is sandwiched between two space tokens and the call is unclosed
80 // this prevents us from leaving the CallExpression
81 .and_then(|tok
| algo
::skip_trivia_token(tok
, Direction
::Prev
))?
;
82 let token
= sema
.descend_into_macros_single(token
, offset
);
84 for node
in token
.parent_ancestors() {
87 ast
::ArgList(arg_list
) => {
88 let cursor_outside
= arg_list
.r_paren_token().as_ref() == Some(&token
);
92 return signature_help_for_call(&sema
, arg_list
, token
);
94 ast
::GenericArgList(garg_list
) => {
95 let cursor_outside
= garg_list
.r_angle_token().as_ref() == Some(&token
);
99 return signature_help_for_generics(&sema
, garg_list
, token
);
101 ast
::RecordExpr(record
) => {
102 let cursor_outside
= record
.record_expr_field_list().and_then(|list
| list
.r_curly_token()).as_ref() == Some(&token
);
106 return signature_help_for_record_lit(&sema
, record
, token
);
108 ast
::RecordPat(record
) => {
109 let cursor_outside
= record
.record_pat_field_list().and_then(|list
| list
.r_curly_token()).as_ref() == Some(&token
);
113 return signature_help_for_record_pat(&sema
, record
, token
);
115 ast
::TupleStructPat(tuple_pat
) => {
116 let cursor_outside
= tuple_pat
.r_paren_token().as_ref() == Some(&token
);
120 return signature_help_for_tuple_struct_pat(&sema
, tuple_pat
, token
);
122 ast
::TuplePat(tuple_pat
) => {
123 let cursor_outside
= tuple_pat
.r_paren_token().as_ref() == Some(&token
);
127 return signature_help_for_tuple_pat(&sema
, tuple_pat
, token
);
129 ast
::TupleExpr(tuple_expr
) => {
130 let cursor_outside
= tuple_expr
.r_paren_token().as_ref() == Some(&token
);
134 return signature_help_for_tuple_expr(&sema
, tuple_expr
, token
);
140 // Stop at multi-line expressions, since the signature of the outer call is not very
141 // helpful inside them.
142 if let Some(expr
) = ast
::Expr
::cast(node
.clone()) {
143 if !matches
!(expr
, ast
::Expr
::RecordExpr(..))
144 && expr
.syntax().text().contains_char('
\n'
)
154 fn signature_help_for_call(
155 sema
: &Semantics
<'_
, RootDatabase
>,
156 arg_list
: ast
::ArgList
,
158 ) -> Option
<SignatureHelp
> {
159 // Find the calling expression and its NameRef
160 let mut nodes
= arg_list
.syntax().ancestors().skip(1);
161 let calling_node
= loop {
162 if let Some(callable
) = ast
::CallableExpr
::cast(nodes
.next()?
) {
163 let inside_callable
= callable
165 .map_or(false, |it
| it
.syntax().text_range().contains(token
.text_range().start()));
172 let (callable
, active_parameter
) = callable_for_node(sema
, &calling_node
, &token
)?
;
175 SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter }
;
178 let mut fn_params
= None
;
179 match callable
.kind() {
180 hir
::CallableKind
::Function(func
) => {
181 res
.doc
= func
.docs(db
);
182 format_to
!(res
.signature
, "fn {}", func
.name(db
).display(db
));
183 fn_params
= Some(match callable
.receiver_param(db
) {
184 Some(_self
) => func
.params_without_self(db
),
185 None
=> func
.assoc_fn_params(db
),
188 hir
::CallableKind
::TupleStruct(strukt
) => {
189 res
.doc
= strukt
.docs(db
);
190 format_to
!(res
.signature
, "struct {}", strukt
.name(db
).display(db
));
192 hir
::CallableKind
::TupleEnumVariant(variant
) => {
193 res
.doc
= variant
.docs(db
);
197 variant
.parent_enum(db
).name(db
).display(db
),
198 variant
.name(db
).display(db
)
201 hir
::CallableKind
::Closure
| hir
::CallableKind
::FnPtr
| hir
::CallableKind
::Other
=> (),
204 res
.signature
.push('
('
);
206 if let Some((self_param
, _
)) = callable
.receiver_param(db
) {
207 format_to
!(res
.signature
, "{}", self_param
.display(db
))
209 let mut buf
= String
::new();
210 for (idx
, (pat
, ty
)) in callable
.params(db
).into_iter().enumerate() {
212 if let Some(pat
) = pat
{
214 Either
::Left(_self
) => format_to
!(buf
, "self: "),
215 Either
::Right(pat
) => format_to
!(buf
, "{}: ", pat
),
218 // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
219 // in the middle of entering call arguments.
220 // In that case, fall back to render definitions of the respective parameters.
221 // This is overly conservative: we do not substitute known type vars
222 // (see FIXME in tests::impl_trait) and falling back on any unknowns.
223 match (ty
.contains_unknown(), fn_params
.as_deref()) {
224 (true, Some(fn_params
)) => format_to
!(buf
, "{}", fn_params
[idx
].ty().display(db
)),
225 _
=> format_to
!(buf
, "{}", ty
.display(db
)),
227 res
.push_call_param(&buf
);
230 res
.signature
.push('
)'
);
232 let mut render
= |ret_type
: hir
::Type
| {
233 if !ret_type
.is_unit() {
234 format_to
!(res
.signature
, " -> {}", ret_type
.display(db
));
237 match callable
.kind() {
238 hir
::CallableKind
::Function(func
) if callable
.return_type().contains_unknown() => {
239 render(func
.ret_type(db
))
241 hir
::CallableKind
::Function(_
)
242 | hir
::CallableKind
::Closure
243 | hir
::CallableKind
::FnPtr
244 | hir
::CallableKind
::Other
=> render(callable
.return_type()),
245 hir
::CallableKind
::TupleStruct(_
) | hir
::CallableKind
::TupleEnumVariant(_
) => {}
250 fn signature_help_for_generics(
251 sema
: &Semantics
<'_
, RootDatabase
>,
252 arg_list
: ast
::GenericArgList
,
254 ) -> Option
<SignatureHelp
> {
255 let (mut generics_def
, mut active_parameter
, first_arg_is_non_lifetime
) =
256 generic_def_for_node(sema
, &arg_list
, &token
)?
;
257 let mut res
= SignatureHelp
{
259 signature
: String
::new(),
261 active_parameter
: None
,
266 hir
::GenericDef
::Function(it
) => {
267 res
.doc
= it
.docs(db
);
268 format_to
!(res
.signature
, "fn {}", it
.name(db
).display(db
));
270 hir
::GenericDef
::Adt(hir
::Adt
::Enum(it
)) => {
271 res
.doc
= it
.docs(db
);
272 format_to
!(res
.signature
, "enum {}", it
.name(db
).display(db
));
274 hir
::GenericDef
::Adt(hir
::Adt
::Struct(it
)) => {
275 res
.doc
= it
.docs(db
);
276 format_to
!(res
.signature
, "struct {}", it
.name(db
).display(db
));
278 hir
::GenericDef
::Adt(hir
::Adt
::Union(it
)) => {
279 res
.doc
= it
.docs(db
);
280 format_to
!(res
.signature
, "union {}", it
.name(db
).display(db
));
282 hir
::GenericDef
::Trait(it
) => {
283 res
.doc
= it
.docs(db
);
284 format_to
!(res
.signature
, "trait {}", it
.name(db
).display(db
));
286 hir
::GenericDef
::TraitAlias(it
) => {
287 res
.doc
= it
.docs(db
);
288 format_to
!(res
.signature
, "trait {}", it
.name(db
).display(db
));
290 hir
::GenericDef
::TypeAlias(it
) => {
291 res
.doc
= it
.docs(db
);
292 format_to
!(res
.signature
, "type {}", it
.name(db
).display(db
));
294 hir
::GenericDef
::Variant(it
) => {
295 // In paths, generics of an enum can be specified *after* one of its variants.
297 // We'll use the signature of the enum, but include the docs of the variant.
298 res
.doc
= it
.docs(db
);
299 let enum_
= it
.parent_enum(db
);
300 format_to
!(res
.signature
, "enum {}", enum_
.name(db
).display(db
));
301 generics_def
= enum_
.into();
303 // These don't have generic args that can be specified
304 hir
::GenericDef
::Impl(_
) | hir
::GenericDef
::Const(_
) => return None
,
307 let params
= generics_def
.params(sema
.db
);
308 let num_lifetime_params
=
309 params
.iter().take_while(|param
| matches
!(param
, GenericParam
::LifetimeParam(_
))).count();
310 if first_arg_is_non_lifetime
{
311 // Lifetime parameters were omitted.
312 active_parameter
+= num_lifetime_params
;
314 res
.active_parameter
= Some(active_parameter
);
316 res
.signature
.push('
<'
);
317 let mut buf
= String
::new();
318 for param
in params
{
319 if let hir
::GenericParam
::TypeParam(ty
) = param
{
320 if ty
.is_implicit(db
) {
326 format_to
!(buf
, "{}", param
.display(db
));
327 res
.push_generic_param(&buf
);
329 if let hir
::GenericDef
::Trait(tr
) = generics_def
{
330 add_assoc_type_bindings(db
, &mut res
, tr
, arg_list
);
332 res
.signature
.push('
>'
);
337 fn add_assoc_type_bindings(
339 res
: &mut SignatureHelp
,
341 args
: ast
::GenericArgList
,
343 if args
.syntax().ancestors().find_map(ast
::TypeBound
::cast
).is_none() {
344 // Assoc type bindings are only valid in type bound position.
348 let present_bindings
= args
350 .filter_map(|arg
| match arg
{
351 ast
::GenericArg
::AssocTypeArg(arg
) => arg
.name_ref().map(|n
| n
.to_string()),
354 .collect
::<BTreeSet
<_
>>();
356 let mut buf
= String
::new();
357 for binding
in &present_bindings
{
359 format_to
!(buf
, "{} = …", binding
);
360 res
.push_generic_param(&buf
);
363 for item
in tr
.items_with_supertraits(db
) {
364 if let AssocItem
::TypeAlias(ty
) = item
{
365 let name
= ty
.name(db
).to_smol_str();
366 if !present_bindings
.contains(&*name
) {
368 format_to
!(buf
, "{} = …", name
);
369 res
.push_generic_param(&buf
);
375 fn signature_help_for_record_lit(
376 sema
: &Semantics
<'_
, RootDatabase
>,
377 record
: ast
::RecordExpr
,
379 ) -> Option
<SignatureHelp
> {
380 signature_help_for_record_(
382 record
.record_expr_field_list()?
.syntax().children_with_tokens(),
385 .record_expr_field_list()?
387 .filter_map(|field
| sema
.resolve_record_field(&field
))
388 .map(|(field
, _
, ty
)| (field
, ty
)),
393 fn signature_help_for_record_pat(
394 sema
: &Semantics
<'_
, RootDatabase
>,
395 record
: ast
::RecordPat
,
397 ) -> Option
<SignatureHelp
> {
398 signature_help_for_record_(
400 record
.record_pat_field_list()?
.syntax().children_with_tokens(),
403 .record_pat_field_list()?
405 .filter_map(|field
| sema
.resolve_record_pat_field(&field
)),
410 fn signature_help_for_tuple_struct_pat(
411 sema
: &Semantics
<'_
, RootDatabase
>,
412 pat
: ast
::TupleStructPat
,
414 ) -> Option
<SignatureHelp
> {
415 let path
= pat
.path()?
;
416 let path_res
= sema
.resolve_path(&path
)?
;
417 let mut res
= SignatureHelp
{
419 signature
: String
::new(),
421 active_parameter
: None
,
425 let fields
: Vec
<_
> = if let PathResolution
::Def(ModuleDef
::Variant(variant
)) = path_res
{
426 let en
= variant
.parent_enum(db
);
428 res
.doc
= en
.docs(db
).map(|it
| it
.into());
432 en
.name(db
).display(db
),
433 variant
.name(db
).display(db
)
437 let adt
= match path_res
{
438 PathResolution
::SelfType(imp
) => imp
.self_ty(db
).as_adt()?
,
439 PathResolution
::Def(ModuleDef
::Adt(adt
)) => adt
,
444 hir
::Adt
::Struct(it
) => {
445 res
.doc
= it
.docs(db
).map(|it
| it
.into());
446 format_to
!(res
.signature
, "struct {} (", it
.name(db
).display(db
));
452 Some(signature_help_for_tuple_pat_ish(
458 fields
.into_iter().map(|it
| it
.ty(db
)),
462 fn signature_help_for_tuple_pat(
463 sema
: &Semantics
<'_
, RootDatabase
>,
466 ) -> Option
<SignatureHelp
> {
468 let field_pats
= pat
.fields();
469 let pat
= pat
.into();
470 let ty
= sema
.type_of_pat(&pat
)?
;
471 let fields
= ty
.original
.tuple_fields(db
);
473 Some(signature_help_for_tuple_pat_ish(
477 signature
: String
::from('
('
),
479 active_parameter
: None
,
488 fn signature_help_for_tuple_expr(
489 sema
: &Semantics
<'_
, RootDatabase
>,
490 expr
: ast
::TupleExpr
,
492 ) -> Option
<SignatureHelp
> {
493 let active_parameter
= Some(
495 .children_with_tokens()
496 .filter_map(NodeOrToken
::into_token
)
497 .filter(|t
| t
.kind() == T
![,])
498 .take_while(|t
| t
.text_range().start() <= token
.text_range().start())
503 let mut res
= SignatureHelp
{
505 signature
: String
::from('
('
),
509 let expr
= sema
.type_of_expr(&expr
.into())?
;
510 let fields
= expr
.original
.tuple_fields(db
);
511 let mut buf
= String
::new();
513 format_to
!(buf
, "{}", ty
.display_truncated(db
, Some(20)));
514 res
.push_call_param(&buf
);
517 res
.signature
.push('
)'
);
521 fn signature_help_for_record_(
522 sema
: &Semantics
<'_
, RootDatabase
>,
523 field_list_children
: SyntaxElementChildren
,
525 fields2
: impl Iterator
<Item
= (hir
::Field
, hir
::Type
)>,
527 ) -> Option
<SignatureHelp
> {
528 let active_parameter
= field_list_children
529 .filter_map(NodeOrToken
::into_token
)
530 .filter(|t
| t
.kind() == T
![,])
531 .take_while(|t
| t
.text_range().start() <= token
.text_range().start())
534 let mut res
= SignatureHelp
{
536 signature
: String
::new(),
538 active_parameter
: Some(active_parameter
),
544 let path_res
= sema
.resolve_path(path
)?
;
545 if let PathResolution
::Def(ModuleDef
::Variant(variant
)) = path_res
{
546 fields
= variant
.fields(db
);
547 let en
= variant
.parent_enum(db
);
549 res
.doc
= en
.docs(db
).map(|it
| it
.into());
553 en
.name(db
).display(db
),
554 variant
.name(db
).display(db
)
557 let adt
= match path_res
{
558 PathResolution
::SelfType(imp
) => imp
.self_ty(db
).as_adt()?
,
559 PathResolution
::Def(ModuleDef
::Adt(adt
)) => adt
,
564 hir
::Adt
::Struct(it
) => {
565 fields
= it
.fields(db
);
566 res
.doc
= it
.docs(db
).map(|it
| it
.into());
567 format_to
!(res
.signature
, "struct {} {{ ", it
.name(db
).display(db
));
569 hir
::Adt
::Union(it
) => {
570 fields
= it
.fields(db
);
571 res
.doc
= it
.docs(db
).map(|it
| it
.into());
572 format_to
!(res
.signature
, "union {} {{ ", it
.name(db
).display(db
));
579 fields
.into_iter().map(|field
| (field
.name(db
), Some(field
))).collect
::<FxIndexMap
<_
, _
>>();
580 let mut buf
= String
::new();
581 for (field
, ty
) in fields2
{
582 let name
= field
.name(db
);
583 format_to
!(buf
, "{}: {}", name
.display(db
), ty
.display_truncated(db
, Some(20)));
584 res
.push_record_field(&buf
);
587 if let Some(field
) = fields
.get_mut(&name
) {
591 for (name
, field
) in fields
{
592 let Some(field
) = field
else { continue }
;
593 format_to
!(buf
, "{}: {}", name
.display(db
), field
.ty(db
).display_truncated(db
, Some(20)));
594 res
.push_record_field(&buf
);
597 res
.signature
.push_str(" }");
601 fn signature_help_for_tuple_pat_ish(
603 mut res
: SignatureHelp
,
606 mut field_pats
: AstChildren
<ast
::Pat
>,
607 fields
: impl ExactSizeIterator
<Item
= hir
::Type
>,
609 let rest_pat
= field_pats
.find(|it
| matches
!(it
, ast
::Pat
::RestPat(_
)));
610 let is_left_of_rest_pat
=
611 rest_pat
.map_or(true, |it
| token
.text_range().start() < it
.syntax().text_range().end());
614 .children_with_tokens()
615 .filter_map(NodeOrToken
::into_token
)
616 .filter(|t
| t
.kind() == T
![,]);
618 res
.active_parameter
= {
619 Some(if is_left_of_rest_pat
{
620 commas
.take_while(|t
| t
.text_range().start() <= token
.text_range().start()).count()
622 let n_commas
= commas
626 .take_while(|t
| t
.text_range().start() > token
.text_range().start())
628 fields
.len().saturating_sub(1).saturating_sub(n_commas
)
632 let mut buf
= String
::new();
634 format_to
!(buf
, "{}", ty
.display_truncated(db
, Some(20)));
635 res
.push_call_param(&buf
);
638 res
.signature
.push_str(")");
645 use expect_test
::{expect, Expect}
;
646 use ide_db
::base_db
::{fixture::ChangeFixture, FilePosition}
;
649 use crate::RootDatabase
;
651 /// Creates analysis from a multi-file fixture, returns positions marked with $0.
652 pub(crate) fn position(ra_fixture
: &str) -> (RootDatabase
, FilePosition
) {
653 let change_fixture
= ChangeFixture
::parse(ra_fixture
);
654 let mut database
= RootDatabase
::default();
655 database
.apply_change(change_fixture
.change
);
656 let (file_id
, range_or_offset
) =
657 change_fixture
.file_position
.expect("expected a marker ($0)");
658 let offset
= range_or_offset
.expect_offset();
659 (database
, FilePosition { file_id, offset }
)
663 fn check(ra_fixture
: &str, expect
: Expect
) {
664 let fixture
= format
!(
666 //- minicore: sized, fn
670 let (db
, position
) = position(&fixture
);
671 let sig_help
= crate::signature_help
::signature_help(&db
, position
);
672 let actual
= match sig_help
{
674 let mut rendered
= String
::new();
675 if let Some(docs
) = &sig_help
.doc
{
676 format_to
!(rendered
, "{}\n------\n", docs
.as_str());
678 format_to
!(rendered
, "{}\n", sig_help
.signature
);
680 for (i
, range
) in sig_help
.parameter_ranges().iter().enumerate() {
681 let is_active
= sig_help
.active_parameter
== Some(i
);
683 let start
= u32::from(range
.start());
684 let gap
= start
.checked_sub(offset
).unwrap_or_else(|| {
685 panic
!("parameter ranges out of order: {:?}", sig_help
.parameter_ranges())
687 rendered
.extend(iter
::repeat(' '
).take(gap
as usize));
688 let param_text
= &sig_help
.signature
[*range
];
689 let width
= param_text
.chars().count(); // …
690 let marker
= if is_active { '^' }
else { '-' }
;
691 rendered
.extend(iter
::repeat(marker
).take(width
));
692 offset
+= gap
+ u32::from(range
.len());
694 if !sig_help
.parameter_ranges().is_empty() {
695 format_to
!(rendered
, "\n");
699 None
=> String
::new(),
701 expect
.assert_eq(&actual
);
705 fn test_fn_signature_two_args() {
708 fn foo(x: u32, y: u32) -> u32 {x + y}
709 fn bar() { foo($03, ); }
712 fn foo(x: u32, y: u32) -> u32
718 fn foo(x: u32, y: u32) -> u32 {x + y}
719 fn bar() { foo(3$0, ); }
722 fn foo(x: u32, y: u32) -> u32
728 fn foo(x: u32, y: u32) -> u32 {x + y}
729 fn bar() { foo(3,$0 ); }
732 fn foo(x: u32, y: u32) -> u32
738 fn foo(x: u32, y: u32) -> u32 {x + y}
739 fn bar() { foo(3, $0); }
742 fn foo(x: u32, y: u32) -> u32
749 fn test_fn_signature_two_args_empty() {
752 fn foo(x: u32, y: u32) -> u32 {x + y}
753 fn bar() { foo($0); }
756 fn foo(x: u32, y: u32) -> u32
763 fn test_fn_signature_two_args_first_generics() {
766 fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
767 where T: Copy + Display, U: Debug
770 fn bar() { foo($03, ); }
773 fn foo(x: i32, y: U) -> u32
780 fn test_fn_signature_no_params() {
783 fn foo<T>() -> T where T: Copy + Display {}
784 fn bar() { foo($0); }
793 fn test_fn_signature_for_impl() {
797 impl F { pub fn new() { } }
799 let _ : F = F::new($0);
809 fn test_fn_signature_for_method_self() {
813 impl S { pub fn do_it(&self) {} }
827 fn test_fn_signature_for_method_with_arg() {
832 fn foo(&self, x: i32) {}
835 fn main() { S.foo($0); }
838 fn foo(&self, x: i32)
845 fn test_fn_signature_for_generic_method() {
850 fn foo(&self, x: T) {}
853 fn main() { S(1u32).foo($0); }
856 fn foo(&self, x: u32)
863 fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
868 fn foo(&self, x: i32) {}
871 fn main() { S::foo($0); }
874 fn foo(self: &S, x: i32)
881 fn test_fn_signature_with_docs_simple() {
886 fn foo(j: u32) -> u32 {
897 fn foo(j: u32) -> u32
904 fn test_fn_signature_with_docs() {
907 /// Adds one to the number given.
914 /// assert_eq!(6, my_crate::add_one(5));
916 pub fn add_one(x: i32) -> i32 {
924 Adds one to the number given.
931 assert_eq!(6, my_crate::add_one(5));
934 fn add_one(x: i32) -> i32
941 fn test_fn_signature_with_docs_impl() {
946 /// Adds one to the number given.
953 /// assert_eq!(6, my_crate::add_one(5));
955 pub fn add_one(x: i32) -> i32 {
966 Adds one to the number given.
973 assert_eq!(6, my_crate::add_one(5));
976 fn add_one(x: i32) -> i32
983 fn test_fn_signature_with_docs_from_actix() {
987 /// Actor execution context type
990 trait WriteHandler<E>
994 /// Method is called when writer finishes.
996 /// By default this method stops actor's `Context`.
997 fn finished(&mut self, ctx: &mut Self::Context) {}
1000 fn foo(mut r: impl WriteHandler<()>) {
1005 Method is called when writer finishes.
1007 By default this method stops actor's `Context`.
1009 fn finished(&mut self, ctx: &mut <impl WriteHandler<()> as Actor>::Context)
1010 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1016 fn call_info_bad_offset() {
1019 fn foo(x: u32, y: u32) -> u32 {x + y}
1020 fn bar() { foo $0 (3, ); }
1027 fn outside_of_arg_list() {
1048 fn foo(a: u8) -> u8 {a}
1049 fn bar(a: u8) -> u8 {a}
1064 let _: Vec2<Vec<u8>$0>
1075 fn test_nested_method_in_lambda() {
1079 impl Foo { fn bar(&self, _: u32) { } }
1085 std::thread::spawn(move || foo.bar($0));
1089 fn bar(&self, _: u32)
1096 fn works_for_tuple_structs() {
1099 /// A cool tuple struct
1115 fn tuple_struct_pat() {
1118 /// A cool tuple struct
1134 fn tuple_struct_pat_rest() {
1137 /// A cool tuple struct
1138 struct S(u32, i32, f32, u16);
1146 struct S (u32, i32, f32, u16)
1152 /// A cool tuple struct
1153 struct S(u32, i32, f32, u16, u8);
1155 let S(0, .., $0, 0);
1161 struct S (u32, i32, f32, u16, u8)
1167 /// A cool tuple struct
1168 struct S(u32, i32, f32, u16);
1176 struct S (u32, i32, f32, u16)
1182 /// A cool tuple struct
1183 struct S(u32, i32, f32, u16, u8);
1185 let S(1, .., 1, $0, 2);
1191 struct S (u32, i32, f32, u16, u8)
1197 /// A cool tuple struct
1198 struct S(u32, i32, f32, u16);
1206 struct S (u32, i32, f32, u16)
1212 /// A cool tuple struct
1213 struct S(u32, i32, f32, u16);
1221 struct S (u32, i32, f32, u16)
1228 fn generic_struct() {
1244 fn works_for_enum_variants() {
1253 C { a: i32, b: i32 }
1270 fn cant_call_struct_record() {
1273 struct S { x: u32, y: i32 }
1283 fn cant_call_enum_record() {
1292 C { a: i32, b: i32 }
1304 fn fn_signature_for_call_in_macro() {
1307 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1310 fn bar() { foo($0); }
1320 fn fn_signature_for_method_call_defined_in_macro() {
1323 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1327 fn foo<'a>(&'a mut self) {}
1330 fn test() { S.foo($0); }
1333 fn foo(&'a mut self)
1339 fn call_info_for_lambdas() {
1343 fn foo(s: S) -> i32 { 92 }
1356 fn call_info_for_fn_def_over_reference() {
1360 fn foo(s: S) -> i32 { 92 }
1374 fn call_info_for_fn_ptr() {
1377 fn main(f: fn(i32, f64) -> char) {
1389 fn call_info_for_unclosed_call() {
1392 fn foo(foo: u32, bar: u32) {}
1397 fn foo(foo: u32, bar: u32)
1401 // check with surrounding space
1404 fn foo(foo: u32, bar: u32) {}
1409 fn foo(foo: u32, bar: u32)
1416 fn test_multiline_argument() {
1419 fn callee(a: u8, b: u8) {}
1429 fn callee(a: u8, b: u8) {}
1436 fn callee(a: u8, b: u8)
1442 fn callee(a: u8, b: u8) {}
1449 fn callee(a: u8, b: u8)
1456 fn test_generics_simple() {
1479 fn test_generics_on_variant() {
1506 fn test_lots_of_generics() {
1514 fn f<G, H>(g: G, h: impl Tr<G>) where G: Tr<()> {}
1529 fn test_generics_in_trait_ufcs() {
1552 fn test_generics_in_method_call() {
1573 fn test_generic_param_in_method_call() {
1578 fn test<V>(&mut self, val: V) {}
1585 fn test(&mut self, val: V)
1592 fn test_generic_kinds() {
1595 fn callee<'a, const A: u8, T, const C: u8>() {}
1598 callee::<'static, $0
1602 fn callee<'a, const A: u8, T, const C: u8>
1603 -- ^^^^^^^^^^^ - -----------
1608 fn callee<'a, const A: u8, T, const C: u8>() {}
1611 callee::<NON_LIFETIME$0
1615 fn callee<'a, const A: u8, T, const C: u8>
1616 -- ^^^^^^^^^^^ - -----------
1622 fn test_trait_assoc_types() {
1625 trait Trait<'a, T> {
1628 fn f() -> impl Trait<(), $0
1631 trait Trait<'a, T, Assoc = …>
1640 fn f() -> impl Iterator<$0
1643 trait Iterator<Item = …>
1652 fn f() -> impl Iterator<Item = $0
1655 trait Iterator<Item = …>
1665 fn f() -> impl Tr<$0
1668 trait Tr<A = …, B = …>
1678 fn f() -> impl Tr<B$0
1681 trait Tr<A = …, B = …>
1691 fn f() -> impl Tr<B = $0
1694 trait Tr<B = …, A = …>
1704 fn f() -> impl Tr<B = (), $0
1707 trait Tr<B = …, A = …>
1714 fn test_supertrait_assoc() {
1720 trait Sub: Super + Super {
1723 fn f() -> impl Sub<$0
1726 trait Sub<SubTy = …, SuperTy = …>
1727 ^^^^^^^^^ -----------
1733 fn no_assoc_types_outside_type_bounds() {
1751 // FIXME: Substitute type vars in impl trait (`U` -> `i8`)
1756 fn foo<U>(x: Wrap<impl Trait<U>>) {}
1762 fn foo(x: Wrap<impl Trait<U>>)
1763 ^^^^^^^^^^^^^^^^^^^^^^
1769 fn fully_qualified_syntax() {
1773 trait A { fn foo(&self, other: Self); }
1774 A::foo(&self$0, other);
1778 fn foo(self: &Self, other: Self)
1779 ^^^^^^^^^^^ -----------
1785 fn help_for_generic_call() {
1788 fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
1799 fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
1811 fn regression_13579() {
1820 ) -> impl Fn() -> C {
1831 fn record_literal() {
1834 struct Strukt<T, U = ()> {
1847 struct Strukt { u: i32, t: T, unit: () }
1848 ------ ^^^^ --------
1854 fn record_literal_nonexistent_field() {
1868 struct Strukt { a: u8 }
1875 fn tuple_variant_record_literal() {
1886 enum Opt::Some { 0: u8 }
1900 enum Opt::Some { 0: u8 }
1907 fn record_literal_self() {
1928 struct Strukt<T, U = ()> {
1941 struct Strukt { u: i32, t: T, unit: () }
1942 ------ ^^^^ --------
1948 fn test_enum_in_nested_method_in_lambda() {
1960 std::thread::spawn(move || { bar(A:$0) } );
1971 fn test_tuple_expr_free() {
2019 fn test_tuple_expr_expected() {
2023 let _: (&str, u32, u32)= ($0, 1, 3);
2031 // FIXME: Should typeck report a 4-ary tuple for the expression here?
2035 let _: (&str, u32, u32, u32) = ($0, 1, 3);
2046 let _: (&str, u32, u32)= ($0, 1, 3, 5);
2050 (&str, u32, u32, i32)
2057 fn test_tuple_pat_free() {
2065 ({unknown}, i32, i32)
2130 // FIXME: This is wrong, this should not mark the last as active
2139 fn test_tuple_pat_expected() {
2143 let (0$0, 1, 3): (i32, i32, i32);
2154 let ($0, 1, 3): (i32, i32, i32);
2165 let (1, 3 $0): (i32,);
2176 let (1, 3 $0, ..): (i32, i32, i32, i32);
2180 (i32, i32, i32, i32)
2187 let (1, 3, .., $0): (i32, i32, i32);
2197 fn test_tuple_pat_expected_inferred() {
2201 let (0$0, 1, 3) = (1, 2 ,3);
2212 let ($0 1, 3) = (1, 2, 3);
2215 // FIXME: Should typeck report a 3-ary tuple for the pattern here?
2224 let (1, 3 $0) = (1,);
2235 let (1, 3 $0, ..) = (1, 2, 3, 4);
2239 (i32, i32, i32, i32)
2246 let (1, 3, .., $0) = (1, 2, 3);