mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
Merge pull request #19861 from vremyavnikuda/docs/find-all-refs-constructor-search
Some checks are pending
metrics / generate_final_metrics (push) Blocked by required conditions
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
Some checks are pending
metrics / generate_final_metrics (push) Blocked by required conditions
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
docs: add documentation for find_all_refs constructor search
This commit is contained in:
commit
e65dddaf59
2 changed files with 88 additions and 3 deletions
|
|
@ -514,7 +514,6 @@ impl Analysis {
|
||||||
self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
|
self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds all usages of the reference at point.
|
|
||||||
pub fn find_all_refs(
|
pub fn find_all_refs(
|
||||||
&self,
|
&self,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,14 @@
|
||||||
//! for text occurrences of the identifier. If there's an `ast::NameRef`
|
//! 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
|
//! at the index that the match starts at and its tree parent is
|
||||||
//! resolved to the search element definition, we get a reference.
|
//! 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 hir::{PathResolution, Semantics};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
|
|
@ -28,27 +36,76 @@ use syntax::{
|
||||||
|
|
||||||
use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
|
use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
|
||||||
|
|
||||||
|
/// Result of a reference search operation.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ReferenceSearchResult {
|
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>,
|
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)>>,
|
pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about the declaration site of a searched item.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Declaration {
|
pub struct Declaration {
|
||||||
|
/// Navigation information to jump to the declaration
|
||||||
pub nav: NavigationTarget,
|
pub nav: NavigationTarget,
|
||||||
|
/// Whether the declared item is mutable (relevant for variables)
|
||||||
pub is_mut: bool,
|
pub is_mut: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feature: Find All References
|
// 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 |
|
// | Editor | Shortcut |
|
||||||
// |---------|----------|
|
// |---------|----------|
|
||||||
// | VS Code | <kbd>Shift+Alt+F12</kbd> |
|
// | VS Code | <kbd>Shift+Alt+F12</kbd> |
|
||||||
//
|
//
|
||||||
// 
|
// 
|
||||||
|
|
||||||
|
/// 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(
|
pub(crate) fn find_all_refs(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
position: FilePosition,
|
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> {
|
fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
|
||||||
let token = syntax.token_at_offset(position.offset).right_biased()?;
|
let token = syntax.token_at_offset(position.offset).right_biased()?;
|
||||||
let token_parent = token.parent()?;
|
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(
|
fn is_enum_lit_name_ref(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
enum_: hir::Enum,
|
enum_: hir::Enum,
|
||||||
|
|
@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
|
||||||
.unwrap_or(false)
|
.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 {
|
fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
|
||||||
path.and_then(|path| path.segment())
|
path.and_then(|path| path.segment())
|
||||||
.and_then(|segment| segment.name_ref())
|
.and_then(|segment| segment.name_ref())
|
||||||
.map_or(false, |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 {
|
fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
|
||||||
name_ref.syntax().ancestors().find_map(|ancestor| {
|
name_ref.syntax().ancestors().find_map(|ancestor| {
|
||||||
match_ast! {
|
match_ast! {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue