4605: Reorganize TypeScript r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-05-25 10:17:40 +00:00 committed by GitHub
commit e4f91bfa57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 382 additions and 499 deletions

View File

@ -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<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?
// 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) {

View File

@ -0,0 +1,370 @@
import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient';
import * as ra from './rust-analyzer-api';
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 './ast_inspector';
export * from './run';
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<vscode.Uri>();
provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> {
if (!vscode.window.activeTextEditor) return '';
return ctx.client.sendRequest(ra.analyzerStatus, null);
}
get onDidChange(): vscode.Event<vscode.Uri> {
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);
};
}
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
//
// 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<vscode.Uri>();
async provideTextDocumentContent(_uri: vscode.Uri): Promise<string> {
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<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);
return vscode.window.showTextDocument(
document,
vscode.ViewColumn.Two,
true,
);
};
}
export function collectGarbage(ctx: Ctx): Cmd {
return async () => ctx.client.sendRequest(ra.collectGarbage, null);
}
export function showReferences(ctx: Ctx): Cmd {
return (uri: string, position: lc.Position, locations: lc.Location[]) => {
const client = ctx.client;
if (client) {
vscode.commands.executeCommand(
'editor.action.showReferences',
vscode.Uri.parse(uri),
client.protocol2CodeConverter.asPosition(position),
locations.map(client.protocol2CodeConverter.asLocation),
);
}
};
}
export function applyActionGroup(_ctx: Ctx): Cmd {
return async (actions: { label: string; edit: vscode.WorkspaceEdit }[]) => {
const selectedAction = await vscode.window.showQuickPick(actions);
if (!selectedAction) return;
await applySnippetWorkspaceEdit(selectedAction.edit);
};
}
export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd {
return async (edit: vscode.WorkspaceEdit) => {
await applySnippetWorkspaceEdit(edit);
};
}

View File

@ -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<vscode.Uri>();
constructor(private readonly ctx: Ctx) {
}
provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> {
if (!vscode.window.activeTextEditor) return '';
return this.ctx.client.sendRequest(ra.analyzerStatus, null);
}
get onDidChange(): vscode.Event<vscode.Uri> {
return this.eventEmitter.event;
}
}

View File

@ -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<vscode.Uri>();
constructor(private readonly ctx: Ctx) {
}
async provideTextDocumentContent(_uri: vscode.Uri): Promise<string> {
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<vscode.Uri> {
return this.eventEmitter.event;
}
}

View File

@ -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);
});
});
};
}

View File

@ -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);
};
}

View File

@ -1,35 +0,0 @@
import * as vscode from 'vscode';
import * as ra from '../rust-analyzer-api';
import { Cmd, Ctx } from '../ctx';
import { applySnippetWorkspaceEdit } from '.';
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' });
};
}

View File

@ -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);
};
}

View File

@ -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})`
);
};
}

View File

@ -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));
};
}

View File

@ -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);
};
}

View File

@ -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);

View File

@ -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<RunnableQuickPick | undefined> {
export async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debuggeeOnly = false, showButtons: boolean = true): Promise<RunnableQuickPick | undefined> {
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',

View File

@ -1,60 +1,6 @@
import * as vscode from 'vscode';
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';
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 collectGarbage(ctx: Ctx): Cmd {
return async () => ctx.client.sendRequest(ra.collectGarbage, null);
}
export function showReferences(ctx: Ctx): Cmd {
return (uri: string, position: lc.Position, locations: lc.Location[]) => {
const client = ctx.client;
if (client) {
vscode.commands.executeCommand(
'editor.action.showReferences',
vscode.Uri.parse(uri),
client.protocol2CodeConverter.asPosition(position),
locations.map(client.protocol2CodeConverter.asLocation),
);
}
};
}
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);
if (!selectedAction) return;
await applySnippetWorkspaceEdit(selectedAction.edit);
};
}
export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd {
return async (edit: vscode.WorkspaceEdit) => {
await applySnippetWorkspaceEdit(edit);
};
}
import { assert } from './util';
export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`);

View File

@ -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,
);
}
}