8
8
//! for text occurrences of the identifier. If there's an `ast::NameRef`
9
9
//! at the index that the match starts at and its tree parent is
10
10
//! resolved to the search element definition, we get a reference.
11
+ //!
12
+ //! Special handling for constructors/initializations:
13
+ //! When searching for references to a struct/enum/variant, if the cursor is positioned on:
14
+ //! - `{` after a struct/enum/variant definition
15
+ //! - `(` for tuple structs/variants
16
+ //! - `;` for unit structs
17
+ //! - The type name in a struct/enum/variant definition
18
+ //! Then only constructor/initialization usages will be shown, filtering out other references.
11
19
12
20
use hir:: { PathResolution , Semantics } ;
13
21
use ide_db:: {
@@ -28,27 +36,76 @@ use syntax::{
28
36
29
37
use crate :: { FilePosition , HighlightedRange , NavigationTarget , TryToNav , highlight_related} ;
30
38
39
+ /// Result of a reference search operation.
31
40
#[ derive( Debug , Clone ) ]
32
41
pub struct ReferenceSearchResult {
42
+ /// Information about the declaration site of the searched item.
43
+ /// For ADTs (structs/enums), this points to the type definition.
44
+ /// May be None for primitives or items without clear declaration sites.
33
45
pub declaration : Option < Declaration > ,
46
+ /// All references found, grouped by file.
47
+ /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),
48
+ /// this only includes constructor/initialization usages.
49
+ /// The map key is the file ID, and the value is a vector of (range, category) pairs.
50
+ /// - range: The text range of the reference in the file
51
+ /// - category: Metadata about how the reference is used (read/write/etc)
34
52
pub references : IntMap < FileId , Vec < ( TextRange , ReferenceCategory ) > > ,
35
53
}
36
54
55
+ /// Information about the declaration site of a searched item.
37
56
#[ derive( Debug , Clone ) ]
38
57
pub struct Declaration {
58
+ /// Navigation information to jump to the declaration
39
59
pub nav : NavigationTarget ,
60
+ /// Whether the declared item is mutable (relevant for variables)
40
61
pub is_mut : bool ,
41
62
}
42
63
43
64
// Feature: Find All References
44
65
//
45
- // Shows all references of the item at the cursor location
66
+ // Shows all references of the item at the cursor location. This includes:
67
+ // - Direct references to variables, functions, types, etc.
68
+ // - Constructor/initialization references when cursor is on struct/enum definition tokens
69
+ // - References in patterns and type contexts
70
+ // - References through dereferencing and borrowing
71
+ // - References in macro expansions
72
+ //
73
+ // Special handling for constructors:
74
+ // - When the cursor is on `{`, `(`, or `;` in a struct/enum definition
75
+ // - When the cursor is on the type name in a struct/enum definition
76
+ // These cases will show only constructor/initialization usages of the type
46
77
//
47
78
// | Editor | Shortcut |
48
79
// |---------|----------|
49
80
// | VS Code | <kbd>Shift+Alt+F12</kbd> |
50
81
//
51
82
// 
83
+
84
+ /// Find all references to the item at the given position.
85
+ ///
86
+ /// # Arguments
87
+ /// * `sema` - Semantic analysis context
88
+ /// * `position` - Position in the file where to look for the item
89
+ /// * `search_scope` - Optional scope to limit the search (e.g. current crate only)
90
+ ///
91
+ /// # Returns
92
+ /// Returns `None` if no valid item is found at the position.
93
+ /// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.
94
+ /// Multiple results can occur in case of ambiguity or when searching for trait items.
95
+ ///
96
+ /// # Special cases
97
+ /// - Control flow keywords (break, continue, etc): Shows all related jump points
98
+ /// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites
99
+ /// - Format string arguments: Shows template parameter usages
100
+ /// - Lifetime parameters: Shows lifetime constraint usages
101
+ ///
102
+ /// # Constructor search
103
+ /// When the cursor is on specific tokens in a struct/enum definition:
104
+ /// - `{` after struct/enum/variant: Shows record literal initializations
105
+ /// - `(` after tuple struct/variant: Shows tuple literal initializations
106
+ /// - `;` after unit struct: Shows unit literal initializations
107
+ /// - Type name in definition: Shows all initialization usages
108
+ /// In these cases, other kinds of references (like type references) are filtered out.
52
109
pub ( crate ) fn find_all_refs (
53
110
sema : & Semantics < ' _ , RootDatabase > ,
54
111
position : FilePosition ,
@@ -219,7 +276,19 @@ fn retain_adt_literal_usages(
219
276
}
220
277
}
221
278
222
- /// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
279
+ /// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.
280
+ /// This is used to implement the special constructor search behavior when the cursor is on specific tokens
281
+ /// in a struct/enum/variant definition.
282
+ ///
283
+ /// # Returns
284
+ /// - `Some(name)` if the cursor is on:
285
+ /// - `{` after a struct/enum/variant definition
286
+ /// - `(` for tuple structs/variants
287
+ /// - `;` for unit structs
288
+ /// - The type name in a struct/enum/variant definition
289
+ /// - `None` otherwise
290
+ ///
291
+ /// The returned name is the name of the type whose constructor usages should be searched for.
223
292
fn name_for_constructor_search ( syntax : & SyntaxNode , position : FilePosition ) -> Option < ast:: Name > {
224
293
let token = syntax. token_at_offset ( position. offset ) . right_biased ( ) ?;
225
294
let token_parent = token. parent ( ) ?;
@@ -257,6 +326,16 @@ fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> O
257
326
}
258
327
}
259
328
329
+ /// Checks if a name reference is part of an enum variant literal expression.
330
+ /// Used to filter references when searching for enum variant constructors.
331
+ ///
332
+ /// # Arguments
333
+ /// * `sema` - Semantic analysis context
334
+ /// * `enum_` - The enum type to check against
335
+ /// * `name_ref` - The name reference to check
336
+ ///
337
+ /// # Returns
338
+ /// `true` if the name reference is used as part of constructing a variant of the given enum.
260
339
fn is_enum_lit_name_ref (
261
340
sema : & Semantics < ' _ , RootDatabase > ,
262
341
enum_ : hir:: Enum ,
@@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
284
363
. unwrap_or ( false )
285
364
}
286
365
366
+ /// Checks if a path ends with the given name reference.
367
+ /// Helper function for checking constructor usage patterns.
287
368
fn path_ends_with ( path : Option < ast:: Path > , name_ref : & ast:: NameRef ) -> bool {
288
369
path. and_then ( |path| path. segment ( ) )
289
370
. and_then ( |segment| segment. name_ref ( ) )
290
371
. map_or ( false , |segment| segment == * name_ref)
291
372
}
292
373
374
+ /// Checks if a name reference is used in a literal (constructor) context.
375
+ /// Used to filter references when searching for struct/variant constructors.
376
+ ///
377
+ /// # Returns
378
+ /// `true` if the name reference is used as part of a struct/variant literal expression.
293
379
fn is_lit_name_ref ( name_ref : & ast:: NameRef ) -> bool {
294
380
name_ref. syntax ( ) . ancestors ( ) . find_map ( |ancestor| {
295
381
match_ast ! {
0 commit comments