Skip to main content

SymbolPath

Struct SymbolPath 

Source
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

Source

pub fn from_file_path( crate_name: &CrateName, path: &WorkspaceFilePath, ) -> Result<SymbolPath, ParseError>

Create from file path (external API)

This is the primary way to create a SymbolPath from outside the crate.

§Arguments
  • crate_name: The crate containing the file
  • path: The file path within the workspace
§Returns

A SymbolPath representing the module path for this file

Source

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::bar
Source

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 item
  • item_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::MyStruct
Source

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 item
  • segments: 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::new
Source

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:

  1. Disambiguation: Prevents conflicts between lib.rs and main.rs symbols
  2. File Resolution: RegistryGenerator uses is_main_symbol() to determine whether to output to src/main.rs or src/lib.rs
  3. 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 entry
  • FilePathResolver::resolve_candidates_with_crate_info() - Reverse conversion
  • RegistryGenerator::generate() - Uses is_main_symbol() to determine output file
Source

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).

Source

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::UnknownCrate if the crate name is not in the registry
  • All errors from parse()
Source

pub fn from_segments( segments: impl IntoIterator<Item = impl AsRef<str>>, ) -> Result<SymbolPath, ParseError>

Construct from segments (with validation)

Source

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");
Source

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");
Source

pub fn crate_name(&self) -> &str

Get the crate name (first segment)

Source

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());
Source

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);
Source

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");
Source

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());
Source

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");
Source

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); // []
Source

pub fn depth(&self) -> usize

Get the depth (number of segments)

Source

pub fn segments(&self) -> impl Iterator<Item = &str>

Iterate over segment names

Source

pub fn segment_refs(&self) -> &[Segment]

Get segment references as slice

Source

pub fn segment(&self, index: usize) -> Option<&Segment>

Get segment at index

Source

pub fn name(&self) -> &str

Get the last segment (symbol name)

Source

pub fn parent(&self) -> Option<SymbolPath>

Get the parent path

§Examples
let path = SymbolPath::parse("tokio::sync::Mutex::lock")?;
assert_eq!(path.parent().unwrap().to_string(), "tokio::sync::Mutex");
Source

pub fn is_ancestor_of(&self, other: &SymbolPath) -> bool

Check if this path is an ancestor of another

Source

pub fn is_descendant_of(&self, other: &SymbolPath) -> bool

Check if this path is a descendant of another

Source

pub fn same_crate(&self, other: &SymbolPath) -> bool

Check if both paths are in the same crate

Source

pub fn common_ancestor(&self, other: &SymbolPath) -> Option<SymbolPath>

Get the common ancestor of two paths

Source

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");
Source

pub fn child_inherent_impl(&self, self_ty: &str) -> SymbolPath

Append an inherent impl segment: parent::<impl Type>

Source

pub fn child_trait_impl(&self, trait_name: &str, self_ty: &str) -> SymbolPath

Append a trait impl segment: parent::<impl Trait for Type>

Source

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".

Source

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.

Source

pub fn is_in_symbol(&self) -> bool

Check if this is an InSymbol (variable/parameter/field)

Source

pub fn containing_symbol(&self) -> Option<SymbolPath>

Get the containing symbol path (for InSymbol)

my_crate::my_fn::$param::xmy_crate::my_fn

Source

pub fn var_name(&self) -> Option<&str>

Get the variable name (for InSymbol)

my_crate::my_fn::$param::x"x"

Source

pub fn var_scope(&self) -> Option<VarScope>

Get the VarScope if this is an InSymbol path

Source

pub fn has_body_segment(&self) -> bool

Check if this path contains a $body segment

Source

pub fn body_segment_index(&self) -> Option<usize>

Get the position of the $body segment

Source

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);
Source

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");
Source

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

Source§

fn clone(&self) -> SymbolPath

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SymbolPath

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for SymbolPath

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<SymbolPath, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for SymbolPath

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl FromStr for SymbolPath

Source§

type Err = ParseError

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<SymbolPath, <SymbolPath as FromStr>::Err>

Parses a string s to return a value of this type. Read more
Source§

impl Hash for SymbolPath

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for SymbolPath

Source§

fn eq(&self, other: &SymbolPath) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for SymbolPath

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for SymbolPath

Source§

impl StructuralPartialEq for SymbolPath

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToCompactString for T
where T: Display,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,