10
10
//! resolved to the search element definition, we get a reference.
11
11
12
12
mod rename;
13
- mod search_scope;
14
13
15
14
use hir:: Semantics ;
16
- use once_cell:: unsync:: Lazy ;
17
- use ra_db:: SourceDatabaseExt ;
18
15
use ra_ide_db:: {
19
16
defs:: { classify_name, classify_name_ref, Definition } ,
17
+ search:: SearchScope ,
20
18
RootDatabase ,
21
19
} ;
22
20
use ra_prof:: profile;
23
21
use ra_syntax:: {
24
22
algo:: find_node_at_offset,
25
23
ast:: { self , NameOwner } ,
26
- match_ast , AstNode , SyntaxKind , SyntaxNode , TextRange , TextUnit , TokenAtOffset ,
24
+ AstNode , SyntaxKind , SyntaxNode , TextRange , TokenAtOffset ,
27
25
} ;
28
- use test_utils:: tested_by;
29
26
30
27
use crate :: { display:: TryToNav , FilePosition , FileRange , NavigationTarget , RangeInfo } ;
31
28
32
29
pub ( crate ) use self :: rename:: rename;
33
30
34
- pub use self :: search_scope :: SearchScope ;
31
+ pub use ra_ide_db :: search :: { Reference , ReferenceAccess , ReferenceKind } ;
35
32
36
33
#[ derive( Debug , Clone ) ]
37
34
pub struct ReferenceSearchResult {
@@ -46,25 +43,6 @@ pub struct Declaration {
46
43
pub access : Option < ReferenceAccess > ,
47
44
}
48
45
49
- #[ derive( Debug , Clone ) ]
50
- pub struct Reference {
51
- pub file_range : FileRange ,
52
- pub kind : ReferenceKind ,
53
- pub access : Option < ReferenceAccess > ,
54
- }
55
-
56
- #[ derive( Debug , Clone , PartialEq ) ]
57
- pub enum ReferenceKind {
58
- StructLiteral ,
59
- Other ,
60
- }
61
-
62
- #[ derive( Debug , Copy , Clone , PartialEq ) ]
63
- pub enum ReferenceAccess {
64
- Read ,
65
- Write ,
66
- }
67
-
68
46
impl ReferenceSearchResult {
69
47
pub fn declaration ( & self ) -> & Declaration {
70
48
& self . declaration
@@ -125,7 +103,8 @@ pub(crate) fn find_all_refs(
125
103
126
104
let RangeInfo { range, info : def } = find_name ( & sema, & syntax, position, opt_name) ?;
127
105
128
- let references = find_refs_to_def ( db, & def, search_scope)
106
+ let references = def
107
+ . find_usages ( db, search_scope)
129
108
. into_iter ( )
130
109
. filter ( |r| search_kind == ReferenceKind :: Other || search_kind == r. kind )
131
110
. collect ( ) ;
@@ -141,27 +120,6 @@ pub(crate) fn find_all_refs(
141
120
Some ( RangeInfo :: new ( range, ReferenceSearchResult { declaration, references } ) )
142
121
}
143
122
144
- pub ( crate ) fn find_refs_to_def (
145
- db : & RootDatabase ,
146
- def : & Definition ,
147
- search_scope : Option < SearchScope > ,
148
- ) -> Vec < Reference > {
149
- let search_scope = {
150
- let base = SearchScope :: for_def ( & def, db) ;
151
- match search_scope {
152
- None => base,
153
- Some ( scope) => base. intersection ( & scope) ,
154
- }
155
- } ;
156
-
157
- let name = match def. name ( db) {
158
- None => return Vec :: new ( ) ,
159
- Some ( it) => it. to_string ( ) ,
160
- } ;
161
-
162
- process_definition ( db, def, name, search_scope)
163
- }
164
-
165
123
fn find_name (
166
124
sema : & Semantics < RootDatabase > ,
167
125
syntax : & SyntaxNode ,
@@ -179,72 +137,6 @@ fn find_name(
179
137
Some ( RangeInfo :: new ( range, def) )
180
138
}
181
139
182
- fn process_definition (
183
- db : & RootDatabase ,
184
- def : & Definition ,
185
- name : String ,
186
- scope : SearchScope ,
187
- ) -> Vec < Reference > {
188
- let _p = profile ( "process_definition" ) ;
189
-
190
- let pat = name. as_str ( ) ;
191
- let mut refs = vec ! [ ] ;
192
-
193
- for ( file_id, search_range) in scope {
194
- let text = db. file_text ( file_id) ;
195
- let search_range =
196
- search_range. unwrap_or ( TextRange :: offset_len ( 0 . into ( ) , TextUnit :: of_str ( & text) ) ) ;
197
-
198
- let sema = Semantics :: new ( db) ;
199
- let tree = Lazy :: new ( || sema. parse ( file_id) . syntax ( ) . clone ( ) ) ;
200
-
201
- for ( idx, _) in text. match_indices ( pat) {
202
- let offset = TextUnit :: from_usize ( idx) ;
203
- if !search_range. contains_inclusive ( offset) {
204
- tested_by ! ( search_filters_by_range) ;
205
- continue ;
206
- }
207
-
208
- let name_ref =
209
- if let Some ( name_ref) = find_node_at_offset :: < ast:: NameRef > ( & tree, offset) {
210
- name_ref
211
- } else {
212
- // Handle macro token cases
213
- let token = match tree. token_at_offset ( offset) {
214
- TokenAtOffset :: None => continue ,
215
- TokenAtOffset :: Single ( t) => t,
216
- TokenAtOffset :: Between ( _, t) => t,
217
- } ;
218
- let expanded = sema. descend_into_macros ( token) ;
219
- match ast:: NameRef :: cast ( expanded. parent ( ) ) {
220
- Some ( name_ref) => name_ref,
221
- _ => continue ,
222
- }
223
- } ;
224
-
225
- if let Some ( d) = classify_name_ref ( & sema, & name_ref) {
226
- let d = d. definition ( ) ;
227
- if & d == def {
228
- let kind =
229
- if is_record_lit_name_ref ( & name_ref) || is_call_expr_name_ref ( & name_ref) {
230
- ReferenceKind :: StructLiteral
231
- } else {
232
- ReferenceKind :: Other
233
- } ;
234
-
235
- let file_range = sema. original_range ( name_ref. syntax ( ) ) ;
236
- refs. push ( Reference {
237
- file_range,
238
- kind,
239
- access : reference_access ( & d, & name_ref) ,
240
- } ) ;
241
- }
242
- }
243
- }
244
- }
245
- refs
246
- }
247
-
248
140
fn decl_access ( def : & Definition , syntax : & SyntaxNode , range : TextRange ) -> Option < ReferenceAccess > {
249
141
match def {
250
142
Definition :: Local ( _) | Definition :: StructField ( _) => { }
@@ -264,48 +156,6 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio
264
156
None
265
157
}
266
158
267
- fn reference_access ( def : & Definition , name_ref : & ast:: NameRef ) -> Option < ReferenceAccess > {
268
- // Only Locals and Fields have accesses for now.
269
- match def {
270
- Definition :: Local ( _) | Definition :: StructField ( _) => { }
271
- _ => return None ,
272
- } ;
273
-
274
- let mode = name_ref. syntax ( ) . ancestors ( ) . find_map ( |node| {
275
- match_ast ! {
276
- match ( node) {
277
- ast:: BinExpr ( expr) => {
278
- if expr. op_kind( ) ?. is_assignment( ) {
279
- // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
280
- // FIXME: This is not terribly accurate.
281
- if let Some ( lhs) = expr. lhs( ) {
282
- if lhs. syntax( ) . text_range( ) . end( ) == name_ref. syntax( ) . text_range( ) . end( ) {
283
- return Some ( ReferenceAccess :: Write ) ;
284
- }
285
- }
286
- }
287
- Some ( ReferenceAccess :: Read )
288
- } ,
289
- _ => { None }
290
- }
291
- }
292
- } ) ;
293
-
294
- // Default Locals and Fields to read
295
- mode. or ( Some ( ReferenceAccess :: Read ) )
296
- }
297
-
298
- fn is_record_lit_name_ref ( name_ref : & ast:: NameRef ) -> bool {
299
- name_ref
300
- . syntax ( )
301
- . ancestors ( )
302
- . find_map ( ast:: RecordLit :: cast)
303
- . and_then ( |l| l. path ( ) )
304
- . and_then ( |p| p. segment ( ) )
305
- . map ( |p| p. name_ref ( ) . as_ref ( ) == Some ( name_ref) )
306
- . unwrap_or ( false )
307
- }
308
-
309
159
fn get_struct_def_name_for_struc_litetal_search (
310
160
syntax : & SyntaxNode ,
311
161
position : FilePosition ,
@@ -324,20 +174,6 @@ fn get_struct_def_name_for_struc_litetal_search(
324
174
None
325
175
}
326
176
327
- fn is_call_expr_name_ref ( name_ref : & ast:: NameRef ) -> bool {
328
- name_ref
329
- . syntax ( )
330
- . ancestors ( )
331
- . find_map ( ast:: CallExpr :: cast)
332
- . and_then ( |c| match c. expr ( ) ? {
333
- ast:: Expr :: PathExpr ( p) => {
334
- Some ( p. path ( ) ?. segment ( ) ?. name_ref ( ) . as_ref ( ) == Some ( name_ref) )
335
- }
336
- _ => None ,
337
- } )
338
- . unwrap_or ( false )
339
- }
340
-
341
177
#[ cfg( test) ]
342
178
mod tests {
343
179
use test_utils:: covers;
@@ -451,7 +287,7 @@ mod tests {
451
287
452
288
#[ test]
453
289
fn search_filters_by_range ( ) {
454
- covers ! ( search_filters_by_range) ;
290
+ covers ! ( ra_ide_db :: search_filters_by_range) ;
455
291
let code = r#"
456
292
fn foo() {
457
293
let spam<|> = 92;
@@ -767,7 +603,10 @@ mod tests {
767
603
fn check_result ( res : ReferenceSearchResult , expected_decl : & str , expected_refs : & [ & str ] ) {
768
604
res. declaration ( ) . assert_match ( expected_decl) ;
769
605
assert_eq ! ( res. references. len( ) , expected_refs. len( ) ) ;
770
- res. references ( ) . iter ( ) . enumerate ( ) . for_each ( |( i, r) | r. assert_match ( expected_refs[ i] ) ) ;
606
+ res. references ( )
607
+ . iter ( )
608
+ . enumerate ( )
609
+ . for_each ( |( i, r) | ref_assert_match ( r, expected_refs[ i] ) ) ;
771
610
}
772
611
773
612
impl Declaration {
@@ -785,21 +624,16 @@ mod tests {
785
624
}
786
625
}
787
626
788
- impl Reference {
789
- fn debug_render ( & self ) -> String {
790
- let mut s = format ! (
791
- "{:?} {:?} {:?}" ,
792
- self . file_range. file_id, self . file_range. range, self . kind
793
- ) ;
794
- if let Some ( access) = self . access {
795
- s. push_str ( & format ! ( " {:?}" , access) ) ;
796
- }
797
- s
627
+ fn ref_debug_render ( r : & Reference ) -> String {
628
+ let mut s = format ! ( "{:?} {:?} {:?}" , r. file_range. file_id, r. file_range. range, r. kind) ;
629
+ if let Some ( access) = r. access {
630
+ s. push_str ( & format ! ( " {:?}" , access) ) ;
798
631
}
632
+ s
633
+ }
799
634
800
- fn assert_match ( & self , expected : & str ) {
801
- let actual = self . debug_render ( ) ;
802
- test_utils:: assert_eq_text!( expected. trim( ) , actual. trim( ) , ) ;
803
- }
635
+ fn ref_assert_match ( r : & Reference , expected : & str ) {
636
+ let actual = ref_debug_render ( r) ;
637
+ test_utils:: assert_eq_text!( expected. trim( ) , actual. trim( ) , ) ;
804
638
}
805
639
}
0 commit comments