about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAnatol Liu <axlui@anatols-mbp.lan>2020-11-12 17:48:07 -0800
committerAnatol Liu <axlui@anatols-mbp.lan>2020-11-12 17:48:07 -0800
commitb1b7727e046b4b25dcca034ee767a7fc3238409d (patch)
treec1942b7af1e73b139d2c62d1d81e8d6749dc8cd2
parent111cc34c8f181315f4dcfa85c616d54d47eff0b9 (diff)
downloadrust-b1b7727e046b4b25dcca034ee767a7fc3238409d.tar.gz
rust-b1b7727e046b4b25dcca034ee767a7fc3238409d.zip
add open Cargo.toml action
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock5
-rw-r--r--crates/hir_ty/Cargo.toml1
-rw-r--r--crates/hir_ty/src/tests.rs7
-rw-r--r--crates/ide/.DS_Storebin0 -> 6148 bytes
-rw-r--r--crates/rust-analyzer/src/config.rs9
-rw-r--r--crates/rust-analyzer/src/handlers.rs22
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs14
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/stdx/src/lib.rs30
-rw-r--r--docs/dev/lsp-extensions.md29
-rw-r--r--editors/code/package.json9
-rw-r--r--editors/code/src/commands.ts21
-rw-r--r--editors/code/src/lsp_ext.ts6
-rw-r--r--editors/code/src/main.ts1
15 files changed, 114 insertions, 42 deletions
diff --git a/.gitignore b/.gitignore
index b205bf3fb68..7e097c01585 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ crates/*/target
 generated_assists.adoc
 generated_features.adoc
 generated_diagnostic.adoc
+.DS_Store
diff --git a/Cargo.lock b/Cargo.lock
index 1a4a63550d1..c5645b2d255 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -612,6 +612,7 @@ dependencies = [
  "hir_expand",
  "itertools",
  "log",
+ "once_cell",
  "profile",
  "rustc-hash",
  "scoped-tls",
@@ -1053,9 +1054,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
 
 [[package]]
 name = "once_cell"
-version = "1.4.1"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
+checksum = "f53cef67919d7d247eb9a2f128ca9e522789967ef1eb4ccd8c71a95a8aedf596"
 
 [[package]]
 name = "oorandom"
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index fdc65a5c324..cf5c38a2357 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -35,3 +35,4 @@ expect-test = "1.0"
 tracing = "0.1"
 tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
 tracing-tree = { version = "0.1.4" }
+once_cell = { version = "1.5.0", features = ["unstable"] }
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 104ef334c68..0a400cb7050 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -22,7 +22,8 @@ use hir_def::{
     AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
 };
 use hir_expand::{db::AstDatabase, InFile};
-use stdx::{format_to, RacyFlag};
+use once_cell::race::OnceBool;
+use stdx::format_to;
 use syntax::{
     algo,
     ast::{self, AstNode},
@@ -40,8 +41,8 @@ use crate::{
 // `env UPDATE_EXPECT=1 cargo test -p hir_ty` to update the snapshots.
 
 fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
-    static ENABLE: RacyFlag = RacyFlag::new();
-    if !ENABLE.get(|| env::var("CHALK_DEBUG").is_ok()) {
+    static ENABLE: OnceBool = OnceBool::new();
+    if !ENABLE.get_or_init(|| env::var("CHALK_DEBUG").is_ok()) {
         return None;
     }
 
diff --git a/crates/ide/.DS_Store b/crates/ide/.DS_Store
new file mode 100644
index 00000000000..a566736aa9e
--- /dev/null
+++ b/crates/ide/.DS_Store
Binary files differdiff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index b4c738272b6..9cc14fe827b 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -385,13 +385,10 @@ impl Config {
             }
 
             if let Some(code_action) = &doc_caps.code_action {
-                match (code_action.data_support, &code_action.resolve_support) {
-                    (Some(true), Some(resolve_support)) => {
-                        if resolve_support.properties.iter().any(|it| it == "edit") {
-                            self.client_caps.code_action_resolve = true;
-                        }
+                if let Some(resolve_support) = &code_action.resolve_support {
+                    if resolve_support.properties.iter().any(|it| it == "edit") {
+                        self.client_caps.code_action_resolve = true;
                     }
-                    _ => (),
                 }
             }
         }
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 95659b0db9d..782797e85f7 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1322,6 +1322,28 @@ pub(crate) fn handle_open_docs(
     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 {
     if count == 1 {
         "1 implementation".into()
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index a7c3028e499..a5c65fa3e8b 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -354,3 +354,17 @@ impl Request for ExternalDocs {
     type Result = Option<lsp_types::Url>;
     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,
+}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 6e6cac42e03..68a53bbcb96 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -438,6 +438,7 @@ impl GlobalState {
             .on::<lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
             .on::<lsp_ext::HoverRequest>(handlers::handle_hover)
             .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::DocumentSymbolRequest>(handlers::handle_document_symbol)
             .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 59d89f47d1c..374ed59105d 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,8 +1,5 @@
 //! Missing batteries for standard libraries.
-use std::{
-    sync::atomic::{AtomicUsize, Ordering},
-    time::Instant,
-};
+use std::time::Instant;
 
 mod macros;
 pub mod panic_context;
@@ -150,31 +147,6 @@ where
     left
 }
 
-pub struct RacyFlag(AtomicUsize);
-
-impl RacyFlag {
-    pub const fn new() -> RacyFlag {
-        RacyFlag(AtomicUsize::new(!0))
-    }
-
-    pub fn get(&self, init: impl FnMut() -> bool) -> bool {
-        let mut init = Some(init);
-        self.get_impl(&mut || init.take().map_or(false, |mut f| f()))
-    }
-
-    fn get_impl(&self, init: &mut dyn FnMut() -> bool) -> bool {
-        match self.0.load(Ordering::Relaxed) {
-            0 => false,
-            1 => true,
-            _ => {
-                let res = init();
-                self.0.store(if res { 1 } else { 0 }, Ordering::Relaxed);
-                res
-            }
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 77d4e0ec996..db9727bee42 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -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
-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
 
@@ -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.
diff --git a/editors/code/package.json b/editors/code/package.json
index eccafccdd9e..b02c807734f 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -187,6 +187,11 @@
                 "command": "rust-analyzer.openDocs",
                 "title": "Open docs under cursor",
                 "category": "Rust Analyzer"
+            },
+            {
+                "command": "rust-analyzer.openCargoToml",
+                "title": "Open Cargo.toml",
+                "category": "Rust Analyzer"
             }
         ],
         "keybindings": [
@@ -1057,6 +1062,10 @@
                 {
                     "command": "rust-analyzer.openDocs",
                     "when": "inRustProject"
+                },
+                {
+                    "command": "rust-analyzer.openCargoToml",
+                    "when": "inRustProject"
                 }
             ]
         }
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index cf34622c341..92bc4d7f723 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -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 {
     return async () => {
         const editor = vscode.window.activeTextEditor;
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index d320c3cd718..5e877ce6511 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -114,3 +114,9 @@ export interface CommandLinkGroup {
 }
 
 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;
+}
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 09543e348a8..2f3dde8acd6 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -111,6 +111,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
     ctx.registerCommand('debug', commands.debug);
     ctx.registerCommand('newDebugConfig', commands.newDebugConfig);
     ctx.registerCommand('openDocs', commands.openDocs);
+    ctx.registerCommand('openCargoToml', commands.openCargoToml);
 
     defaultOnEnter.dispose();
     ctx.registerCommand('onEnter', commands.onEnter);