4
4
use either:: Either ;
5
5
use hir:: { HasAttrs , HirDisplay , Semantics } ;
6
6
use ide_db:: {
7
- active_parameter:: { callable_for_token , generics_for_token} ,
7
+ active_parameter:: { callable_for_node , generics_for_token} ,
8
8
base_db:: FilePosition ,
9
9
} ;
10
10
use 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
+ } ;
12
16
13
17
use crate :: RootDatabase ;
14
18
@@ -65,8 +69,8 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
65
69
. and_then ( |tok| algo:: skip_trivia_token ( tok, Direction :: Prev ) ) ?;
66
70
let token = sema. descend_into_macros_single ( token) ;
67
71
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 ) ;
70
74
}
71
75
72
76
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
76
80
None
77
81
}
78
82
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
+
84
112
let mut res =
85
113
SignatureHelp { doc : None , signature : String :: new ( ) , parameters : vec ! [ ] , active_parameter } ;
86
114
115
+ let db = sema. db ;
87
116
match callable. kind ( ) {
88
117
hir:: CallableKind :: Function ( func) => {
89
118
res. doc = func. docs ( db) . map ( |it| it. into ( ) ) ;
@@ -134,7 +163,7 @@ fn signature_help_for_callable(
134
163
}
135
164
hir:: CallableKind :: TupleStruct ( _) | hir:: CallableKind :: TupleEnumVariant ( _) => { }
136
165
}
137
- res
166
+ Some ( res)
138
167
}
139
168
140
169
fn signature_help_for_generics (
@@ -786,6 +815,46 @@ fn main() {
786
815
)
787
816
}
788
817
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
+
789
858
#[ test]
790
859
fn test_generics_simple ( ) {
791
860
check (
0 commit comments