6519: Add "Open Cargo.toml" action r=matklad a=p3achyjr

## What is it?

This adds an "open cargo.toml" action from the vscode shell, resolves #6462 

## Test

Ran ```cargo xtask install --server``` and ```cargo xtask install --client```, then ```Developer: Reload Window```.

![image](https://user-images.githubusercontent.com/8763808/98614382-2a578f00-22ad-11eb-9811-4a72a54ff6fb.png)

When clicked:

![image](https://user-images.githubusercontent.com/8763808/98618176-77d7fa00-22b5-11eb-8788-35256542f3a6.png)


Co-authored-by: Anatol Liu <axlui@anatols-mbp.lan>
This commit is contained in:
bors[bot] 2020-11-13 15:25:26 +00:00 committed by GitHub
commit b0ad492e3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 105 additions and 8 deletions

1
.gitignore vendored
View file

@ -10,3 +10,4 @@ crates/*/target
generated_assists.adoc generated_assists.adoc
generated_features.adoc generated_features.adoc
generated_diagnostic.adoc generated_diagnostic.adoc
.DS_Store

BIN
crates/ide/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -398,13 +398,10 @@ impl Config {
} }
if let Some(code_action) = &doc_caps.code_action { if let Some(code_action) = &doc_caps.code_action {
match (code_action.data_support, &code_action.resolve_support) { if let Some(resolve_support) = &code_action.resolve_support {
(Some(true), Some(resolve_support)) => { if resolve_support.properties.iter().any(|it| it == "edit") {
if resolve_support.properties.iter().any(|it| it == "edit") { self.client_caps.code_action_resolve = true;
self.client_caps.code_action_resolve = true;
}
} }
_ => (),
} }
} }
} }

View file

@ -1322,6 +1322,28 @@ pub(crate) fn handle_open_docs(
Ok(remote.and_then(|remote| Url::parse(&remote).ok())) Ok(remote.and_then(|remote| Url::parse(&remote).ok()))
} }
pub(crate) fn handle_open_cargo_toml(
snap: GlobalStateSnapshot,
params: lsp_ext::OpenCargoTomlParams,
) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
let _p = profile::span("handle_open_cargo_toml");
let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
let maybe_cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?;
if maybe_cargo_spec.is_none() {
return Ok(None);
}
let cargo_spec = maybe_cargo_spec.unwrap();
let cargo_toml_path = cargo_spec.workspace_root.join("Cargo.toml");
if !cargo_toml_path.exists() {
return Ok(None);
}
let cargo_toml_url = to_proto::url_from_abs_path(&cargo_toml_path);
let cargo_toml_location = Location::new(cargo_toml_url, Range::default());
let res = lsp_types::GotoDefinitionResponse::from(cargo_toml_location);
Ok(Some(res))
}
fn implementation_title(count: usize) -> String { fn implementation_title(count: usize) -> String {
if count == 1 { if count == 1 {
"1 implementation".into() "1 implementation".into()

View file

@ -354,3 +354,17 @@ impl Request for ExternalDocs {
type Result = Option<lsp_types::Url>; type Result = Option<lsp_types::Url>;
const METHOD: &'static str = "experimental/externalDocs"; const METHOD: &'static str = "experimental/externalDocs";
} }
pub enum OpenCargoToml {}
impl Request for OpenCargoToml {
type Params = OpenCargoTomlParams;
type Result = Option<lsp_types::GotoDefinitionResponse>;
const METHOD: &'static str = "experimental/openCargoToml";
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct OpenCargoTomlParams {
pub text_document: TextDocumentIdentifier,
}

View file

@ -438,6 +438,7 @@ impl GlobalState {
.on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve) .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
.on::<lsp_ext::HoverRequest>(handlers::handle_hover) .on::<lsp_ext::HoverRequest>(handlers::handle_hover)
.on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs) .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)
.on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
.on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting) .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol) .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
.on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol) .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)

View file

@ -1,8 +1,8 @@
<!--- <!---
lsp_ext.rs hash: 4f86fb54e4b2870e lsp_ext.rs hash: 9d5daed5b25dc4f6
If you need to change the above hash to make the test pass, please check if you If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue: need to adjust this doc as well and ping this issue:
https://github.com/rust-analyzer/rust-analyzer/issues/4604 https://github.com/rust-analyzer/rust-analyzer/issues/4604
@ -537,3 +537,28 @@ Such actions on the client side are appended to a hover bottom as command links:
+-----------------------------+ +-----------------------------+
... ...
``` ```
## Open Cargo.toml
**Issue:** https://github.com/rust-analyzer/rust-analyzer/issues/6462
This request is sent from client to server to open the current project's Cargo.toml
**Method:** `experimental/openCargoToml`
**Request:** `OpenCargoTomlParams`
**Response:** `Location | null`
### Example
```rust
// Cargo.toml
[package]
// src/main.rs
/* cursor here*/
```
`experimental/openCargoToml` returns a single `Link` to the start of the `[package]` keyword.

View file

@ -187,6 +187,11 @@
"command": "rust-analyzer.openDocs", "command": "rust-analyzer.openDocs",
"title": "Open docs under cursor", "title": "Open docs under cursor",
"category": "Rust Analyzer" "category": "Rust Analyzer"
},
{
"command": "rust-analyzer.openCargoToml",
"title": "Open Cargo.toml",
"category": "Rust Analyzer"
} }
], ],
"keybindings": [ "keybindings": [
@ -1065,6 +1070,10 @@
{ {
"command": "rust-analyzer.openDocs", "command": "rust-analyzer.openDocs",
"when": "inRustProject" "when": "inRustProject"
},
{
"command": "rust-analyzer.openCargoToml",
"when": "inRustProject"
} }
] ]
} }

View file

@ -188,6 +188,27 @@ export function parentModule(ctx: Ctx): Cmd {
}; };
} }
export function openCargoToml(ctx: Ctx): Cmd {
return async () => {
const editor = ctx.activeRustEditor;
const client = ctx.client;
if (!editor || !client) return;
const response = await client.sendRequest(ra.openCargoToml, {
textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
});
if (!response) return;
const uri = client.protocol2CodeConverter.asUri(response.uri);
const range = client.protocol2CodeConverter.asRange(response.range);
const doc = await vscode.workspace.openTextDocument(uri);
const e = await vscode.window.showTextDocument(doc);
e.selection = new vscode.Selection(range.start, range.start);
e.revealRange(range, vscode.TextEditorRevealType.InCenter);
};
}
export function ssr(ctx: Ctx): Cmd { export function ssr(ctx: Ctx): Cmd {
return async () => { return async () => {
const editor = vscode.window.activeTextEditor; const editor = vscode.window.activeTextEditor;

View file

@ -114,3 +114,9 @@ export interface CommandLinkGroup {
} }
export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, string | void, void>('experimental/externalDocs'); export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, string | void, void>('experimental/externalDocs');
export const openCargoToml = new lc.RequestType<OpenCargoTomlParams, lc.Location, void>("experimental/openCargoToml");
export interface OpenCargoTomlParams {
textDocument: lc.TextDocumentIdentifier;
}

View file

@ -111,6 +111,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
ctx.registerCommand('debug', commands.debug); ctx.registerCommand('debug', commands.debug);
ctx.registerCommand('newDebugConfig', commands.newDebugConfig); ctx.registerCommand('newDebugConfig', commands.newDebugConfig);
ctx.registerCommand('openDocs', commands.openDocs); ctx.registerCommand('openDocs', commands.openDocs);
ctx.registerCommand('openCargoToml', commands.openCargoToml);
defaultOnEnter.dispose(); defaultOnEnter.dispose();
ctx.registerCommand('onEnter', commands.onEnter); ctx.registerCommand('onEnter', commands.onEnter);