Skip to main content

FilePathResolver

Struct FilePathResolver 

Source
pub struct FilePathResolver { /* private fields */ }
Expand description

Resolves symbol paths to file paths

§Design

This resolver centralizes the conversion from Rust symbol paths to file system paths (WorkspaceFilePath). It provides two resolution strategies:

  1. Registry-based (preferred): Uses SymbolRegistry span info
  2. Inference-based (fallback): Infers file path from module structure

§Example

let resolver = FilePathResolver::new(workspace_root);

// With registry (preferred - uses span info)
let path = resolver.resolve_with_registry(&symbol_path, &registry)?;

// Without registry (inference-based)
let path = resolver.resolve_by_inference(&symbol_path)?;

Implementations§

Source§

impl FilePathResolver

Source

pub fn new(workspace_root: PathBuf) -> Self

Create a new resolver with the given workspace root

Source

pub fn from_workspace_resolver( workspace_resolver: WorkspacePathResolver, ) -> Self

Create from an existing WorkspacePathResolver

Source

pub fn workspace_root(&self) -> &Path

Get the workspace root

Source

pub fn resolve_with_registry( &self, path: &SymbolPath, registry: &SymbolRegistry, ) -> Result<WorkspaceFilePath, ResolutionError>

Resolve SymbolPath to WorkspaceFilePath using SymbolRegistry

This is the preferred method as it uses span information from the registry.

§Returns
  • Ok(WorkspaceFilePath) - The file containing the symbol
  • Err(ResolutionError::SymbolNotFound) - Symbol not in registry
  • Err(ResolutionError::NoSpanInfo) - Symbol found but has no span
Source

pub fn resolve( &self, path: &SymbolPath, registry: Option<&SymbolRegistry>, ) -> Result<WorkspaceFilePath, ResolutionError>

Resolve SymbolPath to WorkspaceFilePath, falling back to inference

Tries registry first, then falls back to inference if:

  • Symbol not found in registry
  • Symbol has no span info
§Arguments
  • path - The symbol path to resolve
  • registry - Optional registry for span-based resolution
Source

pub fn resolve_by_inference( &self, path: &SymbolPath, ) -> Result<WorkspaceFilePath, ResolutionError>

Resolve SymbolPath to WorkspaceFilePath by inferring from module structure

Follows Rust’s module conventions:

  • crate_namesrc/lib.rs or src/main.rs
  • crate_name::foosrc/foo.rs or src/foo/mod.rs
  • crate_name::foo::barsrc/foo/bar.rs or src/foo/bar/mod.rs
  • crate_name::foo::bar::Item → same as crate_name::foo::bar
§Note

This method cannot distinguish between:

  • A module file (foo.rs defines module foo)
  • An item in a parent module (foo is an item in lib.rs)

Use resolve_with_registry when accuracy is critical.

Source

pub fn resolve_candidates(&self, path: &SymbolPath) -> Vec<WorkspaceFilePath>

Resolve with mod.rs fallback

First tries src/foo/bar.rs, then src/foo/bar/mod.rs. Returns both candidates for caller to check existence.

Source

pub fn resolve_candidates_with_crate_info( &self, path: &SymbolPath, crate_info: &CrateInfo, ) -> Vec<WorkspaceFilePath>

Resolve SymbolPath to WorkspaceFilePath candidates using Cargo metadata.

This is the accurate, metadata-driven file resolution method that correctly handles:

  • Bin-only crates (no lib.rs, only main.rs)
  • Mixed crates (both lib.rs and main.rs)
  • Library-only crates
  • Workspace crates in subdirectories
§Main Symbol Handling

This method handles the main:: prefix correctly by skipping both “main” and the crate name when processing segments:

// Library symbol:
"my_crate::models::User"
segments: skip(1) → ["models", "User"]

// Binary symbol:
"main::my_crate::models::User"
segments: skip(2) → ["models", "User"]  // Skip both "main" and "my_crate"
§Crate Root Resolution

For crate root symbols (0 or 1 segments after crate name):

// Library crate:
"my_crate" or "my_crate::Item" → ["src/lib.rs"]

// Bin-only crate:
"main::my_app" or "main::my_app::Item" → ["src/main.rs"]

// Mixed crate (both lib and bin):
"my_crate::Item" → ["src/lib.rs", "src/main.rs"]
"main::my_crate::Item" → ["src/main.rs", "src/lib.rs"]

The resolve_crate_root_candidates() method consults crate_info.entry_points to determine which files to include.

§Sub-Module Resolution

For nested modules (2+ segments after crate name):

"my_crate::models::User" → ["src/models.rs", "src/models/mod.rs"]
"main::my_app::cli::Args" → ["src/cli.rs", "src/cli/mod.rs"]
§Arguments
  • path - The symbol path to resolve (may have main:: prefix)
  • crate_info - Cargo metadata for the target crate
§Returns

A vector of candidate file paths, ordered by preference:

  1. For crate root: entry point files (lib.rs, main.rs, or both)
  2. For modules: file.rs first, then file/mod.rs
§Example
// Bin-only crate (only main.rs):
let path = SymbolPath::parse("main::my_app::Status")?;
let candidates = resolver.resolve_candidates_with_crate_info(&path, &crate_info);
// → ["src/main.rs"] (crate root, bin-only)

// Library crate with module:
let path = SymbolPath::parse("my_lib::models::User")?;
let candidates = resolver.resolve_candidates_with_crate_info(&path, &crate_info);
// → ["src/models.rs", "src/models/mod.rs"]
§See Also
Source

pub fn resolve_with_crate_info<F>( &self, path: &SymbolPath, crate_info: &CrateInfo, file_exists: F, ) -> Result<WorkspaceFilePath, ResolutionError>
where F: Fn(&WorkspaceFilePath) -> bool,

Resolve using CrateInfo, checking file existence

Returns the first candidate that exists in the provided file set. This is the recommended method for production use.

§Arguments
  • path - The symbol path to resolve
  • crate_info - Cargo metadata for the crate
  • existing_files - Set of files that exist (for existence checking)

Trait Implementations§

Source§

impl Clone for FilePathResolver

Source§

fn clone(&self) -> FilePathResolver

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 FilePathResolver

Source§

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

Formats the value using the given formatter. Read more

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