diff options
Diffstat (limited to 'editors/code/src/commands')
-rw-r--r-- | editors/code/src/commands/apply_source_change.ts | 58 | ||||
-rw-r--r-- | editors/code/src/commands/extend_selection.ts | 29 | ||||
-rw-r--r-- | editors/code/src/commands/index.ts | 17 | ||||
-rw-r--r-- | editors/code/src/commands/join_lines.ts | 21 | ||||
-rw-r--r-- | editors/code/src/commands/matching_brace.ts | 27 | ||||
-rw-r--r-- | editors/code/src/commands/parent_module.ts | 22 | ||||
-rw-r--r-- | editors/code/src/commands/runnables.ts | 88 | ||||
-rw-r--r-- | editors/code/src/commands/syntaxTree.ts | 38 |
8 files changed, 300 insertions, 0 deletions
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..67765e5a3 --- /dev/null +++ b/editors/code/src/commands/apply_source_change.ts | |||
@@ -0,0 +1,58 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import * as lc from 'vscode-languageclient'; | ||
3 | |||
4 | import { Server } from '../server'; | ||
5 | |||
6 | interface FileSystemEdit { | ||
7 | type: string; | ||
8 | uri?: string; | ||
9 | src?: string; | ||
10 | dst?: string; | ||
11 | } | ||
12 | |||
13 | export interface SourceChange { | ||
14 | label: string; | ||
15 | sourceFileEdits: lc.TextDocumentEdit[]; | ||
16 | fileSystemEdits: FileSystemEdit[]; | ||
17 | cursorPosition?: lc.TextDocumentPositionParams; | ||
18 | } | ||
19 | |||
20 | export async function handle(change: SourceChange) { | ||
21 | const wsEdit = new vscode.WorkspaceEdit(); | ||
22 | for (const sourceEdit of change.sourceFileEdits) { | ||
23 | const uri = Server.client.protocol2CodeConverter.asUri(sourceEdit.textDocument.uri); | ||
24 | const edits = Server.client.protocol2CodeConverter.asTextEdits(sourceEdit.edits); | ||
25 | wsEdit.set(uri, edits); | ||
26 | } | ||
27 | let created; | ||
28 | let moved; | ||
29 | for (const fsEdit of change.fileSystemEdits) { | ||
30 | switch (fsEdit.type) { | ||
31 | case 'createFile': | ||
32 | const uri = vscode.Uri.parse(fsEdit.uri!); | ||
33 | wsEdit.createFile(uri); | ||
34 | created = uri; | ||
35 | break; | ||
36 | case 'moveFile': | ||
37 | const src = vscode.Uri.parse(fsEdit.src!); | ||
38 | const dst = vscode.Uri.parse(fsEdit.dst!); | ||
39 | wsEdit.renameFile(src, dst); | ||
40 | moved = dst; | ||
41 | break; | ||
42 | } | ||
43 | } | ||
44 | const toOpen = created || moved; | ||
45 | const toReveal = change.cursorPosition; | ||
46 | await vscode.workspace.applyEdit(wsEdit); | ||
47 | if (toOpen) { | ||
48 | const doc = await vscode.workspace.openTextDocument(toOpen); | ||
49 | await vscode.window.showTextDocument(doc); | ||
50 | } else if (toReveal) { | ||
51 | const uri = Server.client.protocol2CodeConverter.asUri(toReveal.textDocument.uri); | ||
52 | const position = Server.client.protocol2CodeConverter.asPosition(toReveal.position); | ||
53 | const editor = vscode.window.activeTextEditor; | ||
54 | if (!editor || editor.document.uri.toString() !== uri.toString()) { return; } | ||
55 | if (!editor.selection.isEmpty) { return; } | ||
56 | editor!.selection = new vscode.Selection(position, position); | ||
57 | } | ||
58 | } | ||
diff --git a/editors/code/src/commands/extend_selection.ts b/editors/code/src/commands/extend_selection.ts new file mode 100644 index 000000000..cdc3d10fb --- /dev/null +++ b/editors/code/src/commands/extend_selection.ts | |||
@@ -0,0 +1,29 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; | ||
4 | import { Server } from '../server'; | ||
5 | |||
6 | interface ExtendSelectionParams { | ||
7 | textDocument: TextDocumentIdentifier; | ||
8 | selections: Range[]; | ||
9 | } | ||
10 | |||
11 | interface ExtendSelectionResult { | ||
12 | selections: Range[]; | ||
13 | } | ||
14 | |||
15 | export async function handle() { | ||
16 | const editor = vscode.window.activeTextEditor; | ||
17 | if (editor == null || editor.document.languageId !== 'rust') { return; } | ||
18 | const request: ExtendSelectionParams = { | ||
19 | selections: editor.selections.map((s) => { | ||
20 | return Server.client.code2ProtocolConverter.asRange(s); | ||
21 | }), | ||
22 | textDocument: { uri: editor.document.uri.toString() }, | ||
23 | }; | ||
24 | const response = await Server.client.sendRequest<ExtendSelectionResult>('m/extendSelection', request); | ||
25 | editor.selections = response.selections.map((range: Range) => { | ||
26 | const r = Server.client.protocol2CodeConverter.asRange(range); | ||
27 | return new vscode.Selection(r.start, r.end); | ||
28 | }); | ||
29 | } | ||
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts new file mode 100644 index 000000000..dfdcd6454 --- /dev/null +++ b/editors/code/src/commands/index.ts | |||
@@ -0,0 +1,17 @@ | |||
1 | import * as applySourceChange from './apply_source_change'; | ||
2 | import * as extendSelection from './extend_selection'; | ||
3 | import * as joinLines from './join_lines'; | ||
4 | import * as matchingBrace from './matching_brace'; | ||
5 | import * as parentModule from './parent_module'; | ||
6 | import * as runnables from './runnables'; | ||
7 | import * as syntaxTree from './syntaxTree'; | ||
8 | |||
9 | export { | ||
10 | applySourceChange, | ||
11 | extendSelection, | ||
12 | joinLines, | ||
13 | matchingBrace, | ||
14 | parentModule, | ||
15 | runnables, | ||
16 | syntaxTree, | ||
17 | }; | ||
diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts new file mode 100644 index 000000000..526b698cc --- /dev/null +++ b/editors/code/src/commands/join_lines.ts | |||
@@ -0,0 +1,21 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; | ||
4 | import { Server } from '../server'; | ||
5 | import { handle as applySourceChange, SourceChange } from './apply_source_change'; | ||
6 | |||
7 | interface JoinLinesParams { | ||
8 | textDocument: TextDocumentIdentifier; | ||
9 | range: Range; | ||
10 | } | ||
11 | |||
12 | export async function handle() { | ||
13 | const editor = vscode.window.activeTextEditor; | ||
14 | if (editor == null || editor.document.languageId !== 'rust') { return; } | ||
15 | const request: JoinLinesParams = { | ||
16 | range: Server.client.code2ProtocolConverter.asRange(editor.selection), | ||
17 | textDocument: { uri: editor.document.uri.toString() }, | ||
18 | }; | ||
19 | const change = await Server.client.sendRequest<SourceChange>('m/joinLines', request); | ||
20 | await applySourceChange(change); | ||
21 | } | ||
diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts new file mode 100644 index 000000000..a80446a8f --- /dev/null +++ b/editors/code/src/commands/matching_brace.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { Position, TextDocumentIdentifier } from 'vscode-languageclient'; | ||
4 | import { Server } from '../server'; | ||
5 | |||
6 | interface FindMatchingBraceParams { | ||
7 | textDocument: TextDocumentIdentifier; | ||
8 | offsets: Position[]; | ||
9 | } | ||
10 | |||
11 | export async function handle() { | ||
12 | const editor = vscode.window.activeTextEditor; | ||
13 | if (editor == null || editor.document.languageId !== 'rust') { return; } | ||
14 | const request: FindMatchingBraceParams = { | ||
15 | textDocument: { uri: editor.document.uri.toString() }, | ||
16 | offsets: editor.selections.map((s) => { | ||
17 | return Server.client.code2ProtocolConverter.asPosition(s.active); | ||
18 | }), | ||
19 | }; | ||
20 | const response = await Server.client.sendRequest<Position[]>('m/findMatchingBrace', request); | ||
21 | editor.selections = editor.selections.map((sel, idx) => { | ||
22 | const active = Server.client.protocol2CodeConverter.asPosition(response[idx]); | ||
23 | const anchor = sel.isEmpty ? active : sel.anchor; | ||
24 | return new vscode.Selection(anchor, active); | ||
25 | }); | ||
26 | editor.revealRange(editor.selection); | ||
27 | } | ||
diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts new file mode 100644 index 000000000..d66fb3026 --- /dev/null +++ b/editors/code/src/commands/parent_module.ts | |||
@@ -0,0 +1,22 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { Location, TextDocumentIdentifier } from 'vscode-languageclient'; | ||
4 | import { Server } from '../server'; | ||
5 | |||
6 | export async function handle() { | ||
7 | const editor = vscode.window.activeTextEditor; | ||
8 | if (editor == null || editor.document.languageId !== 'rust') { return; } | ||
9 | const request: TextDocumentIdentifier = { | ||
10 | uri: editor.document.uri.toString(), | ||
11 | }; | ||
12 | const response = await Server.client.sendRequest<Location[]>('m/parentModule', request); | ||
13 | const loc = response[0]; | ||
14 | if (loc == null) { return; } | ||
15 | const uri = Server.client.protocol2CodeConverter.asUri(loc.uri); | ||
16 | const range = Server.client.protocol2CodeConverter.asRange(loc.range); | ||
17 | |||
18 | const doc = await vscode.workspace.openTextDocument(uri); | ||
19 | const e = await vscode.window.showTextDocument(doc); | ||
20 | e.selection = new vscode.Selection(range.start, range.start); | ||
21 | e.revealRange(range, vscode.TextEditorRevealType.InCenter); | ||
22 | } | ||
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts new file mode 100644 index 000000000..40f590dce --- /dev/null +++ b/editors/code/src/commands/runnables.ts | |||
@@ -0,0 +1,88 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import * as lc from 'vscode-languageclient'; | ||
3 | import { Server } from '../server'; | ||
4 | |||
5 | interface RunnablesParams { | ||
6 | textDocument: lc.TextDocumentIdentifier; | ||
7 | position?: lc.Position; | ||
8 | } | ||
9 | |||
10 | interface Runnable { | ||
11 | range: lc.Range; | ||
12 | label: string; | ||
13 | bin: string; | ||
14 | args: string[]; | ||
15 | env: { [index: string]: string }; | ||
16 | } | ||
17 | |||
18 | class RunnableQuickPick implements vscode.QuickPickItem { | ||
19 | public label: string; | ||
20 | public description?: string | undefined; | ||
21 | public detail?: string | undefined; | ||
22 | public picked?: boolean | undefined; | ||
23 | |||
24 | constructor(public runnable: Runnable) { | ||
25 | this.label = runnable.label; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | interface CargoTaskDefinition extends vscode.TaskDefinition { | ||
30 | type: 'cargo'; | ||
31 | label: string; | ||
32 | command: string; | ||
33 | args: string[]; | ||
34 | env?: { [key: string]: string }; | ||
35 | } | ||
36 | |||
37 | function createTask(spec: Runnable): vscode.Task { | ||
38 | const TASK_SOURCE = 'Rust'; | ||
39 | const definition: CargoTaskDefinition = { | ||
40 | type: 'cargo', | ||
41 | label: 'cargo', | ||
42 | command: spec.bin, | ||
43 | args: spec.args, | ||
44 | env: spec.env, | ||
45 | }; | ||
46 | |||
47 | const execCmd = `${definition.command} ${definition.args.join(' ')}`; | ||
48 | const execOption: vscode.ShellExecutionOptions = { | ||
49 | cwd: '.', | ||
50 | env: definition.env, | ||
51 | }; | ||
52 | const exec = new vscode.ShellExecution(`clear; ${execCmd}`, execOption); | ||
53 | |||
54 | const f = vscode.workspace.workspaceFolders![0]; | ||
55 | const t = new vscode.Task(definition, f, definition.label, TASK_SOURCE, exec, ['$rustc']); | ||
56 | return t; | ||
57 | } | ||
58 | |||
59 | let prevRunnable: RunnableQuickPick | undefined; | ||
60 | export async function handle() { | ||
61 | const editor = vscode.window.activeTextEditor; | ||
62 | if (editor == null || editor.document.languageId !== 'rust') { return; } | ||
63 | const textDocument: lc.TextDocumentIdentifier = { | ||
64 | uri: editor.document.uri.toString(), | ||
65 | }; | ||
66 | const params: RunnablesParams = { | ||
67 | textDocument, | ||
68 | position: Server.client.code2ProtocolConverter.asPosition(editor.selection.active), | ||
69 | }; | ||
70 | const runnables = await Server.client.sendRequest<Runnable[]>('m/runnables', params); | ||
71 | const items: RunnableQuickPick[] = []; | ||
72 | if (prevRunnable) { | ||
73 | items.push(prevRunnable); | ||
74 | } | ||
75 | for (const r of runnables) { | ||
76 | if (prevRunnable && JSON.stringify(prevRunnable.runnable) === JSON.stringify(r)) { | ||
77 | continue; | ||
78 | } | ||
79 | items.push(new RunnableQuickPick(r)); | ||
80 | } | ||
81 | const item = await vscode.window.showQuickPick(items); | ||
82 | if (item) { | ||
83 | item.detail = 'rerun'; | ||
84 | prevRunnable = item; | ||
85 | const task = createTask(item.runnable); | ||
86 | return await vscode.tasks.executeTask(task); | ||
87 | } | ||
88 | } | ||
diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts new file mode 100644 index 000000000..dcb721eee --- /dev/null +++ b/editors/code/src/commands/syntaxTree.ts | |||
@@ -0,0 +1,38 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import { TextDocumentIdentifier } from 'vscode-languageclient'; | ||
3 | |||
4 | import { Server } from '../server'; | ||
5 | |||
6 | export const syntaxTreeUri = vscode.Uri.parse('ra-lsp://syntaxtree'); | ||
7 | |||
8 | export class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { | ||
9 | public eventEmitter = new vscode.EventEmitter<vscode.Uri>(); | ||
10 | public syntaxTree: string = 'Not available'; | ||
11 | |||
12 | public provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult<string> { | ||
13 | const editor = vscode.window.activeTextEditor; | ||
14 | if (editor == null) { return ''; } | ||
15 | const request: SyntaxTreeParams = { | ||
16 | textDocument: { uri: editor.document.uri.toString() }, | ||
17 | }; | ||
18 | return Server.client.sendRequest<SyntaxTreeResult>('m/syntaxTree', request); | ||
19 | } | ||
20 | |||
21 | get onDidChange(): vscode.Event<vscode.Uri> { | ||
22 | return this.eventEmitter.event; | ||
23 | } | ||
24 | } | ||
25 | |||
26 | interface SyntaxTreeParams { | ||
27 | textDocument: TextDocumentIdentifier; | ||
28 | } | ||
29 | |||
30 | type SyntaxTreeResult = string; | ||
31 | |||
32 | // Opens the virtual file that will show the syntax tree | ||
33 | // | ||
34 | // The contents of the file come from the `TextDocumentContentProvider` | ||
35 | export async function handle() { | ||
36 | const document = await vscode.workspace.openTextDocument(syntaxTreeUri); | ||
37 | return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true); | ||
38 | } | ||