44use either:: Either ;
55use hir:: { HasAttrs , HirDisplay , Semantics } ;
66use ide_db:: {
7- active_parameter:: { callable_for_token , generics_for_token} ,
7+ active_parameter:: { callable_for_node , generics_for_token} ,
88 base_db:: FilePosition ,
99} ;
1010use stdx:: format_to;
11- use syntax:: { algo, AstNode , Direction , TextRange , TextSize } ;
11+ use syntax:: {
12+ algo,
13+ ast:: { self , HasArgList } ,
14+ AstNode , Direction , SyntaxToken , TextRange , TextSize ,
15+ } ;
1216
1317use crate :: RootDatabase ;
1418
@@ -65,8 +69,8 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
6569 . and_then ( |tok| algo:: skip_trivia_token ( tok, Direction :: Prev ) ) ?;
6670 let token = sema. descend_into_macros_single ( token) ;
6771
68- if let Some ( ( callable , active_parameter ) ) = callable_for_token ( & sema, token. clone ( ) ) {
69- return Some ( signature_help_for_callable ( db , callable , active_parameter ) ) ;
72+ if let Some ( help ) = signature_help_for_call ( & sema, & token) {
73+ return Some ( help ) ;
7074 }
7175
7276 if let Some ( ( generic_def, active_parameter) ) = generics_for_token ( & sema, token. clone ( ) ) {
@@ -76,14 +80,39 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
7680 None
7781}
7882
79- fn signature_help_for_callable (
80- db : & RootDatabase ,
81- callable : hir:: Callable ,
82- active_parameter : Option < usize > ,
83- ) -> SignatureHelp {
83+ fn signature_help_for_call (
84+ sema : & Semantics < RootDatabase > ,
85+ token : & SyntaxToken ,
86+ ) -> Option < SignatureHelp > {
87+ // Find the calling expression and its NameRef
88+ let mut node = token. parent ( ) ?;
89+ let calling_node = loop {
90+ if let Some ( callable) = ast:: CallableExpr :: cast ( node. clone ( ) ) {
91+ if callable
92+ . arg_list ( )
93+ . map_or ( false , |it| it. syntax ( ) . text_range ( ) . contains ( token. text_range ( ) . start ( ) ) )
94+ {
95+ break callable;
96+ }
97+ }
98+
99+ // Stop at multi-line expressions, since the signature of the outer call is not very
100+ // helpful inside them.
101+ if let Some ( expr) = ast:: Expr :: cast ( node. clone ( ) ) {
102+ if expr. syntax ( ) . text ( ) . contains_char ( '\n' ) {
103+ return None ;
104+ }
105+ }
106+
107+ node = node. parent ( ) ?;
108+ } ;
109+
110+ let ( callable, active_parameter) = callable_for_node ( sema, & calling_node, token) ?;
111+
84112 let mut res =
85113 SignatureHelp { doc : None , signature : String :: new ( ) , parameters : vec ! [ ] , active_parameter } ;
86114
115+ let db = sema. db ;
87116 match callable. kind ( ) {
88117 hir:: CallableKind :: Function ( func) => {
89118 res. doc = func. docs ( db) . map ( |it| it. into ( ) ) ;
@@ -134,7 +163,7 @@ fn signature_help_for_callable(
134163 }
135164 hir:: CallableKind :: TupleStruct ( _) | hir:: CallableKind :: TupleEnumVariant ( _) => { }
136165 }
137- res
166+ Some ( res)
138167}
139168
140169fn signature_help_for_generics (
@@ -786,6 +815,46 @@ fn main() {
786815 )
787816 }
788817
818+ #[ test]
819+ fn test_multiline_argument ( ) {
820+ check (
821+ r#"
822+ fn callee(a: u8, b: u8) {}
823+ fn main() {
824+ callee(match 0 {
825+ 0 => 1,$0
826+ })
827+ }"# ,
828+ expect ! [ [ r#""# ] ] ,
829+ ) ;
830+ check (
831+ r#"
832+ fn callee(a: u8, b: u8) {}
833+ fn main() {
834+ callee(match 0 {
835+ 0 => 1,
836+ },$0)
837+ }"# ,
838+ expect ! [ [ r#"
839+ fn callee(a: u8, b: u8)
840+ ----- ^^^^^
841+ "# ] ] ,
842+ ) ;
843+ check (
844+ r#"
845+ fn callee(a: u8, b: u8) {}
846+ fn main() {
847+ callee($0match 0 {
848+ 0 => 1,
849+ })
850+ }"# ,
851+ expect ! [ [ r#"
852+ fn callee(a: u8, b: u8)
853+ ^^^^^ -----
854+ "# ] ] ,
855+ ) ;
856+ }
857+
789858 #[ test]
790859 fn test_generics_simple ( ) {
791860 check (
0 commit comments