@@ -85,17 +85,20 @@ impl SyntaxRange {
8585#[ derive( Encodable , Decodable , Debug , Clone ) ]
8686crate struct CallLocation {
8787 crate call_expr : SyntaxRange ,
88+ crate call_ident : SyntaxRange ,
8889 crate enclosing_item : SyntaxRange ,
8990}
9091
9192impl CallLocation {
9293 fn new (
9394 expr_span : rustc_span:: Span ,
95+ ident_span : rustc_span:: Span ,
9496 enclosing_item_span : rustc_span:: Span ,
9597 source_file : & SourceFile ,
9698 ) -> Self {
9799 CallLocation {
98100 call_expr : SyntaxRange :: new ( expr_span, source_file) ,
101+ call_ident : SyntaxRange :: new ( ident_span, source_file) ,
99102 enclosing_item : SyntaxRange :: new ( enclosing_item_span, source_file) ,
100103 }
101104 }
@@ -146,24 +149,39 @@ where
146149 }
147150
148151 // Get type of function if expression is a function call
149- let ( ty, span ) = match ex. kind {
152+ let ( ty, call_span , ident_span ) = match ex. kind {
150153 hir:: ExprKind :: Call ( f, _) => {
151154 let types = tcx. typeck ( ex. hir_id . owner ) ;
152155
153156 if let Some ( ty) = types. node_type_opt ( f. hir_id ) {
154- ( ty, ex. span )
157+ ( ty, ex. span , f . span )
155158 } else {
156159 trace ! ( "node_type_opt({}) = None" , f. hir_id) ;
157160 return ;
158161 }
159162 }
160- hir:: ExprKind :: MethodCall ( _, _ , span ) => {
163+ hir:: ExprKind :: MethodCall ( _, args , call_span ) => {
161164 let types = tcx. typeck ( ex. hir_id . owner ) ;
162165 let Some ( def_id) = types. type_dependent_def_id ( ex. hir_id ) else {
163166 trace ! ( "type_dependent_def_id({}) = None" , ex. hir_id) ;
164167 return ;
165168 } ;
166- ( tcx. type_of ( def_id) , span)
169+
170+ // The MethodCall node doesn't directly contain a span for the
171+ // method identifier, so we have to compute it by trimming the full
172+ // span based on the arguments.
173+ let ident_span = match args. get ( 1 ) {
174+ // If there is an argument, e.g. "f(x)", then
175+ // get the span "f(" and delete the lparen.
176+ Some ( arg) => {
177+ let with_paren = call_span. until ( arg. span ) ;
178+ with_paren. with_hi ( with_paren. hi ( ) - BytePos ( 1 ) )
179+ }
180+ // Otherwise, just delete both parens directly.
181+ None => call_span. with_hi ( call_span. hi ( ) - BytePos ( 2 ) ) ,
182+ } ;
183+
184+ ( tcx. type_of ( def_id) , call_span, ident_span)
167185 }
168186 _ => {
169187 return ;
@@ -172,8 +190,8 @@ where
172190
173191 // If this span comes from a macro expansion, then the source code may not actually show
174192 // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
175- if span . from_expansion ( ) {
176- trace ! ( "Rejecting expr from macro: {:?}" , span ) ;
193+ if call_span . from_expansion ( ) {
194+ trace ! ( "Rejecting expr from macro: {:?}" , call_span ) ;
177195 return ;
178196 }
179197
@@ -183,26 +201,29 @@ where
183201 . hir ( )
184202 . span_with_body ( tcx. hir ( ) . local_def_id_to_hir_id ( tcx. hir ( ) . get_parent_item ( ex. hir_id ) ) ) ;
185203 if enclosing_item_span. from_expansion ( ) {
186- trace ! ( "Rejecting expr ({:?}) from macro item: {:?}" , span , enclosing_item_span) ;
204+ trace ! ( "Rejecting expr ({:?}) from macro item: {:?}" , call_span , enclosing_item_span) ;
187205 return ;
188206 }
189207
190208 assert ! (
191- enclosing_item_span. contains( span) ,
192- "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call." ,
193- span,
194- enclosing_item_span
209+ enclosing_item_span. contains( call_span) ,
210+ "Attempted to scrape call at [{call_span:?}] whose enclosing item [{enclosing_item_span:?}] doesn't contain the span of the call." ,
211+ ) ;
212+
213+ assert ! (
214+ call_span. contains( ident_span) ,
215+ "Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was not contained in the span of the call."
195216 ) ;
196217
197218 // Save call site if the function resolves to a concrete definition
198219 if let ty:: FnDef ( def_id, _) = ty. kind ( ) {
199220 if self . target_crates . iter ( ) . all ( |krate| * krate != def_id. krate ) {
200- trace ! ( "Rejecting expr from crate not being documented: {:?}" , span ) ;
221+ trace ! ( "Rejecting expr from crate not being documented: {call_span :?}" ) ;
201222 return ;
202223 }
203224
204225 let source_map = tcx. sess . source_map ( ) ;
205- let file = source_map. lookup_char_pos ( span . lo ( ) ) . file ;
226+ let file = source_map. lookup_char_pos ( call_span . lo ( ) ) . file ;
206227 let file_path = match file. name . clone ( ) {
207228 FileName :: Real ( real_filename) => real_filename. into_local_path ( ) ,
208229 _ => None ,
@@ -212,20 +233,20 @@ where
212233 let abs_path = fs:: canonicalize ( file_path. clone ( ) ) . unwrap ( ) ;
213234 let cx = & self . cx ;
214235 let mk_call_data = || {
215- let clean_span = crate :: clean:: types:: Span :: new ( span ) ;
236+ let clean_span = crate :: clean:: types:: Span :: new ( call_span ) ;
216237 let url = cx. href_from_span ( clean_span, false ) . unwrap ( ) ;
217238 let display_name = file_path. display ( ) . to_string ( ) ;
218- let edition = span . edition ( ) ;
239+ let edition = call_span . edition ( ) ;
219240 CallData { locations : Vec :: new ( ) , url, display_name, edition }
220241 } ;
221242
222243 let fn_key = tcx. def_path_hash ( * def_id) ;
223244 let fn_entries = self . calls . entry ( fn_key) . or_default ( ) ;
224245
225- trace ! ( "Including expr: {:?}" , span ) ;
246+ trace ! ( "Including expr: {:?}" , call_span ) ;
226247 let enclosing_item_span =
227248 source_map. span_extend_to_prev_char ( enclosing_item_span, '\n' , false ) ;
228- let location = CallLocation :: new ( span , enclosing_item_span, & file) ;
249+ let location = CallLocation :: new ( call_span , ident_span , enclosing_item_span, & file) ;
229250 fn_entries. entry ( abs_path) . or_insert_with ( mk_call_data) . locations . push ( location) ;
230251 }
231252 }
0 commit comments