about summary refs log tree commit diff
path: root/src/tools/rust-analyzer
diff options
context:
space:
mode:
authorvremyavnikuda <andrew.nevsky@yandex.ru>2025-05-25 15:28:07 +0700
committervremyavnikuda <andrew.nevsky@yandex.ru>2025-05-26 15:51:50 +0700
commit44612c5f9cbd21ebe60dab93f3c536084c4bf495 (patch)
tree6644b0fe166e25d43a170c083107e9c11f7bba72 /src/tools/rust-analyzer
parent94c624e7f5233ccce1808d740b37aeeb7ed90282 (diff)
downloadrust-44612c5f9cbd21ebe60dab93f3c536084c4bf495.tar.gz
rust-44612c5f9cbd21ebe60dab93f3c536084c4bf495.zip
docs: add documentation for find_all_refs constructor search (#10725)
Diffstat (limited to 'src/tools/rust-analyzer')
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs71
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs90
2 files changed, 158 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index d649dffbd90..6e35084ceb3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -514,7 +514,76 @@ impl Analysis {
         self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
     }
 
-    /// Finds all usages of the reference at point.
+    /// Find all references to the item at the cursor position.
+    ///
+    /// # Examples
+    ///
+    /// Basic struct reference search:
+    /// ```rust
+    /// struct S {
+    ///     pub x: usize,
+    /// }
+    ///
+    /// fn print_s(s: S) {
+    ///     println!("{}", s.x)
+    /// }
+    ///
+    /// fn main() {
+    ///     let s = S { x: 42 };  // This is a constructor usage
+    ///     print_s(s);           // This is a type reference
+    /// }
+    /// ```
+    ///
+    /// To find only constructor/initialization usages:
+    /// 1. Position cursor on special tokens in struct/enum definition:
+    ///    ```rust
+    ///    // On '{' - finds record struct initializations
+    ///    struct Point { // <- cursor here on '{'
+    ///        x: i32,
+    ///        y: i32,
+    ///    }
+    ///
+    ///    // On '(' - finds tuple struct initializations
+    ///    struct Tuple(i32, i32); // <- cursor here on '('
+    ///
+    ///    // On ';' - finds unit struct initializations
+    ///    struct Unit; // <- cursor here on ';'
+    ///    ```
+    ///
+    /// 2. Examples of what will be found:
+    ///    ```rust
+    ///    struct Point{x: i32, y: i32};
+    ///    struct Tuple(i32, i32);
+    ///    struct Unit;
+    ///
+    ///
+    ///    let p1 = Point { x: 0, y: 0 };  // Found when cursor on '{'
+    ///    let p2 = Tuple(1, 2);           // Found when cursor on '('
+    ///    let u = Unit;                    // Found when cursor on ';'
+    ///    ```
+    ///
+    /// 3. For enum variants:
+    ///    ```rust
+    ///    enum E {
+    ///        Struct { // <- cursor here on '{'
+    ///            x: i32
+    ///        },
+    ///        Tuple(i32), // <- cursor here on '('
+    ///        Unit        // <- cursor here on identifier
+    ///    }
+    ///
+    ///    let e1 = E::Struct { x: 0 };  // Found for Struct variant
+    ///    let e2 = E::Tuple(1);         // Found for Tuple variant
+    ///    let e3 = E::Unit;             // Found for Unit variant
+    ///    ```
+    ///
+    /// # Parameters
+    /// * `position` - The position in the file to find references for
+    /// * `search_scope` - Optional scope to limit the search
+    ///
+    /// # Returns
+    /// Returns a vector of reference search results if references are found,
+    /// or None if no valid item is found at the position.
     pub fn find_all_refs(
         &self,
         position: FilePosition,
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 4fa116444b7..91f4d752c8d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -8,6 +8,14 @@
 //! for text occurrences of the identifier. If there's an `ast::NameRef`
 //! at the index that the match starts at and its tree parent is
 //! resolved to the search element definition, we get a reference.
+//!
+//! Special handling for constructors/initializations:
+//! When searching for references to a struct/enum/variant, if the cursor is positioned on:
+//! - `{` after a struct/enum/variant definition
+//! - `(` for tuple structs/variants
+//! - `;` for unit structs
+//! - The type name in a struct/enum/variant definition
+//! Then only constructor/initialization usages will be shown, filtering out other references.
 
 use hir::{PathResolution, Semantics};
 use ide_db::{
@@ -28,27 +36,76 @@ use syntax::{
 
 use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
 
+/// Result of a reference search operation.
 #[derive(Debug, Clone)]
 pub struct ReferenceSearchResult {
+    /// Information about the declaration site of the searched item.
+    /// For ADTs (structs/enums), this points to the type definition.
+    /// May be None for primitives or items without clear declaration sites.
     pub declaration: Option<Declaration>,
+    /// All references found, grouped by file.
+    /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),
+    /// this only includes constructor/initialization usages.
+    /// The map key is the file ID, and the value is a vector of (range, category) pairs.
+    /// - range: The text range of the reference in the file
+    /// - category: Metadata about how the reference is used (read/write/etc)
     pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
 }
 
+/// Information about the declaration site of a searched item.
 #[derive(Debug, Clone)]
 pub struct Declaration {
+    /// Navigation information to jump to the declaration
     pub nav: NavigationTarget,
+    /// Whether the declared item is mutable (relevant for variables)
     pub is_mut: bool,
 }
 
 // Feature: Find All References
 //
-// Shows all references of the item at the cursor location
+// Shows all references of the item at the cursor location. This includes:
+// - Direct references to variables, functions, types, etc.
+// - Constructor/initialization references when cursor is on struct/enum definition tokens
+// - References in patterns and type contexts
+// - References through dereferencing and borrowing
+// - References in macro expansions
+//
+// Special handling for constructors:
+// - When the cursor is on `{`, `(`, or `;` in a struct/enum definition
+// - When the cursor is on the type name in a struct/enum definition
+// These cases will show only constructor/initialization usages of the type
 //
 // | Editor  | Shortcut |
 // |---------|----------|
 // | VS Code | <kbd>Shift+Alt+F12</kbd> |
 //
 // ![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)
+
+/// Find all references to the item at the given position.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `position` - Position in the file where to look for the item
+/// * `search_scope` - Optional scope to limit the search (e.g. current crate only)
+///
+/// # Returns
+/// Returns `None` if no valid item is found at the position.
+/// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.
+/// Multiple results can occur in case of ambiguity or when searching for trait items.
+///
+/// # Special cases
+/// - Control flow keywords (break, continue, etc): Shows all related jump points
+/// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites
+/// - Format string arguments: Shows template parameter usages
+/// - Lifetime parameters: Shows lifetime constraint usages
+///
+/// # Constructor search
+/// When the cursor is on specific tokens in a struct/enum definition:
+/// - `{` after struct/enum/variant: Shows record literal initializations
+/// - `(` after tuple struct/variant: Shows tuple literal initializations
+/// - `;` after unit struct: Shows unit literal initializations
+/// - Type name in definition: Shows all initialization usages
+/// In these cases, other kinds of references (like type references) are filtered out.
 pub(crate) fn find_all_refs(
     sema: &Semantics<'_, RootDatabase>,
     position: FilePosition,
@@ -219,7 +276,19 @@ fn retain_adt_literal_usages(
     }
 }
 
-/// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
+/// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.
+/// This is used to implement the special constructor search behavior when the cursor is on specific tokens
+/// in a struct/enum/variant definition.
+///
+/// # Returns
+/// - `Some(name)` if the cursor is on:
+///   - `{` after a struct/enum/variant definition
+///   - `(` for tuple structs/variants
+///   - `;` for unit structs
+///   - The type name in a struct/enum/variant definition
+/// - `None` otherwise
+///
+/// The returned name is the name of the type whose constructor usages should be searched for.
 fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
     let token = syntax.token_at_offset(position.offset).right_biased()?;
     let token_parent = token.parent()?;
@@ -257,6 +326,16 @@ fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> O
     }
 }
 
+/// Checks if a name reference is part of an enum variant literal expression.
+/// Used to filter references when searching for enum variant constructors.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `enum_` - The enum type to check against
+/// * `name_ref` - The name reference to check
+///
+/// # Returns
+/// `true` if the name reference is used as part of constructing a variant of the given enum.
 fn is_enum_lit_name_ref(
     sema: &Semantics<'_, RootDatabase>,
     enum_: hir::Enum,
@@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
         .unwrap_or(false)
 }
 
+/// Checks if a path ends with the given name reference.
+/// Helper function for checking constructor usage patterns.
 fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
     path.and_then(|path| path.segment())
         .and_then(|segment| segment.name_ref())
         .map_or(false, |segment| segment == *name_ref)
 }
 
+/// Checks if a name reference is used in a literal (constructor) context.
+/// Used to filter references when searching for struct/variant constructors.
+///
+/// # Returns
+/// `true` if the name reference is used as part of a struct/variant literal expression.
 fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
     name_ref.syntax().ancestors().find_map(|ancestor| {
         match_ast! {