From 4a013ec62d2dfacaf6010b08c96947aa38481721 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 25 May 2020 10:59:54 +0200 Subject: [PATCH 1/3] Remove dead code --- editors/code/src/commands/index.ts | 52 +------------------------- editors/code/src/commands/on_enter.ts | 2 +- editors/code/src/snippets.ts | 52 ++++++++++++++++++++++++++ editors/code/src/source_change.ts | 54 --------------------------- 4 files changed, 54 insertions(+), 106 deletions(-) create mode 100644 editors/code/src/snippets.ts delete mode 100644 editors/code/src/source_change.ts diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index c2a232d5fd..1ed8258d86 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -3,8 +3,7 @@ import * as lc from 'vscode-languageclient'; import * as ra from '../rust-analyzer-api'; import { Ctx, Cmd } from '../ctx'; -import * as sourceChange from '../source_change'; -import { assert } from '../util'; +import { applySnippetWorkspaceEdit } from '../snippets'; export * from './analyzer_status'; export * from './matching_brace'; @@ -55,52 +54,3 @@ export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd { await applySnippetWorkspaceEdit(edit); }; } - -export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) { - assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); - const [uri, edits] = edit.entries()[0]; - - const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); - if (!editor) return; - - let selection: vscode.Selection | undefined = undefined; - let lineDelta = 0; - await editor.edit((builder) => { - for (const indel of edits) { - const parsed = parseSnippet(indel.newText); - if (parsed) { - const [newText, [placeholderStart, placeholderLength]] = parsed; - const prefix = newText.substr(0, placeholderStart); - const lastNewline = prefix.lastIndexOf('\n'); - - const startLine = indel.range.start.line + lineDelta + countLines(prefix); - const startColumn = lastNewline === -1 ? - indel.range.start.character + placeholderStart - : prefix.length - lastNewline - 1; - const endColumn = startColumn + placeholderLength; - selection = new vscode.Selection( - new vscode.Position(startLine, startColumn), - new vscode.Position(startLine, endColumn), - ); - builder.replace(indel.range, newText); - } else { - lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line); - builder.replace(indel.range, indel.newText); - } - } - }); - if (selection) editor.selection = selection; -} - -function parseSnippet(snip: string): [string, [number, number]] | undefined { - const m = snip.match(/\$(0|\{0:([^}]*)\})/); - if (!m) return undefined; - const placeholder = m[2] ?? ""; - const range: [number, number] = [m.index!!, placeholder.length]; - const insert = snip.replace(m[0], placeholder); - return [insert, range]; -} - -function countLines(text: string): number { - return (text.match(/\n/g) || []).length; -} diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts index a7871c31ee..0e4769633b 100644 --- a/editors/code/src/commands/on_enter.ts +++ b/editors/code/src/commands/on_enter.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import * as ra from '../rust-analyzer-api'; import { Cmd, Ctx } from '../ctx'; -import { applySnippetWorkspaceEdit } from '.'; +import { applySnippetWorkspaceEdit } from '../snippets'; async function handleKeypress(ctx: Ctx) { const editor = ctx.activeRustEditor; diff --git a/editors/code/src/snippets.ts b/editors/code/src/snippets.ts new file mode 100644 index 0000000000..794530162d --- /dev/null +++ b/editors/code/src/snippets.ts @@ -0,0 +1,52 @@ +import * as vscode from 'vscode'; + +import { assert } from './util'; + +export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) { + assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); + const [uri, edits] = edit.entries()[0]; + + const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); + if (!editor) return; + + let selection: vscode.Selection | undefined = undefined; + let lineDelta = 0; + await editor.edit((builder) => { + for (const indel of edits) { + const parsed = parseSnippet(indel.newText); + if (parsed) { + const [newText, [placeholderStart, placeholderLength]] = parsed; + const prefix = newText.substr(0, placeholderStart); + const lastNewline = prefix.lastIndexOf('\n'); + + const startLine = indel.range.start.line + lineDelta + countLines(prefix); + const startColumn = lastNewline === -1 ? + indel.range.start.character + placeholderStart + : prefix.length - lastNewline - 1; + const endColumn = startColumn + placeholderLength; + selection = new vscode.Selection( + new vscode.Position(startLine, startColumn), + new vscode.Position(startLine, endColumn), + ); + builder.replace(indel.range, newText); + } else { + lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line); + builder.replace(indel.range, indel.newText); + } + } + }); + if (selection) editor.selection = selection; +} + +function parseSnippet(snip: string): [string, [number, number]] | undefined { + const m = snip.match(/\$(0|\{0:([^}]*)\})/); + if (!m) return undefined; + const placeholder = m[2] ?? ""; + const range: [number, number] = [m.index!!, placeholder.length]; + const insert = snip.replace(m[0], placeholder); + return [insert, range]; +} + +function countLines(text: string): number { + return (text.match(/\n/g) || []).length; +} diff --git a/editors/code/src/source_change.ts b/editors/code/src/source_change.ts deleted file mode 100644 index af8f1df511..0000000000 --- a/editors/code/src/source_change.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as vscode from 'vscode'; -import * as lc from 'vscode-languageclient'; -import * as ra from './rust-analyzer-api'; - -import { Ctx } from './ctx'; - -export async function applySourceChange(ctx: Ctx, change: ra.SourceChange) { - const client = ctx.client; - if (!client) return; - - const wsEdit = client.protocol2CodeConverter.asWorkspaceEdit( - change.workspaceEdit, - ); - let created; - let moved; - if (change.workspaceEdit.documentChanges) { - for (const docChange of change.workspaceEdit.documentChanges) { - if (lc.CreateFile.is(docChange)) { - created = docChange.uri; - } else if (lc.RenameFile.is(docChange)) { - moved = docChange.newUri; - } - } - } - const toOpen = created || moved; - const toReveal = change.cursorPosition; - await vscode.workspace.applyEdit(wsEdit); - if (toOpen) { - const toOpenUri = vscode.Uri.parse(toOpen); - const doc = await vscode.workspace.openTextDocument(toOpenUri); - await vscode.window.showTextDocument(doc); - } else if (toReveal) { - const uri = client.protocol2CodeConverter.asUri( - toReveal.textDocument.uri, - ); - const position = client.protocol2CodeConverter.asPosition( - toReveal.position, - ); - const editor = vscode.window.activeTextEditor; - if (!editor || !editor.selection.isEmpty) { - return; - } - - if (editor.document.uri !== uri) { - const doc = await vscode.workspace.openTextDocument(uri); - await vscode.window.showTextDocument(doc); - } - editor.selection = new vscode.Selection(position, position); - editor.revealRange( - new vscode.Range(position, position), - vscode.TextEditorRevealType.Default, - ); - } -} From 021b3da6721df7eaad2eb87024d2b0da28d60ade Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 25 May 2020 11:10:31 +0200 Subject: [PATCH 2/3] Flatten simple commands --- editors/code/src/commands/analyzer_status.ts | 51 ---- editors/code/src/commands/expand_macro.ts | 66 ----- editors/code/src/commands/index.ts | 257 +++++++++++++++++- editors/code/src/commands/join_lines.ts | 22 -- editors/code/src/commands/matching_brace.ts | 27 -- editors/code/src/commands/on_enter.ts | 35 --- editors/code/src/commands/parent_module.ts | 29 -- editors/code/src/commands/server_version.ts | 15 - editors/code/src/commands/ssr.ts | 30 -- .../code/src/commands/toggle_inlay_hints.ts | 11 - 10 files changed, 242 insertions(+), 301 deletions(-) delete mode 100644 editors/code/src/commands/analyzer_status.ts delete mode 100644 editors/code/src/commands/expand_macro.ts delete mode 100644 editors/code/src/commands/join_lines.ts delete mode 100644 editors/code/src/commands/matching_brace.ts delete mode 100644 editors/code/src/commands/on_enter.ts delete mode 100644 editors/code/src/commands/parent_module.ts delete mode 100644 editors/code/src/commands/server_version.ts delete mode 100644 editors/code/src/commands/ssr.ts delete mode 100644 editors/code/src/commands/toggle_inlay_hints.ts diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts deleted file mode 100644 index 09daa3402c..0000000000 --- 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 23f2ef1d5e..0000000000 --- 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 1ed8258d86..1585912a2b 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 0bf1ee6e67..0000000000 --- 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 9c418b887c..0000000000 --- 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 0e4769633b..0000000000 --- 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 8f78ddd71c..0000000000 --- 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 d64ac726e2..0000000000 --- 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 5d40a64d28..0000000000 --- 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 7606af8d0c..0000000000 --- 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); - }; -} From 6058b8b0f6a24ad5b905d99d780a31b9e3d578d7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 25 May 2020 12:02:30 +0200 Subject: [PATCH 3/3] Flatten commands.ts --- .../syntax_tree.ts => ast_inspector.ts} | 88 +---------------- .../src/{commands/index.ts => commands.ts} | 97 ++++++++++++++++++- editors/code/src/main.ts | 1 - .../src/{commands/runnables.ts => run.ts} | 26 ++--- 4 files changed, 103 insertions(+), 109 deletions(-) rename editors/code/src/{commands/syntax_tree.ts => ast_inspector.ts} (67%) rename editors/code/src/{commands/index.ts => commands.ts} (72%) rename editors/code/src/{commands/runnables.ts => run.ts} (88%) diff --git a/editors/code/src/commands/syntax_tree.ts b/editors/code/src/ast_inspector.ts similarity index 67% rename from editors/code/src/commands/syntax_tree.ts rename to editors/code/src/ast_inspector.ts index a5446c3272..4fdd167bd5 100644 --- a/editors/code/src/commands/syntax_tree.ts +++ b/editors/code/src/ast_inspector.ts @@ -1,93 +1,15 @@ import * as vscode from 'vscode'; -import * as ra from '../rust-analyzer-api'; - -import { Ctx, Cmd, Disposable } from '../ctx'; -import { isRustDocument, RustEditor, isRustEditor, sleep } from '../util'; - -const AST_FILE_SCHEME = "rust-analyzer"; - -// Opens the virtual file that will show the syntax tree -// -// The contents of the file come from the `TextDocumentContentProvider` -export function syntaxTree(ctx: Ctx): Cmd { - const tdcp = new TextDocumentContentProvider(ctx); - - void new AstInspector(ctx); - - ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider(AST_FILE_SCHEME, tdcp)); - ctx.pushCleanup(vscode.languages.setLanguageConfiguration("ra_syntax_tree", { - brackets: [["[", ")"]], - })); - - return async () => { - const editor = vscode.window.activeTextEditor; - const rangeEnabled = !!editor && !editor.selection.isEmpty; - - const uri = rangeEnabled - ? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`) - : tdcp.uri; - - const document = await vscode.workspace.openTextDocument(uri); - - tdcp.eventEmitter.fire(uri); - - void await vscode.window.showTextDocument(document, { - viewColumn: vscode.ViewColumn.Two, - preserveFocus: true - }); - }; -} - -class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { - readonly uri = vscode.Uri.parse('rust-analyzer://syntaxtree/tree.rast'); - readonly eventEmitter = new vscode.EventEmitter(); - - - constructor(private readonly ctx: Ctx) { - 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 { - const rustEditor = this.ctx.activeRustEditor; - if (!rustEditor) return ''; - - // When the range based query is enabled we take the range of the selection - const range = uri.query === 'range=true' && !rustEditor.selection.isEmpty - ? this.ctx.client.code2ProtocolConverter.asRange(rustEditor.selection) - : null; - - const params = { textDocument: { uri: rustEditor.document.uri.toString() }, range, }; - return this.ctx.client.sendRequest(ra.syntaxTree, params, ct); - } - - get onDidChange(): vscode.Event { - return this.eventEmitter.event; - } -} +import { Ctx, Disposable } from './ctx'; +import { RustEditor, isRustEditor } from './util'; // FIXME: consider implementing this via the Tree View API? // https://code.visualstudio.com/api/extension-guides/tree-view -class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, Disposable { +export class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, Disposable { private readonly astDecorationType = vscode.window.createTextEditorDecorationType({ borderColor: new vscode.ThemeColor('rust_analyzer.syntaxTreeBorder'), borderStyle: "solid", borderWidth: "2px", - }); private rustEditor: undefined | RustEditor; @@ -113,7 +35,7 @@ class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, D }); constructor(ctx: Ctx) { - ctx.pushCleanup(vscode.languages.registerHoverProvider({ scheme: AST_FILE_SCHEME }, this)); + ctx.pushCleanup(vscode.languages.registerHoverProvider({ scheme: 'rust-analyzer' }, this)); ctx.pushCleanup(vscode.languages.registerDefinitionProvider({ language: "rust" }, this)); vscode.workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, ctx.subscriptions); vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions); @@ -146,7 +68,7 @@ class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, D } private findAstTextEditor(): undefined | vscode.TextEditor { - return vscode.window.visibleTextEditors.find(it => it.document.uri.scheme === AST_FILE_SCHEME); + return vscode.window.visibleTextEditors.find(it => it.document.uri.scheme === 'rust-analyzer'); } private setRustEditor(newRustEditor: undefined | RustEditor) { diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands.ts similarity index 72% rename from editors/code/src/commands/index.ts rename to editors/code/src/commands.ts index 1585912a2b..573af5aa58 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands.ts @@ -1,13 +1,16 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; -import * as ra from '../rust-analyzer-api'; +import * as ra from './rust-analyzer-api'; -import { Ctx, Cmd } from '../ctx'; -import { applySnippetWorkspaceEdit } from '../snippets'; +import { Ctx, Cmd } from './ctx'; +import { applySnippetWorkspaceEdit } from './snippets'; import { spawnSync } from 'child_process'; +import { RunnableQuickPick, selectRunnable, createTask } from './run'; +import { AstInspector } from './ast_inspector'; +import { isRustDocument, sleep, isRustEditor } from './util'; -export * from './syntax_tree'; -export * from './runnables'; +export * from './ast_inspector'; +export * from './run'; export function analyzerStatus(ctx: Ctx): Cmd { const tdcp = new class implements vscode.TextDocumentContentProvider { @@ -194,6 +197,90 @@ export function toggleInlayHints(ctx: Ctx): Cmd { }; } +export function run(ctx: Ctx): Cmd { + let prevRunnable: RunnableQuickPick | undefined; + + return async () => { + const item = await selectRunnable(ctx, prevRunnable); + if (!item) return; + + item.detail = 'rerun'; + prevRunnable = item; + const task = createTask(item.runnable); + return await vscode.tasks.executeTask(task); + }; +} + +// Opens the virtual file that will show the syntax tree +// +// The contents of the file come from the `TextDocumentContentProvider` +export function syntaxTree(ctx: Ctx): Cmd { + const tdcp = new class implements vscode.TextDocumentContentProvider { + readonly uri = vscode.Uri.parse('rust-analyzer://syntaxtree/tree.rast'); + readonly eventEmitter = new vscode.EventEmitter(); + 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 { + const rustEditor = ctx.activeRustEditor; + if (!rustEditor) return ''; + + // When the range based query is enabled we take the range of the selection + const range = uri.query === 'range=true' && !rustEditor.selection.isEmpty + ? ctx.client.code2ProtocolConverter.asRange(rustEditor.selection) + : null; + + const params = { textDocument: { uri: rustEditor.document.uri.toString() }, range, }; + return ctx.client.sendRequest(ra.syntaxTree, params, ct); + } + + get onDidChange(): vscode.Event { + return this.eventEmitter.event; + } + }; + + void new AstInspector(ctx); + + ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp)); + ctx.pushCleanup(vscode.languages.setLanguageConfiguration("ra_syntax_tree", { + brackets: [["[", ")"]], + })); + + return async () => { + const editor = vscode.window.activeTextEditor; + const rangeEnabled = !!editor && !editor.selection.isEmpty; + + const uri = rangeEnabled + ? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`) + : tdcp.uri; + + const document = await vscode.workspace.openTextDocument(uri); + + tdcp.eventEmitter.fire(uri); + + void await vscode.window.showTextDocument(document, { + viewColumn: vscode.ViewColumn.Two, + preserveFocus: true + }); + }; +} + + // Opens the virtual file that will show the syntax tree // // The contents of the file come from the `TextDocumentContentProvider` diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 0e5a206410..31ac81ee88 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -92,7 +92,6 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('runSingle', commands.runSingle); ctx.registerCommand('debugSingle', commands.debugSingle); ctx.registerCommand('showReferences', commands.showReferences); - ctx.registerCommand('applySourceChange', commands.applySourceChange); ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); ctx.registerCommand('applyActionGroup', commands.applyActionGroup); diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/run.ts similarity index 88% rename from editors/code/src/commands/runnables.ts rename to editors/code/src/run.ts index 0bd30fb077..8f0487d74a 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/run.ts @@ -1,13 +1,13 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; -import * as ra from '../rust-analyzer-api'; +import * as ra from './rust-analyzer-api'; -import { Ctx, Cmd } from '../ctx'; -import { startDebugSession, getDebugConfiguration } from '../debug'; +import { Ctx, Cmd } from './ctx'; +import { startDebugSession, getDebugConfiguration } from './debug'; const quickPickButtons = [{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configurtation." }]; -async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debuggeeOnly = false, showButtons: boolean = true): Promise { +export async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debuggeeOnly = false, showButtons: boolean = true): Promise { const editor = ctx.activeRustEditor; const client = ctx.client; if (!editor || !client) return; @@ -83,20 +83,6 @@ async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debugg }); } -export function run(ctx: Ctx): Cmd { - let prevRunnable: RunnableQuickPick | undefined; - - return async () => { - const item = await selectRunnable(ctx, prevRunnable); - if (!item) return; - - item.detail = 'rerun'; - prevRunnable = item; - const task = createTask(item.runnable); - return await vscode.tasks.executeTask(task); - }; -} - export function runSingle(ctx: Ctx): Cmd { return async (runnable: ra.Runnable) => { const editor = ctx.activeRustEditor; @@ -165,7 +151,7 @@ export function newDebugConfig(ctx: Ctx): Cmd { }; } -class RunnableQuickPick implements vscode.QuickPickItem { +export class RunnableQuickPick implements vscode.QuickPickItem { public label: string; public description?: string | undefined; public detail?: string | undefined; @@ -184,7 +170,7 @@ interface CargoTaskDefinition extends vscode.TaskDefinition { env?: { [key: string]: string }; } -function createTask(spec: ra.Runnable): vscode.Task { +export function createTask(spec: ra.Runnable): vscode.Task { const TASK_SOURCE = 'Rust'; const definition: CargoTaskDefinition = { type: 'cargo',