From 69de7e2fd71c3a808f0ac856d7b105eeb210f169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Sun, 7 Oct 2018 22:44:25 +0200 Subject: Refactor vscode extension --- editors/code/src/commands/apply_source_change.ts | 58 ++++++++++++++++ editors/code/src/commands/extend_selection.ts | 29 ++++++++ editors/code/src/commands/join_lines.ts | 21 ++++++ editors/code/src/commands/matching_brace.ts | 27 ++++++++ editors/code/src/commands/parent_module.ts | 22 ++++++ editors/code/src/commands/runnables.ts | 88 ++++++++++++++++++++++++ editors/code/src/commands/syntaxTree.ts | 38 ++++++++++ 7 files changed, 283 insertions(+) create mode 100644 editors/code/src/commands/apply_source_change.ts create mode 100644 editors/code/src/commands/extend_selection.ts create mode 100644 editors/code/src/commands/join_lines.ts create mode 100644 editors/code/src/commands/matching_brace.ts create mode 100644 editors/code/src/commands/parent_module.ts create mode 100644 editors/code/src/commands/runnables.ts create mode 100644 editors/code/src/commands/syntaxTree.ts (limited to 'editors/code/src/commands') diff --git a/editors/code/src/commands/apply_source_change.ts b/editors/code/src/commands/apply_source_change.ts new file mode 100644 index 000000000..dcbbb2b09 --- /dev/null +++ b/editors/code/src/commands/apply_source_change.ts @@ -0,0 +1,58 @@ +import * as vscode from 'vscode'; +import * as lc from 'vscode-languageclient' + +import { Server } from '../server'; + +interface FileSystemEdit { + type: string; + uri?: string; + src?: string; + dst?: string; +} + +export interface SourceChange { + label: string, + sourceFileEdits: lc.TextDocumentEdit[], + fileSystemEdits: FileSystemEdit[], + cursorPosition?: lc.TextDocumentPositionParams, +} + +export async function handle(change: SourceChange) { + console.log(`applySOurceChange ${JSON.stringify(change)}`) + let wsEdit = new vscode.WorkspaceEdit() + for (let sourceEdit of change.sourceFileEdits) { + let uri = Server.client.protocol2CodeConverter.asUri(sourceEdit.textDocument.uri) + let edits = Server.client.protocol2CodeConverter.asTextEdits(sourceEdit.edits) + wsEdit.set(uri, edits) + } + let created; + let moved; + for (let fsEdit of change.fileSystemEdits) { + if (fsEdit.type == "createFile") { + let uri = vscode.Uri.parse(fsEdit.uri!) + wsEdit.createFile(uri) + created = uri + } else if (fsEdit.type == "moveFile") { + let src = vscode.Uri.parse(fsEdit.src!) + let dst = vscode.Uri.parse(fsEdit.dst!) + wsEdit.renameFile(src, dst) + moved = dst + } else { + console.error(`unknown op: ${JSON.stringify(fsEdit)}`) + } + } + let toOpen = created || moved + let toReveal = change.cursorPosition + await vscode.workspace.applyEdit(wsEdit) + if (toOpen) { + let doc = await vscode.workspace.openTextDocument(toOpen) + await vscode.window.showTextDocument(doc) + } else if (toReveal) { + let uri = Server.client.protocol2CodeConverter.asUri(toReveal.textDocument.uri) + let position = Server.client.protocol2CodeConverter.asPosition(toReveal.position) + let editor = vscode.window.activeTextEditor; + if (!editor || editor.document.uri.toString() != uri.toString()) return + if (!editor.selection.isEmpty) return + editor!.selection = new vscode.Selection(position, position) + } +} diff --git a/editors/code/src/commands/extend_selection.ts b/editors/code/src/commands/extend_selection.ts new file mode 100644 index 000000000..b90828ba9 --- /dev/null +++ b/editors/code/src/commands/extend_selection.ts @@ -0,0 +1,29 @@ +import * as vscode from 'vscode'; + +import { TextDocumentIdentifier, Range } from "vscode-languageclient"; +import { Server } from '../server'; + +interface ExtendSelectionParams { + textDocument: TextDocumentIdentifier; + selections: Range[]; +} + +interface ExtendSelectionResult { + selections: Range[]; +} + +export async function handle() { + let editor = vscode.window.activeTextEditor + if (editor == null || editor.document.languageId != "rust") return + let request: ExtendSelectionParams = { + textDocument: { uri: editor.document.uri.toString() }, + selections: editor.selections.map((s) => { + return Server.client.code2ProtocolConverter.asRange(s) + }) + } + let response = await Server.client.sendRequest("m/extendSelection", request) + editor.selections = response.selections.map((range: Range) => { + let r = Server.client.protocol2CodeConverter.asRange(range) + return new vscode.Selection(r.start, r.end) + }) +} diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts new file mode 100644 index 000000000..7ae7b9d76 --- /dev/null +++ b/editors/code/src/commands/join_lines.ts @@ -0,0 +1,21 @@ +import * as vscode from 'vscode'; + +import { TextDocumentIdentifier, Range } from "vscode-languageclient"; +import { Server } from '../server'; +import { handle as applySourceChange, SourceChange } from './apply_source_change'; + +interface JoinLinesParams { + textDocument: TextDocumentIdentifier; + range: Range; +} + +export async function handle() { + let editor = vscode.window.activeTextEditor + if (editor == null || editor.document.languageId != "rust") return + let request: JoinLinesParams = { + textDocument: { uri: editor.document.uri.toString() }, + range: Server.client.code2ProtocolConverter.asRange(editor.selection), + } + let change = await Server.client.sendRequest("m/joinLines", request) + await applySourceChange(change) +} diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts new file mode 100644 index 000000000..572c15ce8 --- /dev/null +++ b/editors/code/src/commands/matching_brace.ts @@ -0,0 +1,27 @@ +import * as vscode from 'vscode'; + +import { TextDocumentIdentifier, Position } from "vscode-languageclient"; +import { Server } from '../server'; + +interface FindMatchingBraceParams { + textDocument: TextDocumentIdentifier; + offsets: Position[]; +} + +export async function handle() { + let editor = vscode.window.activeTextEditor + if (editor == null || editor.document.languageId != "rust") return + let request: FindMatchingBraceParams = { + textDocument: { uri: editor.document.uri.toString() }, + offsets: editor.selections.map((s) => { + return Server.client.code2ProtocolConverter.asPosition(s.active) + }) + } + let response = await Server.client.sendRequest("m/findMatchingBrace", request) + editor.selections = editor.selections.map((sel, idx) => { + let active = Server.client.protocol2CodeConverter.asPosition(response[idx]) + let anchor = sel.isEmpty ? active : sel.anchor + return new vscode.Selection(anchor, active) + }) + editor.revealRange(editor.selection) +}; diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts new file mode 100644 index 000000000..dae60bfb4 --- /dev/null +++ b/editors/code/src/commands/parent_module.ts @@ -0,0 +1,22 @@ +import * as vscode from 'vscode'; + +import { TextDocumentIdentifier, Location } from "vscode-languageclient"; +import { Server } from '../server'; + +export async function handle() { + let editor = vscode.window.activeTextEditor + if (editor == null || editor.document.languageId != "rust") return + let request: TextDocumentIdentifier = { + uri: editor.document.uri.toString() + } + let response = await Server.client.sendRequest("m/parentModule", request) + let loc = response[0] + if (loc == null) return + let uri = Server.client.protocol2CodeConverter.asUri(loc.uri) + let range = Server.client.protocol2CodeConverter.asRange(loc.range) + + let doc = await vscode.workspace.openTextDocument(uri) + let 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/runnables.ts b/editors/code/src/commands/runnables.ts new file mode 100644 index 000000000..45c16497d --- /dev/null +++ b/editors/code/src/commands/runnables.ts @@ -0,0 +1,88 @@ +import * as vscode from 'vscode'; +import * as lc from 'vscode-languageclient' +import { Server } from '../server'; + +interface RunnablesParams { + textDocument: lc.TextDocumentIdentifier, + position?: lc.Position, +} + +interface Runnable { + range: lc.Range; + label: string; + bin: string; + args: string[]; + env: { [index: string]: string }, +} + +class RunnableQuickPick implements vscode.QuickPickItem { + label: string; + description?: string | undefined; + detail?: string | undefined; + picked?: boolean | undefined; + + constructor(public runnable: Runnable) { + this.label = runnable.label + } +} + +interface CargoTaskDefinition extends vscode.TaskDefinition { + type: 'cargo'; + label: string; + command: string; + args: Array; + env?: { [key: string]: string }; +} + +function createTask(spec: Runnable): vscode.Task { + const TASK_SOURCE = 'Rust'; + let definition: CargoTaskDefinition = { + type: 'cargo', + label: 'cargo', + command: spec.bin, + args: spec.args, + env: spec.env + } + + let execCmd = `${definition.command} ${definition.args.join(' ')}`; + let execOption: vscode.ShellExecutionOptions = { + cwd: '.', + env: definition.env, + }; + let exec = new vscode.ShellExecution(`clear; ${execCmd}`, execOption); + + let f = vscode.workspace.workspaceFolders![0] + let t = new vscode.Task(definition, f, definition.label, TASK_SOURCE, exec, ['$rustc']); + return t; +} + +let prevRunnable: RunnableQuickPick | undefined = undefined +export async function handle() { + let editor = vscode.window.activeTextEditor + if (editor == null || editor.document.languageId != "rust") return + let textDocument: lc.TextDocumentIdentifier = { + uri: editor.document.uri.toString() + } + let params: RunnablesParams = { + textDocument, + position: Server.client.code2ProtocolConverter.asPosition(editor.selection.active) + } + let runnables = await Server.client.sendRequest('m/runnables', params) + let items: RunnableQuickPick[] = [] + if (prevRunnable) { + items.push(prevRunnable) + } + for (let r of runnables) { + if (prevRunnable && JSON.stringify(prevRunnable.runnable) == JSON.stringify(r)) { + continue + } + items.push(new RunnableQuickPick(r)) + } + let item = await vscode.window.showQuickPick(items) + if (item) { + item.detail = "rerun" + prevRunnable = item + let task = createTask(item.runnable) + return await vscode.tasks.executeTask(task) + } +} diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts new file mode 100644 index 000000000..d5daa9302 --- /dev/null +++ b/editors/code/src/commands/syntaxTree.ts @@ -0,0 +1,38 @@ +import * as vscode from 'vscode'; +import { TextDocumentIdentifier } from 'vscode-languageclient'; + +import { Server } from '../server'; + +export const syntaxTreeUri = vscode.Uri.parse('ra-lsp://syntaxtree'); + +export class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { + public eventEmitter = new vscode.EventEmitter() + public syntaxTree: string = "Not available" + + public provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult { + let editor = vscode.window.activeTextEditor; + if (editor == null) return "" + let request: SyntaxTreeParams = { + textDocument: { uri: editor.document.uri.toString() } + }; + return Server.client.sendRequest("m/syntaxTree", request); + } + + get onDidChange(): vscode.Event { + return this.eventEmitter.event + } +} + +interface SyntaxTreeParams { + textDocument: TextDocumentIdentifier; +} + +type SyntaxTreeResult = string; + +// Opens the virtual file that will show the syntax tree +// +// The contents of the file come from the `TextDocumentContentProvider` +export async function handle() { + let document = await vscode.workspace.openTextDocument(syntaxTreeUri) + return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true) +} -- cgit v1.2.3