diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts deleted file mode 100644 index 09daa3402cf..00000000000 --- a/editors/code/src/commands/analyzer_status.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as vscode from 'vscode'; - -import * as ra from '../rust-analyzer-api'; -import { Ctx, Cmd } from '../ctx'; - -// Shows status of rust-analyzer (for debugging) -export function analyzerStatus(ctx: Ctx): Cmd { - let poller: NodeJS.Timer | undefined = undefined; - const tdcp = new TextDocumentContentProvider(ctx); - - ctx.pushCleanup( - vscode.workspace.registerTextDocumentContentProvider( - 'rust-analyzer-status', - tdcp, - ), - ); - - ctx.pushCleanup({ - dispose() { - if (poller !== undefined) { - clearInterval(poller); - } - }, - }); - - return async () => { - if (poller === undefined) { - poller = setInterval(() => tdcp.eventEmitter.fire(tdcp.uri), 1000); - } - const document = await vscode.workspace.openTextDocument(tdcp.uri); - return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true); - }; -} - -class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { - readonly uri = vscode.Uri.parse('rust-analyzer-status://status'); - readonly eventEmitter = new vscode.EventEmitter(); - - constructor(private readonly ctx: Ctx) { - } - - provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult { - if (!vscode.window.activeTextEditor) return ''; - - return this.ctx.client.sendRequest(ra.analyzerStatus, null); - } - - get onDidChange(): vscode.Event { - return this.eventEmitter.event; - } -} diff --git a/editors/code/src/commands/expand_macro.ts b/editors/code/src/commands/expand_macro.ts deleted file mode 100644 index 23f2ef1d5e3..00000000000 --- a/editors/code/src/commands/expand_macro.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from '../rust-analyzer-api'; - -import { Ctx, Cmd } from '../ctx'; - -// Opens the virtual file that will show the syntax tree -// -// The contents of the file come from the `TextDocumentContentProvider` -export function expandMacro(ctx: Ctx): Cmd { - const tdcp = new TextDocumentContentProvider(ctx); - ctx.pushCleanup( - vscode.workspace.registerTextDocumentContentProvider( - 'rust-analyzer', - tdcp, - ), - ); - - return async () => { - const document = await vscode.workspace.openTextDocument(tdcp.uri); - tdcp.eventEmitter.fire(tdcp.uri); - return vscode.window.showTextDocument( - document, - vscode.ViewColumn.Two, - true, - ); - }; -} - -function codeFormat(expanded: ra.ExpandedMacro): string { - let result = `// Recursive expansion of ${expanded.name}! macro\n`; - result += '// ' + '='.repeat(result.length - 3); - result += '\n\n'; - result += expanded.expansion; - - return result; -} - -class TextDocumentContentProvider - implements vscode.TextDocumentContentProvider { - uri = vscode.Uri.parse('rust-analyzer://expandMacro/[EXPANSION].rs'); - eventEmitter = new vscode.EventEmitter(); - - constructor(private readonly ctx: Ctx) { - } - - async provideTextDocumentContent(_uri: vscode.Uri): Promise { - const editor = vscode.window.activeTextEditor; - const client = this.ctx.client; - if (!editor || !client) return ''; - - const position = editor.selection.active; - - const expanded = await client.sendRequest(ra.expandMacro, { - textDocument: { uri: editor.document.uri.toString() }, - position, - }); - - if (expanded == null) return 'Not available'; - - return codeFormat(expanded); - } - - get onDidChange(): vscode.Event { - return this.eventEmitter.event; - } -} diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index 1ed8258d867..1585912a2b7 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -4,18 +4,251 @@ import * as ra from '../rust-analyzer-api'; import { Ctx, Cmd } from '../ctx'; import { applySnippetWorkspaceEdit } from '../snippets'; +import { spawnSync } from 'child_process'; -export * from './analyzer_status'; -export * from './matching_brace'; -export * from './join_lines'; -export * from './on_enter'; -export * from './parent_module'; export * from './syntax_tree'; -export * from './expand_macro'; export * from './runnables'; -export * from './ssr'; -export * from './server_version'; -export * from './toggle_inlay_hints'; + +export function analyzerStatus(ctx: Ctx): Cmd { + const tdcp = new class implements vscode.TextDocumentContentProvider { + readonly uri = vscode.Uri.parse('rust-analyzer-status://status'); + readonly eventEmitter = new vscode.EventEmitter(); + + provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult { + if (!vscode.window.activeTextEditor) return ''; + + return ctx.client.sendRequest(ra.analyzerStatus, null); + } + + get onDidChange(): vscode.Event { + return this.eventEmitter.event; + } + }(); + + let poller: NodeJS.Timer | undefined = undefined; + + ctx.pushCleanup( + vscode.workspace.registerTextDocumentContentProvider( + 'rust-analyzer-status', + tdcp, + ), + ); + + ctx.pushCleanup({ + dispose() { + if (poller !== undefined) { + clearInterval(poller); + } + }, + }); + + return async () => { + if (poller === undefined) { + poller = setInterval(() => tdcp.eventEmitter.fire(tdcp.uri), 1000); + } + const document = await vscode.workspace.openTextDocument(tdcp.uri); + return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true); + }; +} + +export function matchingBrace(ctx: Ctx): Cmd { + return async () => { + const editor = ctx.activeRustEditor; + const client = ctx.client; + if (!editor || !client) return; + + const response = await client.sendRequest(ra.matchingBrace, { + textDocument: { uri: editor.document.uri.toString() }, + positions: editor.selections.map(s => + client.code2ProtocolConverter.asPosition(s.active), + ), + }); + editor.selections = editor.selections.map((sel, idx) => { + const active = client.protocol2CodeConverter.asPosition( + response[idx], + ); + const anchor = sel.isEmpty ? active : sel.anchor; + return new vscode.Selection(anchor, active); + }); + editor.revealRange(editor.selection); + }; +} + +export function joinLines(ctx: Ctx): Cmd { + return async () => { + const editor = ctx.activeRustEditor; + const client = ctx.client; + if (!editor || !client) return; + + const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, { + ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), + textDocument: { uri: editor.document.uri.toString() }, + }); + editor.edit((builder) => { + client.protocol2CodeConverter.asTextEdits(items).forEach((edit) => { + builder.replace(edit.range, edit.newText); + }); + }); + }; +} + +export function onEnter(ctx: Ctx): Cmd { + async function handleKeypress() { + const editor = ctx.activeRustEditor; + const client = ctx.client; + + if (!editor || !client) return false; + + const change = await client.sendRequest(ra.onEnter, { + textDocument: { uri: editor.document.uri.toString() }, + position: client.code2ProtocolConverter.asPosition( + editor.selection.active, + ), + }).catch(_error => { + // client.logFailedRequest(OnEnterRequest.type, error); + return null; + }); + if (!change) return false; + + const workspaceEdit = client.protocol2CodeConverter.asWorkspaceEdit(change); + await applySnippetWorkspaceEdit(workspaceEdit); + return true; + } + + return async () => { + if (await handleKeypress()) return; + + await vscode.commands.executeCommand('default:type', { text: '\n' }); + }; +} + +export function parentModule(ctx: Ctx): Cmd { + return async () => { + const editor = ctx.activeRustEditor; + const client = ctx.client; + if (!editor || !client) return; + + const response = await client.sendRequest(ra.parentModule, { + textDocument: { uri: editor.document.uri.toString() }, + position: client.code2ProtocolConverter.asPosition( + editor.selection.active, + ), + }); + const loc = response[0]; + if (loc == null) return; + + const uri = client.protocol2CodeConverter.asUri(loc.uri); + const range = client.protocol2CodeConverter.asRange(loc.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 client = ctx.client; + if (!client) return; + + const options: vscode.InputBoxOptions = { + value: "() ==>> ()", + prompt: "Enter request, for example 'Foo($a:expr) ==> Foo::new($a)' ", + validateInput: async (x: string) => { + try { + await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); + } catch (e) { + return e.toString(); + } + return null; + } + }; + const request = await vscode.window.showInputBox(options); + if (!request) return; + + const edit = await client.sendRequest(ra.ssr, { query: request, parseOnly: false }); + + await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit)); + }; +} + +export function serverVersion(ctx: Ctx): Cmd { + return async () => { + const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); + const commitHash = stdout.slice(`rust-analyzer `.length).trim(); + const { releaseTag } = ctx.config.package; + + void vscode.window.showInformationMessage( + `rust-analyzer version: ${releaseTag ?? "unreleased"} (${commitHash})` + ); + }; +} + +export function toggleInlayHints(ctx: Ctx): Cmd { + return async () => { + await vscode + .workspace + .getConfiguration(`${ctx.config.rootSection}.inlayHints`) + .update('enable', !ctx.config.inlayHints.enable, vscode.ConfigurationTarget.Workspace); + }; +} + +// Opens the virtual file that will show the syntax tree +// +// The contents of the file come from the `TextDocumentContentProvider` +export function expandMacro(ctx: Ctx): Cmd { + function codeFormat(expanded: ra.ExpandedMacro): string { + let result = `// Recursive expansion of ${expanded.name}! macro\n`; + result += '// ' + '='.repeat(result.length - 3); + result += '\n\n'; + result += expanded.expansion; + + return result; + } + + const tdcp = new class implements vscode.TextDocumentContentProvider { + uri = vscode.Uri.parse('rust-analyzer://expandMacro/[EXPANSION].rs'); + eventEmitter = new vscode.EventEmitter(); + async provideTextDocumentContent(_uri: vscode.Uri): Promise { + const editor = vscode.window.activeTextEditor; + const client = ctx.client; + if (!editor || !client) return ''; + + const position = editor.selection.active; + + const expanded = await client.sendRequest(ra.expandMacro, { + textDocument: { uri: editor.document.uri.toString() }, + position, + }); + + if (expanded == null) return 'Not available'; + + return codeFormat(expanded); + } + + get onDidChange(): vscode.Event { + 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); + return vscode.window.showTextDocument( + document, + vscode.ViewColumn.Two, + true, + ); + }; +} export function collectGarbage(ctx: Ctx): Cmd { return async () => ctx.client.sendRequest(ra.collectGarbage, null); @@ -35,12 +268,6 @@ export function showReferences(ctx: Ctx): Cmd { }; } -export function applySourceChange(ctx: Ctx): Cmd { - return async (change: ra.SourceChange) => { - await sourceChange.applySourceChange(ctx, change); - }; -} - export function applyActionGroup(_ctx: Ctx): Cmd { return async (actions: { label: string; edit: vscode.WorkspaceEdit }[]) => { const selectedAction = await vscode.window.showQuickPick(actions); diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts deleted file mode 100644 index 0bf1ee6e671..00000000000 --- a/editors/code/src/commands/join_lines.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as ra from '../rust-analyzer-api'; -import * as lc from 'vscode-languageclient'; - -import { Ctx, Cmd } from '../ctx'; - -export function joinLines(ctx: Ctx): Cmd { - return async () => { - const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; - - const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, { - ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), - textDocument: { uri: editor.document.uri.toString() }, - }); - editor.edit((builder) => { - client.protocol2CodeConverter.asTextEdits(items).forEach((edit) => { - builder.replace(edit.range, edit.newText); - }); - }); - }; -} diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts deleted file mode 100644 index 9c418b887c2..00000000000 --- a/editors/code/src/commands/matching_brace.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from '../rust-analyzer-api'; - -import { Ctx, Cmd } from '../ctx'; - -export function matchingBrace(ctx: Ctx): Cmd { - return async () => { - const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; - - const response = await client.sendRequest(ra.matchingBrace, { - textDocument: { uri: editor.document.uri.toString() }, - positions: editor.selections.map(s => - client.code2ProtocolConverter.asPosition(s.active), - ), - }); - editor.selections = editor.selections.map((sel, idx) => { - const active = client.protocol2CodeConverter.asPosition( - response[idx], - ); - const anchor = sel.isEmpty ? active : sel.anchor; - return new vscode.Selection(anchor, active); - }); - editor.revealRange(editor.selection); - }; -} diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts deleted file mode 100644 index 0e4769633b7..00000000000 --- a/editors/code/src/commands/on_enter.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from '../rust-analyzer-api'; - -import { Cmd, Ctx } from '../ctx'; -import { applySnippetWorkspaceEdit } from '../snippets'; - -async function handleKeypress(ctx: Ctx) { - const editor = ctx.activeRustEditor; - const client = ctx.client; - - if (!editor || !client) return false; - - const change = await client.sendRequest(ra.onEnter, { - textDocument: { uri: editor.document.uri.toString() }, - position: client.code2ProtocolConverter.asPosition( - editor.selection.active, - ), - }).catch(_error => { - // client.logFailedRequest(OnEnterRequest.type, error); - return null; - }); - if (!change) return false; - - const workspaceEdit = client.protocol2CodeConverter.asWorkspaceEdit(change); - await applySnippetWorkspaceEdit(workspaceEdit); - return true; -} - -export function onEnter(ctx: Ctx): Cmd { - return async () => { - if (await handleKeypress(ctx)) return; - - await vscode.commands.executeCommand('default:type', { text: '\n' }); - }; -} diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts deleted file mode 100644 index 8f78ddd71c6..00000000000 --- a/editors/code/src/commands/parent_module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from '../rust-analyzer-api'; - -import { Ctx, Cmd } from '../ctx'; - -export function parentModule(ctx: Ctx): Cmd { - return async () => { - const editor = ctx.activeRustEditor; - const client = ctx.client; - if (!editor || !client) return; - - const response = await client.sendRequest(ra.parentModule, { - textDocument: { uri: editor.document.uri.toString() }, - position: client.code2ProtocolConverter.asPosition( - editor.selection.active, - ), - }); - const loc = response[0]; - if (loc == null) return; - - const uri = client.protocol2CodeConverter.asUri(loc.uri); - const range = client.protocol2CodeConverter.asRange(loc.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); - }; -} diff --git a/editors/code/src/commands/server_version.ts b/editors/code/src/commands/server_version.ts deleted file mode 100644 index d64ac726e2c..00000000000 --- a/editors/code/src/commands/server_version.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as vscode from "vscode"; -import { spawnSync } from "child_process"; -import { Ctx, Cmd } from '../ctx'; - -export function serverVersion(ctx: Ctx): Cmd { - return async () => { - const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); - const commitHash = stdout.slice(`rust-analyzer `.length).trim(); - const { releaseTag } = ctx.config.package; - - void vscode.window.showInformationMessage( - `rust-analyzer version: ${releaseTag ?? "unreleased"} (${commitHash})` - ); - }; -} diff --git a/editors/code/src/commands/ssr.ts b/editors/code/src/commands/ssr.ts deleted file mode 100644 index 5d40a64d28e..00000000000 --- a/editors/code/src/commands/ssr.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as vscode from 'vscode'; -import * as ra from "../rust-analyzer-api"; - -import { Ctx, Cmd } from '../ctx'; - -export function ssr(ctx: Ctx): Cmd { - return async () => { - const client = ctx.client; - if (!client) return; - - const options: vscode.InputBoxOptions = { - value: "() ==>> ()", - prompt: "Enter request, for example 'Foo($a:expr) ==> Foo::new($a)' ", - validateInput: async (x: string) => { - try { - await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); - } catch (e) { - return e.toString(); - } - return null; - } - }; - const request = await vscode.window.showInputBox(options); - if (!request) return; - - const edit = await client.sendRequest(ra.ssr, { query: request, parseOnly: false }); - - await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit)); - }; -} diff --git a/editors/code/src/commands/toggle_inlay_hints.ts b/editors/code/src/commands/toggle_inlay_hints.ts deleted file mode 100644 index 7606af8d0cb..00000000000 --- a/editors/code/src/commands/toggle_inlay_hints.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as vscode from 'vscode'; -import { Ctx, Cmd } from '../ctx'; - -export function toggleInlayHints(ctx: Ctx): Cmd { - return async () => { - await vscode - .workspace - .getConfiguration(`${ctx.config.rootSection}.inlayHints`) - .update('enable', !ctx.config.inlayHints.enable, vscode.ConfigurationTarget.Workspace); - }; -}