Unnamed repository; edit this file 'description' to name the repository.
Allow locate parent module action in cargo toml
rainy-me 2021-10-03
parent 60c5449 · commit 39044fe
-rw-r--r--crates/rust-analyzer/src/handlers.rs80
-rw-r--r--editors/code/src/commands.ts6
-rw-r--r--editors/code/src/util.ts5
3 files changed, 83 insertions, 8 deletions
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index e62bb9499f..a7ca5a7a34 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -20,15 +20,17 @@ use lsp_types::{
CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
CodeLens, CompletionItem, Diagnostic, DiagnosticTag, DocumentFormattingParams, FoldingRange,
- FoldingRangeParams, HoverContents, Location, NumberOrString, Position, PrepareRenameResponse,
- Range, RenameParams, SemanticTokensDeltaParams, SemanticTokensFullDeltaResult,
- SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
- SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
+ FoldingRangeParams, HoverContents, Location, LocationLink, NumberOrString, Position,
+ PrepareRenameResponse, Range, RenameParams, SemanticTokensDeltaParams,
+ SemanticTokensFullDeltaResult, SemanticTokensParams, SemanticTokensRangeParams,
+ SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, SymbolTag,
+ TextDocumentIdentifier, Url, WorkspaceEdit,
};
-use project_model::TargetKind;
+use project_model::{ProjectWorkspace, TargetKind};
use serde_json::json;
use stdx::{format_to, never};
use syntax::{algo, ast, AstNode, TextRange, TextSize, T};
+use vfs::AbsPath;
use crate::{
cargo_target_spec::CargoTargetSpec,
@@ -603,6 +605,74 @@ pub(crate) fn handle_parent_module(
params: lsp_types::TextDocumentPositionParams,
) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
let _p = profile::span("handle_parent_module");
+ if let Ok(file_path) = &params.text_document.uri.to_file_path() {
+ if file_path.file_name().unwrap_or_default() == "Cargo.toml" {
+ // search parent workspace and collect a list of `LocationLink`path,
+ // since cargo.toml doesn't have file_id
+ let links: Vec<LocationLink> = snap
+ .workspaces
+ .iter()
+ .filter_map(|ws| match ws {
+ ProjectWorkspace::Cargo { cargo, .. } => cargo
+ .packages()
+ .find(|&pkg| {
+ cargo[pkg]
+ .targets
+ .iter()
+ .find_map(|&it| {
+ let pkg_parent_path = cargo[it].root.parent()?;
+ let file_parent_path = AbsPath::assert(file_path.parent()?);
+ if pkg_parent_path == file_parent_path {
+ Some(())
+ } else {
+ None
+ }
+ })
+ .is_some()
+ })
+ .and_then(|_| Some(cargo)),
+ _ => None,
+ })
+ .map(|ws| {
+ let target_cargo_toml_path = ws.workspace_root().join("Cargo.toml");
+ let target_cargo_toml_url =
+ to_proto::url_from_abs_path(&target_cargo_toml_path);
+ LocationLink {
+ origin_selection_range: None,
+ target_uri: target_cargo_toml_url,
+ target_range: Range::default(),
+ target_selection_range: Range::default(),
+ }
+ })
+ .collect::<_>();
+ return Ok(Some(links.into()));
+ }
+
+ // check if invoked at the crate root
+ let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
+ let crate_id = match snap.analysis.crate_for(file_id)?.first() {
+ Some(&crate_id) => crate_id,
+ None => return Ok(None),
+ };
+ let cargo_spec = match CargoTargetSpec::for_file(&snap, file_id)? {
+ Some(it) => it,
+ None => return Ok(None),
+ };
+
+ if snap.analysis.crate_root(crate_id)? == file_id {
+ let cargo_toml_url = to_proto::url_from_abs_path(&cargo_spec.cargo_toml);
+ let res = vec![LocationLink {
+ origin_selection_range: None,
+ target_uri: cargo_toml_url,
+ target_range: Range::default(),
+ target_selection_range: Range::default(),
+ }]
+ .into();
+ return Ok(Some(res));
+ }
+ }
+
+ // locate parent module by semantics
let position = from_proto::file_position(&snap, params)?;
let navs = snap.analysis.parent_module(position)?;
let res = to_proto::goto_definition_response(&snap, None, navs)?;
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 0e08b60a93..623e33c7ef 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -8,7 +8,7 @@ import { applySnippetWorkspaceEdit, applySnippetTextEdits } from './snippets';
import { spawnSync } from 'child_process';
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from './run';
import { AstInspector } from './ast_inspector';
-import { isRustDocument, sleep, isRustEditor } from './util';
+import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor } from './util';
import { startDebugSession, makeDebugConfig } from './debug';
import { LanguageClient } from 'vscode-languageclient/node';
@@ -185,10 +185,10 @@ export function onEnter(ctx: Ctx): Cmd {
export function parentModule(ctx: Ctx): Cmd {
return async () => {
- const editor = ctx.activeRustEditor;
+ const editor = vscode.window.activeTextEditor;
const client = ctx.client;
if (!editor || !client) return;
-
+ if (!(isRustDocument(editor.document) || isCargoTomlDocument(editor.document))) return;
const locations = await client.sendRequest(ra.parentModule, {
textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
position: client.code2ProtocolConverter.asPosition(
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts
index aa57081a5f..057a3d2e19 100644
--- a/editors/code/src/util.ts
+++ b/editors/code/src/util.ts
@@ -104,6 +104,11 @@ export function isRustDocument(document: vscode.TextDocument): document is RustD
return document.languageId === 'rust' && document.uri.scheme === 'file';
}
+export function isCargoTomlDocument(document: vscode.TextDocument): document is RustDocument {
+ // ideally `document.languageId` should be 'toml' but user maybe not have toml extension installed
+ return document.uri.scheme === 'file' && document.fileName.endsWith('Cargo.toml');
+}
+
export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor {
return isRustDocument(editor.document);
}