Flatten commands.ts

This commit is contained in:
Aleksey Kladov 2020-05-25 12:02:30 +02:00
parent 021b3da672
commit 6058b8b0f6
4 changed files with 103 additions and 109 deletions

View file

@ -1,93 +1,15 @@
import * as vscode from 'vscode'; 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<vscode.Uri>();
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<string> {
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<vscode.Uri> {
return this.eventEmitter.event;
}
}
import { Ctx, Disposable } from './ctx';
import { RustEditor, isRustEditor } from './util';
// FIXME: consider implementing this via the Tree View API? // FIXME: consider implementing this via the Tree View API?
// https://code.visualstudio.com/api/extension-guides/tree-view // 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({ private readonly astDecorationType = vscode.window.createTextEditorDecorationType({
borderColor: new vscode.ThemeColor('rust_analyzer.syntaxTreeBorder'), borderColor: new vscode.ThemeColor('rust_analyzer.syntaxTreeBorder'),
borderStyle: "solid", borderStyle: "solid",
borderWidth: "2px", borderWidth: "2px",
}); });
private rustEditor: undefined | RustEditor; private rustEditor: undefined | RustEditor;
@ -113,7 +35,7 @@ class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, D
}); });
constructor(ctx: Ctx) { 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)); ctx.pushCleanup(vscode.languages.registerDefinitionProvider({ language: "rust" }, this));
vscode.workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, ctx.subscriptions); vscode.workspace.onDidCloseTextDocument(this.onDidCloseTextDocument, this, ctx.subscriptions);
vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, 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 { 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) { private setRustEditor(newRustEditor: undefined | RustEditor) {

View file

@ -1,13 +1,16 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient'; 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 { Ctx, Cmd } from './ctx';
import { applySnippetWorkspaceEdit } from '../snippets'; import { applySnippetWorkspaceEdit } from './snippets';
import { spawnSync } from 'child_process'; 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 './ast_inspector';
export * from './runnables'; export * from './run';
export function analyzerStatus(ctx: Ctx): Cmd { export function analyzerStatus(ctx: Ctx): Cmd {
const tdcp = new class implements vscode.TextDocumentContentProvider { 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<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;
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<vscode.Uri> {
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 // Opens the virtual file that will show the syntax tree
// //
// The contents of the file come from the `TextDocumentContentProvider` // The contents of the file come from the `TextDocumentContentProvider`

View file

@ -92,7 +92,6 @@ export async function activate(context: vscode.ExtensionContext) {
ctx.registerCommand('runSingle', commands.runSingle); ctx.registerCommand('runSingle', commands.runSingle);
ctx.registerCommand('debugSingle', commands.debugSingle); ctx.registerCommand('debugSingle', commands.debugSingle);
ctx.registerCommand('showReferences', commands.showReferences); ctx.registerCommand('showReferences', commands.showReferences);
ctx.registerCommand('applySourceChange', commands.applySourceChange);
ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
ctx.registerCommand('applyActionGroup', commands.applyActionGroup); ctx.registerCommand('applyActionGroup', commands.applyActionGroup);

View file

@ -1,13 +1,13 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient'; 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 { Ctx, Cmd } from './ctx';
import { startDebugSession, getDebugConfiguration } from '../debug'; import { startDebugSession, getDebugConfiguration } from './debug';
const quickPickButtons = [{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configurtation." }]; 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<RunnableQuickPick | undefined> { export async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debuggeeOnly = false, showButtons: boolean = true): Promise<RunnableQuickPick | undefined> {
const editor = ctx.activeRustEditor; const editor = ctx.activeRustEditor;
const client = ctx.client; const client = ctx.client;
if (!editor || !client) return; 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 { export function runSingle(ctx: Ctx): Cmd {
return async (runnable: ra.Runnable) => { return async (runnable: ra.Runnable) => {
const editor = ctx.activeRustEditor; 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 label: string;
public description?: string | undefined; public description?: string | undefined;
public detail?: string | undefined; public detail?: string | undefined;
@ -184,7 +170,7 @@ interface CargoTaskDefinition extends vscode.TaskDefinition {
env?: { [key: string]: string }; env?: { [key: string]: string };
} }
function createTask(spec: ra.Runnable): vscode.Task { export function createTask(spec: ra.Runnable): vscode.Task {
const TASK_SOURCE = 'Rust'; const TASK_SOURCE = 'Rust';
const definition: CargoTaskDefinition = { const definition: CargoTaskDefinition = {
type: 'cargo', type: 'cargo',