about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonas.schievink@ferrous-systems.com>2022-03-31 14:50:33 +0200
committerJonas Schievink <jonas.schievink@ferrous-systems.com>2022-03-31 14:50:33 +0200
commitec2d0233831cdd1d88a0d0be43534a014c3e4899 (patch)
tree045d7021543058b40ecbf3b9ccd40928f63bf7c2
parent259182b50b131647975926e8c94aad4c47d33747 (diff)
Add "view file text" command to debug sync issues
-rw-r--r--crates/rust-analyzer/src/handlers.rs8
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs8
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--docs/dev/lsp-extensions.md13
-rw-r--r--editors/code/package.json9
-rw-r--r--editors/code/src/commands.ts48
-rw-r--r--editors/code/src/lsp_ext.ts2
-rw-r--r--editors/code/src/main.ts1
8 files changed, 89 insertions, 1 deletions
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 8f91f64a69a..15f49783678 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -123,6 +123,14 @@ pub(crate) fn handle_view_hir(
     Ok(res)
 }
 
+pub(crate) fn handle_view_file_text(
+    snap: GlobalStateSnapshot,
+    params: lsp_types::TextDocumentIdentifier,
+) -> Result<String> {
+    let file_id = from_proto::file_id(&snap, &params.uri)?;
+    Ok(snap.analysis.file_text(file_id)?.to_string())
+}
+
 pub(crate) fn handle_view_item_tree(
     snap: GlobalStateSnapshot,
     params: lsp_ext::ViewItemTreeParams,
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 2e131eeac95..b638a571113 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -70,6 +70,14 @@ impl Request for ViewHir {
     const METHOD: &'static str = "rust-analyzer/viewHir";
 }
 
+pub enum ViewFileText {}
+
+impl Request for ViewFileText {
+    type Params = lsp_types::TextDocumentIdentifier;
+    type Result = String;
+    const METHOD: &'static str = "rust-analyzer/viewFileText";
+}
+
 #[derive(Deserialize, Serialize, Debug)]
 #[serde(rename_all = "camelCase")]
 pub struct ViewCrateGraphParams {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index b62a830803b..2d898d76a6d 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -590,6 +590,7 @@ impl GlobalState {
             .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)
             .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
             .on::<lsp_ext::ViewHir>(handlers::handle_view_hir)
+            .on::<lsp_ext::ViewFileText>(handlers::handle_view_file_text)
             .on::<lsp_ext::ViewCrateGraph>(handlers::handle_view_crate_graph)
             .on::<lsp_ext::ViewItemTree>(handlers::handle_view_item_tree)
             .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 3091bdcbf07..516d1caccc3 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 854109e98d02a780
+lsp_ext.rs hash: a61de7db4504a4d1
 
 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:
@@ -494,6 +494,17 @@ Primarily for debugging, but very useful for all people working on rust-analyzer
 Returns a textual representation of the HIR of the function containing the cursor.
 For debugging or when working on rust-analyzer itself.
 
+## View File Text
+
+**Method:** `rust-analyzer/viewFileText`
+
+**Request:** `TextDocumentIdentifier`
+
+**Response:** `string`
+
+Returns the text of a file as seen by the server.
+This is for debugging file sync problems.
+
 ## View ItemTree
 
 **Method:** `rust-analyzer/viewItemTree`
diff --git a/editors/code/package.json b/editors/code/package.json
index c55ef6f0f7c..7df00d2ef2c 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -105,6 +105,11 @@
                 "category": "Rust Analyzer"
             },
             {
+                "command": "rust-analyzer.viewFileText",
+                "title": "View File Text (as seen by the server)",
+                "category": "Rust Analyzer"
+            },
+            {
                 "command": "rust-analyzer.viewItemTree",
                 "title": "Debug ItemTree",
                 "category": "Rust Analyzer"
@@ -1409,6 +1414,10 @@
                     "when": "inRustProject"
                 },
                 {
+                    "command": "rust-analyzer.viewFileText",
+                    "when": "inRustProject"
+                },
+                {
                     "command": "rust-analyzer.expandMacro",
                     "when": "inRustProject"
                 },
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index fe006a63e27..2802668be30 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -432,6 +432,54 @@ export function viewHir(ctx: Ctx): Cmd {
     };
 }
 
+export function viewFileText(ctx: Ctx): Cmd {
+    const tdcp = new class implements vscode.TextDocumentContentProvider {
+        readonly uri = vscode.Uri.parse('rust-analyzer://viewFileText/file.rs');
+        readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
+        constructor() {
+            vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions);
+            vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, ctx.subscriptions);
+        }
+
+        private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
+            if (isRustDocument(event.document)) {
+                // We need to order this after language server updates, but there's no API for that.
+                // Hence, good old sleep().
+                void sleep(10).then(() => this.eventEmitter.fire(this.uri));
+            }
+        }
+        private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
+            if (editor && isRustEditor(editor)) {
+                this.eventEmitter.fire(this.uri);
+            }
+        }
+
+        provideTextDocumentContent(_uri: vscode.Uri, ct: vscode.CancellationToken): vscode.ProviderResult<string> {
+            const rustEditor = ctx.activeRustEditor;
+            const client = ctx.client;
+            if (!rustEditor || !client) return '';
+
+            const params = client.code2ProtocolConverter.asTextDocumentIdentifier(rustEditor.document);
+            return client.sendRequest(ra.viewFileText, params, ct);
+        }
+
+        get onDidChange(): vscode.Event<vscode.Uri> {
+            return this.eventEmitter.event;
+        }
+    };
+
+    ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp));
+
+    return async () => {
+        const document = await vscode.workspace.openTextDocument(tdcp.uri);
+        tdcp.eventEmitter.fire(tdcp.uri);
+        void await vscode.window.showTextDocument(document, {
+            viewColumn: vscode.ViewColumn.Two,
+            preserveFocus: true
+        });
+    };
+}
+
 export function viewItemTree(ctx: Ctx): Cmd {
     const tdcp = new class implements vscode.TextDocumentContentProvider {
         readonly uri = vscode.Uri.parse('rust-analyzer://viewItemTree/itemtree.rs');
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 9493a034819..0ae5e93a73f 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -36,6 +36,8 @@ export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("ru
 
 export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir");
 
+export const viewFileText = new lc.RequestType<lc.TextDocumentIdentifier, string, void>("rust-analyzer/viewFileText");
+
 export interface ViewItemTreeParams {
     textDocument: lc.TextDocumentIdentifier;
 }
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 06e5c1185d1..36a095bdd36 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -114,6 +114,7 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
     ctx.registerCommand('parentModule', commands.parentModule);
     ctx.registerCommand('syntaxTree', commands.syntaxTree);
     ctx.registerCommand('viewHir', commands.viewHir);
+    ctx.registerCommand('viewFileText', commands.viewFileText);
     ctx.registerCommand('viewItemTree', commands.viewItemTree);
     ctx.registerCommand('viewCrateGraph', commands.viewCrateGraph);
     ctx.registerCommand('viewFullCrateGraph', commands.viewFullCrateGraph);