diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 4518b2a76a9..76ad847b133 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -58,23 +58,20 @@ pub(crate) fn fetch_dependency_list( .into_iter() .filter_map(|it| { let root_file_path = state.file_id_to_file_path(it.root_file_id); - crate_path(it.name.as_ref(), root_file_path).map(|path| CrateInfoResult { + crate_path(root_file_path).and_then(to_url).map(|path| CrateInfoResult { name: it.name, version: it.version, - path: path.to_string(), + path, }) }) .collect(); Ok(FetchDependencyListResult { crates: crate_infos }) } -/// Searches for the directory of a Rust crate with a given name in the directory tree -/// of the root file of that crate. +/// Searches for the directory of a Rust crate given this crate's root file path. /// /// # Arguments /// -/// * `crate_name`: The name of the crate to search for. This should be a `Some` value if -/// a crate name has been specified, or `None` if no crate name has been specified. /// * `root_file_path`: The path to the root file of the crate. /// /// # Returns @@ -82,19 +79,21 @@ pub(crate) fn fetch_dependency_list( /// An `Option` value representing the path to the directory of the crate with the given /// name, if such a crate is found. If no crate with the given name is found, this function /// returns `None`. -fn crate_path(crate_name: Option<&String>, root_file_path: VfsPath) -> Option { - crate_name.and_then(|crate_name| { - let mut root_path = root_file_path; - while let Some(path) = root_path.parent() { - if let Some((name, _)) = path.name_and_extension() { - if name.starts_with(crate_name.as_str()) { - return Some(path); - } - } else { - break; - } - root_path = path; +fn crate_path(root_file_path: VfsPath) -> Option { + let mut current_dir = root_file_path.parent(); + while let Some(path) = current_dir { + let cargo_toml_path = path.join("../Cargo.toml")?; + if fs::metadata(cargo_toml_path.as_path()?).is_ok() { + let crate_path = cargo_toml_path.parent()?; + return Some(crate_path); } - None - }) + current_dir = path.parent(); + } + None +} + +fn to_url(path: VfsPath) -> Option { + let path = path.as_path()?; + let str_path = path.as_os_str().to_str()?; + Url::from_file_path(str_path).ok() } \ No newline at end of file diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 8689fae0798..69e7d824680 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -4,11 +4,11 @@ use ide_db::line_index::WideEncoding; use lsp_types::request::Request; -use lsp_types::PositionEncodingKind; use lsp_types::{ notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams, PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams, }; +use lsp_types::{PositionEncodingKind, Url}; use serde::{Deserialize, Serialize}; use crate::line_index::PositionEncoding; @@ -32,7 +32,7 @@ pub struct AnalyzerStatusParams { pub struct CrateInfoResult { pub name: Option, pub version: Option, - pub path: String, + pub path: Url, } pub enum FetchDependencyList {} diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 81d3b8da7f9..98ccd50dc04 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -276,6 +276,9 @@ export function openCargoToml(ctx: CtxInit): Cmd { export function revealDependency(ctx: CtxInit): Cmd { return async (editor: RustEditor) => { + if (!ctx.dependencies?.isInitialized()) { + return; + } const documentPath = editor.document.uri.fsPath; const dep = ctx.dependencies?.getDependency(documentPath); if (dep) { diff --git a/editors/code/src/dependencies_provider.ts b/editors/code/src/dependencies_provider.ts index 59b3b27731c..74fbacbb3cd 100644 --- a/editors/code/src/dependencies_provider.ts +++ b/editors/code/src/dependencies_provider.ts @@ -32,6 +32,10 @@ export class RustDependenciesProvider return filePath.toLowerCase() in this.dependenciesMap; } + isInitialized(): boolean { + return Object.keys(this.dependenciesMap).length !== 0; + } + refresh(): void { this.dependenciesMap = {}; this._onDidChangeTreeData.fire(); @@ -89,7 +93,12 @@ export class RustDependenciesProvider } private toDep(moduleName: string, version: string, path: string): Dependency { - return new Dependency(moduleName, version, path, vscode.TreeItemCollapsibleState.Collapsed); + return new Dependency( + moduleName, + version, + vscode.Uri.parse(path).fsPath, + vscode.TreeItemCollapsibleState.Collapsed + ); } } @@ -101,9 +110,9 @@ export class Dependency extends vscode.TreeItem { public readonly collapsibleState: vscode.TreeItemCollapsibleState ) { super(label, collapsibleState); - this.id = this.dependencyPath.toLowerCase(); - this.description = this.version; this.resourceUri = vscode.Uri.file(dependencyPath); + this.id = this.resourceUri.fsPath.toLowerCase(); + this.description = this.version; if (this.version) { this.tooltip = `${this.label}-${this.version}`; } else { @@ -120,13 +129,13 @@ export class DependencyFile extends vscode.TreeItem { public readonly collapsibleState: vscode.TreeItemCollapsibleState ) { super(vscode.Uri.file(dependencyPath), collapsibleState); - this.id = this.dependencyPath.toLowerCase(); - const isDir = fs.lstatSync(this.dependencyPath).isDirectory(); + this.id = this.resourceUri!.fsPath.toLowerCase(); + const isDir = fs.lstatSync(this.resourceUri!.fsPath).isDirectory(); if (!isDir) { this.command = { command: "vscode.open", title: "Open File", - arguments: [vscode.Uri.file(this.dependencyPath)], + arguments: [this.resourceUri], }; } } diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index b72804e510c..0d75392c92b 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts @@ -2,6 +2,7 @@ * This file mirrors `crates/rust-analyzer/src/lsp_ext.rs` declarations. */ +import { Uri } from "vscode"; import * as lc from "vscode-languageclient"; // rust-analyzer overrides