pub struct SymbolPath { /* private fields */ }Expand description
Rust ecosystem-wide unique symbol path
§Format
tokio::sync::Mutex::lock
std::collections::HashMap::insert
ryo_core::mutations::AddMethod::apply§Invariants
- segments is non-empty
- First segment is always the crate name
- Each segment is a valid Rust identifier (or tuple field, or scope marker)
- crate_root_depth is either 1 (lib crate) or 2 (bin crate with main:: prefix)
Implementations§
Source§impl SymbolPath
impl SymbolPath
Sourcepub fn from_file_path(
crate_name: &CrateName,
path: &WorkspaceFilePath,
) -> Result<SymbolPath, ParseError>
pub fn from_file_path( crate_name: &CrateName, path: &WorkspaceFilePath, ) -> Result<SymbolPath, ParseError>
Sourcepub fn from_workspace_file(
path: &WorkspaceFilePath,
) -> Result<SymbolPath, ParseError>
pub fn from_workspace_file( path: &WorkspaceFilePath, ) -> Result<SymbolPath, ParseError>
Create from WorkspaceFilePath (uses embedded crate_name)
This is the simplest way to create a SymbolPath from a file path. Since WorkspaceFilePath now contains the crate_name, no external provider is needed.
§Example
let path = WorkspaceFilePath::new_for_test("src/foo/bar.rs", "/workspace", "my_crate");
let symbol = SymbolPath::from_workspace_file(&path)?;
// → my_crate::foo::barSourcepub fn item_in_file(
path: &WorkspaceFilePath,
item_name: &str,
) -> Result<SymbolPath, ParseError>
pub fn item_in_file( path: &WorkspaceFilePath, item_name: &str, ) -> Result<SymbolPath, ParseError>
Create a symbol path for an item within a file
§Arguments
path: The file containing the itemitem_name: The name of the item (struct, fn, etc.)
§Example
let path = WorkspaceFilePath::new_for_test("src/foo.rs", "/workspace", "my_crate");
let symbol = SymbolPath::item_in_file(&path, "MyStruct")?;
// → my_crate::foo::MyStructSourcepub fn nested_in_file(
path: &WorkspaceFilePath,
segments: &[&str],
) -> Result<SymbolPath, ParseError>
pub fn nested_in_file( path: &WorkspaceFilePath, segments: &[&str], ) -> Result<SymbolPath, ParseError>
Create a symbol path for a nested item (e.g., impl block item, enum variant)
§Arguments
path: The file containing the itemsegments: Additional path segments after the module
§Example
let path = WorkspaceFilePath::new_for_test("src/lib.rs", "/workspace", "my_crate");
let symbol = SymbolPath::nested_in_file(&path, &["Foo", "new"])?;
// → my_crate::Foo::newSourcepub fn module_path_str(path: &WorkspaceFilePath) -> String
pub fn module_path_str(path: &WorkspaceFilePath) -> String
Convert a WorkspaceFilePath to its corresponding SymbolPath string representation.
This is the core conversion function from file paths to symbol paths. It handles both library and binary entry points, applying the correct naming convention for each.
§Binary Entry Points (main.rs)
Binary entry points use the main:: prefix to distinguish them from library symbols:
// For src/main.rs in crate "my_app":
module_path_str(path) → "main::my_app"
// For src/main.rs with nested symbol:
// File: src/main.rs with fn main() {}
module_path_str(path) → "main::my_app"
// Then the full symbol path becomes: "main::my_app::main"This main:: prefix serves critical purposes:
- Disambiguation: Prevents conflicts between lib.rs and main.rs symbols
- File Resolution:
RegistryGeneratorusesis_main_symbol()to determine whether to output tosrc/main.rsorsrc/lib.rs - Bin-Only Detection: Crates with only main.rs (no lib.rs) work correctly because symbols are explicitly marked as binary symbols
§Library Entry Points (lib.rs)
Library entry points use the crate name directly:
// For src/lib.rs in crate "my_lib":
module_path_str(path) → "my_lib"§Module Files
Nested module files follow standard Rust module path conventions:
// For src/models.rs:
module_path_str(path) → "my_crate::models"
// For src/models/user.rs:
module_path_str(path) → "my_crate::models::user"§Reverse Conversion
The reverse conversion (SymbolPath → WorkspaceFilePath) is handled by:
FilePathResolver::resolve_candidates_with_crate_info()- Uses CargoMetadataProvider to determine the correct file path, handling both lib and bin targets
§Example Flow (Bin-Only Crate)
// 1. File Loading (src/main.rs → SymbolPath)
let path = WorkspaceFilePath::new(..., "src/main.rs", "my_app");
let symbol_path = SymbolPath::module_path_str(&path);
// → "main::my_app"
// 2. Symbol Registration
registry.register(SymbolPath::parse("main::my_app::Status")?, SymbolKind::Enum);
// 3. File Generation (SymbolPath → WorkspaceFilePath)
let candidates = file_resolver.resolve_candidates_with_crate_info(
&SymbolPath::parse("main::my_app::Status")?,
&crate_info
);
// → ["src/main.rs"] (because is_main_symbol() returns true)§See Also
SymbolPath::is_main_symbol()- Checks if a symbol is from a binary entryFilePathResolver::resolve_candidates_with_crate_info()- Reverse conversionRegistryGenerator::generate()- Uses is_main_symbol() to determine output file
Sourcepub fn parse(s: &str) -> Result<SymbolPath, ParseError>
pub fn parse(s: &str) -> Result<SymbolPath, ParseError>
Parse from string representation (e.g., “my_crate::foo::Bar”)
Handles :: inside <impl ...> segments correctly by treating
angle-bracketed blocks as atomic (e.g., <impl io::Write for Foo>
is a single segment, not split on io::Write).
Sourcepub fn parse_validated(
s: &str,
registry: &SymbolRegistry,
) -> Result<SymbolPath, ParseError>
pub fn parse_validated( s: &str, registry: &SymbolRegistry, ) -> Result<SymbolPath, ParseError>
Parse with registry validation - ensures crate name exists in registry.
Use this when constructing paths from user input or DSL where the crate name must be validated against known crates.
§Errors
ParseError::UnknownCrateif the crate name is not in the registry- All errors from
parse()
Sourcepub fn from_segments(
segments: impl IntoIterator<Item = impl AsRef<str>>,
) -> Result<SymbolPath, ParseError>
pub fn from_segments( segments: impl IntoIterator<Item = impl AsRef<str>>, ) -> Result<SymbolPath, ParseError>
Construct from segments (with validation)
Sourcepub fn builder(crate_name: impl Into<String>) -> SymbolPathBuilder
pub fn builder(crate_name: impl Into<String>) -> SymbolPathBuilder
Create a builder for constructing SymbolPath
§Examples
let path = SymbolPath::builder("my_crate")
.push("module")
.push("MyStruct")
.build()
.unwrap();
assert_eq!(path.to_string(), "my_crate::module::MyStruct");Sourcepub fn with_var_scope(
&self,
scope: VarScope,
name: &str,
) -> Result<SymbolPath, ParseError>
pub fn with_var_scope( &self, scope: VarScope, name: &str, ) -> Result<SymbolPath, ParseError>
Create a path with variable scope (for variable registration)
§Examples
let fn_path = SymbolPath::parse("my_crate::my_fn").unwrap();
let var_path = fn_path.with_var_scope(VarScope::Param, "x").unwrap();
assert_eq!(var_path.to_string(), "my_crate::my_fn::$param::x");Sourcepub fn crate_name(&self) -> &str
pub fn crate_name(&self) -> &str
Get the crate name (first segment)
Sourcepub fn is_main_symbol(&self) -> bool
pub fn is_main_symbol(&self) -> bool
Check if this is a main.rs symbol (starts with “main::”)
Main symbols use a special prefix to distinguish them from library symbols. This allows explicit targeting of binary entry points in Intent DSL.
§Example
let main_symbol = SymbolPath::parse("main::my_crate::Config")?;
assert!(main_symbol.is_main_symbol());
let lib_symbol = SymbolPath::parse("my_crate::Config")?;
assert!(!lib_symbol.is_main_symbol());Sourcepub fn main_target_crate(&self) -> Option<&str>
pub fn main_target_crate(&self) -> Option<&str>
Get the actual crate name for main symbols
For paths like “main::my_crate::Foo”, returns “my_crate”. Returns None if this is not a main symbol or has insufficient depth.
§Example
let path = SymbolPath::parse("main::my_crate::Config")?;
assert_eq!(path.main_target_crate(), Some("my_crate"));
let lib_path = SymbolPath::parse("my_crate::Config")?;
assert_eq!(lib_path.main_target_crate(), None);Sourcepub fn to_lib_path(&self) -> Option<SymbolPath>
pub fn to_lib_path(&self) -> Option<SymbolPath>
Convert a main symbol path to its library equivalent
Strips the “main::” prefix, converting “main::my_crate::Foo” to “my_crate::Foo”. Returns None if this is not a main symbol.
§Example
let main_path = SymbolPath::parse("main::my_crate::Config")?;
let lib_path = main_path.to_lib_path()?;
assert_eq!(lib_path.to_string(), "my_crate::Config");Sourcepub fn is_crate_root(&self) -> bool
pub fn is_crate_root(&self) -> bool
Check if this symbol path represents a crate root itself
Returns true if this path is the crate root module (not a submodule).
§Examples
let lib_root = SymbolPath::parse("my_lib")?;
assert!(lib_root.is_crate_root());
let lib_mod = SymbolPath::parse("my_lib::utils")?;
assert!(!lib_mod.is_crate_root());
let bin_root = SymbolPath::parse("main::my_app")?;
assert!(bin_root.is_crate_root());
let bin_mod = SymbolPath::parse("main::my_app::utils")?;
assert!(!bin_mod.is_crate_root());Sourcepub fn actual_crate_name(&self) -> &str
pub fn actual_crate_name(&self) -> &str
Get the actual crate name (excluding main:: prefix)
Returns the real crate name, stripping the “main::” prefix for binary crates.
§Examples
let lib_path = SymbolPath::parse("my_lib::Config")?;
assert_eq!(lib_path.actual_crate_name(), "my_lib");
let bin_path = SymbolPath::parse("main::my_app::Config")?;
assert_eq!(bin_path.actual_crate_name(), "my_app");Sourcepub fn mod_path(&self) -> &[Segment]
pub fn mod_path(&self) -> &[Segment]
Get the module path relative to crate root
Returns segments after the crate root.
§Examples
let path = SymbolPath::parse("my_lib::utils::Helper")?;
let mod_path = path.mod_path();
assert_eq!(mod_path.len(), 2); // ["utils", "Helper"]
let bin_path = SymbolPath::parse("main::my_app::utils::Helper")?;
let bin_mod_path = bin_path.mod_path();
assert_eq!(bin_mod_path.len(), 2); // ["utils", "Helper"]
let root = SymbolPath::parse("my_lib")?;
assert_eq!(root.mod_path().len(), 0); // []Sourcepub fn segment_refs(&self) -> &[Segment]
pub fn segment_refs(&self) -> &[Segment]
Get segment references as slice
Sourcepub fn parent(&self) -> Option<SymbolPath>
pub fn parent(&self) -> Option<SymbolPath>
Sourcepub fn is_ancestor_of(&self, other: &SymbolPath) -> bool
pub fn is_ancestor_of(&self, other: &SymbolPath) -> bool
Check if this path is an ancestor of another
Sourcepub fn is_descendant_of(&self, other: &SymbolPath) -> bool
pub fn is_descendant_of(&self, other: &SymbolPath) -> bool
Check if this path is a descendant of another
Sourcepub fn same_crate(&self, other: &SymbolPath) -> bool
pub fn same_crate(&self, other: &SymbolPath) -> bool
Check if both paths are in the same crate
Sourcepub fn common_ancestor(&self, other: &SymbolPath) -> Option<SymbolPath>
pub fn common_ancestor(&self, other: &SymbolPath) -> Option<SymbolPath>
Get the common ancestor of two paths
Sourcepub fn child(&self, name: impl AsRef<str>) -> Result<SymbolPath, ParseError>
pub fn child(&self, name: impl AsRef<str>) -> Result<SymbolPath, ParseError>
Construct a child path by appending a segment.
§Example
let path = SymbolPath::parse("tokio::sync").unwrap();
let child = path.child("Mutex").unwrap();
assert_eq!(child.to_string(), "tokio::sync::Mutex");Sourcepub fn child_inherent_impl(&self, self_ty: &str) -> SymbolPath
pub fn child_inherent_impl(&self, self_ty: &str) -> SymbolPath
Append an inherent impl segment: parent::<impl Type>
Sourcepub fn child_trait_impl(&self, trait_name: &str, self_ty: &str) -> SymbolPath
pub fn child_trait_impl(&self, trait_name: &str, self_ty: &str) -> SymbolPath
Append a trait impl segment: parent::<impl Trait for Type>
Sourcepub fn module_path(&self) -> String
pub fn module_path(&self) -> String
Get the module path (parent of this symbol).
Returns the path without the final item name.
For tokio::sync::Mutex::lock, returns "tokio::sync::Mutex".
For a crate root like tokio, returns "tokio".
Sourcepub fn with_renamed_last_segment(&self, from: &str, to: &str) -> SymbolPath
pub fn with_renamed_last_segment(&self, from: &str, to: &str) -> SymbolPath
Create a new path with the last segment renamed.
If the last segment matches from, it is replaced with to.
Otherwise, returns a clone of self.
Sourcepub fn is_in_symbol(&self) -> bool
pub fn is_in_symbol(&self) -> bool
Check if this is an InSymbol (variable/parameter/field)
Sourcepub fn containing_symbol(&self) -> Option<SymbolPath>
pub fn containing_symbol(&self) -> Option<SymbolPath>
Get the containing symbol path (for InSymbol)
my_crate::my_fn::$param::x → my_crate::my_fn
Sourcepub fn var_name(&self) -> Option<&str>
pub fn var_name(&self) -> Option<&str>
Get the variable name (for InSymbol)
my_crate::my_fn::$param::x → "x"
Sourcepub fn has_body_segment(&self) -> bool
pub fn has_body_segment(&self) -> bool
Check if this path contains a $body segment
Sourcepub fn body_segment_index(&self) -> Option<usize>
pub fn body_segment_index(&self) -> Option<usize>
Get the position of the $body segment
Sourcepub fn body_indices(&self) -> Option<Vec<usize>>
pub fn body_indices(&self) -> Option<Vec<usize>>
Extract body indices (numeric segments after $body)
§Example
let path = SymbolPath::parse("my_crate::my_fn::$body::0::1::2").unwrap();
assert_eq!(path.body_indices(), Some(vec![0, 1, 2]));
let no_body = SymbolPath::parse("my_crate::my_fn").unwrap();
assert_eq!(no_body.body_indices(), None);Sourcepub fn function_path(&self) -> Option<SymbolPath>
pub fn function_path(&self) -> Option<SymbolPath>
Get the function path (everything before $body)
§Example
let path = SymbolPath::parse("my_crate::my_fn::$body::0::1").unwrap();
let fn_path = path.function_path().unwrap();
assert_eq!(fn_path.to_string(), "my_crate::my_fn");Sourcepub fn split_at_body(&self) -> Option<(SymbolPath, Vec<usize>)>
pub fn split_at_body(&self) -> Option<(SymbolPath, Vec<usize>)>
Split into function path and body indices
§Returns
Some((function_path, body_indices)) if path contains $body, None otherwise.
Trait Implementations§
Source§impl Clone for SymbolPath
impl Clone for SymbolPath
Source§fn clone(&self) -> SymbolPath
fn clone(&self) -> SymbolPath
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SymbolPath
impl Debug for SymbolPath
Source§impl<'de> Deserialize<'de> for SymbolPath
impl<'de> Deserialize<'de> for SymbolPath
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<SymbolPath, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<SymbolPath, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Display for SymbolPath
impl Display for SymbolPath
Source§impl FromStr for SymbolPath
impl FromStr for SymbolPath
Source§type Err = ParseError
type Err = ParseError
Source§fn from_str(s: &str) -> Result<SymbolPath, <SymbolPath as FromStr>::Err>
fn from_str(s: &str) -> Result<SymbolPath, <SymbolPath as FromStr>::Err>
s to return a value of this type. Read moreSource§impl Hash for SymbolPath
impl Hash for SymbolPath
Source§impl PartialEq for SymbolPath
impl PartialEq for SymbolPath
Source§fn eq(&self, other: &SymbolPath) -> bool
fn eq(&self, other: &SymbolPath) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for SymbolPath
impl Serialize for SymbolPath
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl Eq for SymbolPath
impl StructuralPartialEq for SymbolPath
Auto Trait Implementations§
impl Freeze for SymbolPath
impl RefUnwindSafe for SymbolPath
impl Send for SymbolPath
impl Sync for SymbolPath
impl Unpin for SymbolPath
impl UnsafeUnpin for SymbolPath
impl UnwindSafe for SymbolPath
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string() Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString. Read more