aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/commands')
-rw-r--r--editors/code/src/commands/analyzer_status.ts17
-rw-r--r--editors/code/src/commands/apply_source_change.ts54
-rw-r--r--editors/code/src/commands/index.ts18
-rw-r--r--editors/code/src/commands/join_lines.ts45
-rw-r--r--editors/code/src/commands/matching_brace.ts15
-rw-r--r--editors/code/src/commands/on_enter.ts51
-rw-r--r--editors/code/src/commands/parent_module.ts54
-rw-r--r--editors/code/src/commands/syntaxTree.ts76
-rw-r--r--editors/code/src/commands/syntax_tree.ts106
9 files changed, 200 insertions, 236 deletions
diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts
index c9d32fe07..b2b624b75 100644
--- a/editors/code/src/commands/analyzer_status.ts
+++ b/editors/code/src/commands/analyzer_status.ts
@@ -1,4 +1,5 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2
2import { Ctx, Cmd } from '../ctx'; 3import { Ctx, Cmd } from '../ctx';
3// Shows status of rust-analyzer (for debugging) 4// Shows status of rust-analyzer (for debugging)
4 5
@@ -23,10 +24,7 @@ export function analyzerStatus(ctx: Ctx): Cmd {
23 24
24 return async function handle() { 25 return async function handle() {
25 if (poller == null) { 26 if (poller == null) {
26 poller = setInterval( 27 poller = setInterval(() => tdcp.eventEmitter.fire(tdcp.uri), 1000);
27 () => tdcp.eventEmitter.fire(tdcp.uri),
28 1000,
29 );
30 } 28 }
31 const document = await vscode.workspace.openTextDocument(tdcp.uri); 29 const document = await vscode.workspace.openTextDocument(tdcp.uri);
32 return vscode.window.showTextDocument( 30 return vscode.window.showTextDocument(
@@ -39,23 +37,20 @@ export function analyzerStatus(ctx: Ctx): Cmd {
39 37
40class TextDocumentContentProvider 38class TextDocumentContentProvider
41 implements vscode.TextDocumentContentProvider { 39 implements vscode.TextDocumentContentProvider {
42 40 ctx: Ctx;
43 uri = vscode.Uri.parse('rust-analyzer-status://status'); 41 uri = vscode.Uri.parse('rust-analyzer-status://status');
44 eventEmitter = new vscode.EventEmitter<vscode.Uri>(); 42 eventEmitter = new vscode.EventEmitter<vscode.Uri>();
45 43
46 ctx: Ctx
47
48 constructor(ctx: Ctx) { 44 constructor(ctx: Ctx) {
49 this.ctx = ctx 45 this.ctx = ctx;
50 } 46 }
51 47
52 provideTextDocumentContent( 48 provideTextDocumentContent(
53 _uri: vscode.Uri, 49 _uri: vscode.Uri,
54 ): vscode.ProviderResult<string> { 50 ): vscode.ProviderResult<string> {
55 const editor = vscode.window.activeTextEditor; 51 const editor = vscode.window.activeTextEditor;
56 if (editor == null) { 52 if (editor == null) return '';
57 return ''; 53
58 }
59 return this.ctx.client.sendRequest<string>( 54 return this.ctx.client.sendRequest<string>(
60 'rust-analyzer/analyzerStatus', 55 'rust-analyzer/analyzerStatus',
61 null, 56 null,
diff --git a/editors/code/src/commands/apply_source_change.ts b/editors/code/src/commands/apply_source_change.ts
deleted file mode 100644
index 8167398b1..000000000
--- a/editors/code/src/commands/apply_source_change.ts
+++ /dev/null
@@ -1,54 +0,0 @@
1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient';
3
4import { Server } from '../server';
5
6export interface SourceChange {
7 label: string;
8 workspaceEdit: lc.WorkspaceEdit;
9 cursorPosition?: lc.TextDocumentPositionParams;
10}
11
12export async function handle(change: SourceChange) {
13 const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit(
14 change.workspaceEdit,
15 );
16 let created;
17 let moved;
18 if (change.workspaceEdit.documentChanges) {
19 for (const docChange of change.workspaceEdit.documentChanges) {
20 if (lc.CreateFile.is(docChange)) {
21 created = docChange.uri;
22 } else if (lc.RenameFile.is(docChange)) {
23 moved = docChange.newUri;
24 }
25 }
26 }
27 const toOpen = created || moved;
28 const toReveal = change.cursorPosition;
29 await vscode.workspace.applyEdit(wsEdit);
30 if (toOpen) {
31 const toOpenUri = vscode.Uri.parse(toOpen);
32 const doc = await vscode.workspace.openTextDocument(toOpenUri);
33 await vscode.window.showTextDocument(doc);
34 } else if (toReveal) {
35 const uri = Server.client.protocol2CodeConverter.asUri(
36 toReveal.textDocument.uri,
37 );
38 const position = Server.client.protocol2CodeConverter.asPosition(
39 toReveal.position,
40 );
41 const editor = vscode.window.activeTextEditor;
42 if (!editor || editor.document.uri.toString() !== uri.toString()) {
43 return;
44 }
45 if (!editor.selection.isEmpty) {
46 return;
47 }
48 editor.selection = new vscode.Selection(position, position);
49 editor.revealRange(
50 new vscode.Range(position, position),
51 vscode.TextEditorRevealType.Default,
52 );
53 }
54}
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts
index 9d9b9c575..8f91b3b7d 100644
--- a/editors/code/src/commands/index.ts
+++ b/editors/code/src/commands/index.ts
@@ -1,23 +1,23 @@
1import { Ctx, Cmd } from '../ctx' 1import { Ctx, Cmd } from '../ctx';
2 2
3import { analyzerStatus } from './analyzer_status'; 3import { analyzerStatus } from './analyzer_status';
4import { matchingBrace } from './matching_brace'; 4import { matchingBrace } from './matching_brace';
5import * as applySourceChange from './apply_source_change'; 5import { joinLines } from './join_lines';
6import { onEnter } from './on_enter';
7import { parentModule } from './parent_module';
8import { syntaxTree } from './syntax_tree';
6import * as expandMacro from './expand_macro'; 9import * as expandMacro from './expand_macro';
7import * as inlayHints from './inlay_hints'; 10import * as inlayHints from './inlay_hints';
8import * as joinLines from './join_lines';
9import * as onEnter from './on_enter';
10import * as parentModule from './parent_module';
11import * as runnables from './runnables'; 11import * as runnables from './runnables';
12import * as syntaxTree from './syntaxTree';
13 12
14function collectGarbage(ctx: Ctx): Cmd { 13function collectGarbage(ctx: Ctx): Cmd {
15 return async () => { ctx.client.sendRequest<null>('rust-analyzer/collectGarbage', null) } 14 return async () => {
15 ctx.client.sendRequest<null>('rust-analyzer/collectGarbage', null);
16 };
16} 17}
17 18
18export { 19export {
19 analyzerStatus, 20 analyzerStatus,
20 applySourceChange,
21 expandMacro, 21 expandMacro,
22 joinLines, 22 joinLines,
23 matchingBrace, 23 matchingBrace,
@@ -26,5 +26,5 @@ export {
26 syntaxTree, 26 syntaxTree,
27 onEnter, 27 onEnter,
28 inlayHints, 28 inlayHints,
29 collectGarbage 29 collectGarbage,
30}; 30};
diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts
index 134ddc801..f4f902cf9 100644
--- a/editors/code/src/commands/join_lines.ts
+++ b/editors/code/src/commands/join_lines.ts
@@ -1,29 +1,26 @@
1import * as vscode from 'vscode'; 1import * as lc from 'vscode-languageclient';
2 2
3import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; 3import { Ctx, Cmd } from '../ctx';
4import { Server } from '../server'; 4import { applySourceChange, SourceChange } from '../source_change';
5import {
6 handle as applySourceChange,
7 SourceChange,
8} from './apply_source_change';
9 5
10interface JoinLinesParams { 6export function joinLines(ctx: Ctx): Cmd {
11 textDocument: TextDocumentIdentifier; 7 return async () => {
12 range: Range; 8 const editor = ctx.activeRustEditor;
13} 9 if (!editor) return;
14 10
15export async function handle() { 11 const request: JoinLinesParams = {
16 const editor = vscode.window.activeTextEditor; 12 range: ctx.client.code2ProtocolConverter.asRange(editor.selection),
17 if (editor == null || editor.document.languageId !== 'rust') { 13 textDocument: { uri: editor.document.uri.toString() },
18 return; 14 };
19 } 15 const change = await ctx.client.sendRequest<SourceChange>(
20 const request: JoinLinesParams = { 16 'rust-analyzer/joinLines',
21 range: Server.client.code2ProtocolConverter.asRange(editor.selection), 17 request,
22 textDocument: { uri: editor.document.uri.toString() }, 18 );
19 await applySourceChange(ctx, change);
23 }; 20 };
24 const change = await Server.client.sendRequest<SourceChange>( 21}
25 'rust-analyzer/joinLines', 22
26 request, 23interface JoinLinesParams {
27 ); 24 textDocument: lc.TextDocumentIdentifier;
28 await applySourceChange(change); 25 range: lc.Range;
29} 26}
diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts
index 665b0c33c..59c253f88 100644
--- a/editors/code/src/commands/matching_brace.ts
+++ b/editors/code/src/commands/matching_brace.ts
@@ -1,5 +1,6 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import { Position, TextDocumentIdentifier } from 'vscode-languageclient'; 2import * as lc from 'vscode-languageclient';
3
3import { Ctx, Cmd } from '../ctx'; 4import { Ctx, Cmd } from '../ctx';
4 5
5export function matchingBrace(ctx: Ctx): Cmd { 6export function matchingBrace(ctx: Ctx): Cmd {
@@ -10,9 +11,11 @@ export function matchingBrace(ctx: Ctx): Cmd {
10 } 11 }
11 const request: FindMatchingBraceParams = { 12 const request: FindMatchingBraceParams = {
12 textDocument: { uri: editor.document.uri.toString() }, 13 textDocument: { uri: editor.document.uri.toString() },
13 offsets: editor.selections.map(s => ctx.client.code2ProtocolConverter.asPosition(s.active)), 14 offsets: editor.selections.map(s =>
15 ctx.client.code2ProtocolConverter.asPosition(s.active),
16 ),
14 }; 17 };
15 const response = await ctx.client.sendRequest<Position[]>( 18 const response = await ctx.client.sendRequest<lc.Position[]>(
16 'rust-analyzer/findMatchingBrace', 19 'rust-analyzer/findMatchingBrace',
17 request, 20 request,
18 ); 21 );
@@ -24,10 +27,10 @@ export function matchingBrace(ctx: Ctx): Cmd {
24 return new vscode.Selection(anchor, active); 27 return new vscode.Selection(anchor, active);
25 }); 28 });
26 editor.revealRange(editor.selection); 29 editor.revealRange(editor.selection);
27 } 30 };
28} 31}
29 32
30interface FindMatchingBraceParams { 33interface FindMatchingBraceParams {
31 textDocument: TextDocumentIdentifier; 34 textDocument: lc.TextDocumentIdentifier;
32 offsets: Position[]; 35 offsets: lc.Position[];
33} 36}
diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts
index 772c64b3c..8324060e8 100644
--- a/editors/code/src/commands/on_enter.ts
+++ b/editors/code/src/commands/on_enter.ts
@@ -1,33 +1,26 @@
1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient'; 1import * as lc from 'vscode-languageclient';
3import { Server } from '../server';
4import {
5 handle as applySourceChange,
6 SourceChange,
7} from './apply_source_change';
8 2
9export async function handle(event: { text: string }): Promise<boolean> { 3import { applySourceChange, SourceChange } from '../source_change';
10 const editor = vscode.window.activeTextEditor; 4import { Cmd, Ctx } from '../ctx';
11 if ( 5
12 editor == null || 6export function onEnter(ctx: Ctx): Cmd {
13 editor.document.languageId !== 'rust' || 7 return async (event: { text: string }) => {
14 event.text !== '\n' 8 const editor = ctx.activeRustEditor;
15 ) { 9 if (!editor || event.text !== '\n') return false;
16 return false; 10
17 } 11 const request: lc.TextDocumentPositionParams = {
18 const request: lc.TextDocumentPositionParams = { 12 textDocument: { uri: editor.document.uri.toString() },
19 textDocument: { uri: editor.document.uri.toString() }, 13 position: ctx.client.code2ProtocolConverter.asPosition(
20 position: Server.client.code2ProtocolConverter.asPosition( 14 editor.selection.active,
21 editor.selection.active, 15 ),
22 ), 16 };
17 const change = await ctx.client.sendRequest<undefined | SourceChange>(
18 'rust-analyzer/onEnter',
19 request,
20 );
21 if (!change) return false;
22
23 await applySourceChange(ctx, change);
24 return true;
23 }; 25 };
24 const change = await Server.client.sendRequest<undefined | SourceChange>(
25 'rust-analyzer/onEnter',
26 request,
27 );
28 if (!change) {
29 return false;
30 }
31 await applySourceChange(change);
32 return true;
33} 26}
diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts
index ad49e1bdb..258b61b21 100644
--- a/editors/code/src/commands/parent_module.ts
+++ b/editors/code/src/commands/parent_module.ts
@@ -1,32 +1,32 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2
3import * as lc from 'vscode-languageclient'; 2import * as lc from 'vscode-languageclient';
4import { Server } from '../server';
5 3
6export async function handle() { 4import { Ctx, Cmd } from '../ctx';
7 const editor = vscode.window.activeTextEditor; 5
8 if (editor == null || editor.document.languageId !== 'rust') { 6export function parentModule(ctx: Ctx): Cmd {
9 return; 7 return async () => {
10 } 8 const editor = ctx.activeRustEditor;
11 const request: lc.TextDocumentPositionParams = { 9 if (!editor) return;
12 textDocument: { uri: editor.document.uri.toString() },
13 position: Server.client.code2ProtocolConverter.asPosition(
14 editor.selection.active,
15 ),
16 };
17 const response = await Server.client.sendRequest<lc.Location[]>(
18 'rust-analyzer/parentModule',
19 request,
20 );
21 const loc = response[0];
22 if (loc == null) {
23 return;
24 }
25 const uri = Server.client.protocol2CodeConverter.asUri(loc.uri);
26 const range = Server.client.protocol2CodeConverter.asRange(loc.range);
27 10
28 const doc = await vscode.workspace.openTextDocument(uri); 11 const request: lc.TextDocumentPositionParams = {
29 const e = await vscode.window.showTextDocument(doc); 12 textDocument: { uri: editor.document.uri.toString() },
30 e.selection = new vscode.Selection(range.start, range.start); 13 position: ctx.client.code2ProtocolConverter.asPosition(
31 e.revealRange(range, vscode.TextEditorRevealType.InCenter); 14 editor.selection.active,
15 ),
16 };
17 const response = await ctx.client.sendRequest<lc.Location[]>(
18 'rust-analyzer/parentModule',
19 request,
20 );
21 const loc = response[0];
22 if (loc == null) return;
23
24 const uri = ctx.client.protocol2CodeConverter.asUri(loc.uri);
25 const range = ctx.client.protocol2CodeConverter.asRange(loc.range);
26
27 const doc = await vscode.workspace.openTextDocument(uri);
28 const e = await vscode.window.showTextDocument(doc);
29 e.selection = new vscode.Selection(range.start, range.start);
30 e.revealRange(range, vscode.TextEditorRevealType.InCenter);
31 };
32} 32}
diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts
deleted file mode 100644
index 89a80550c..000000000
--- a/editors/code/src/commands/syntaxTree.ts
+++ /dev/null
@@ -1,76 +0,0 @@
1import * as vscode from 'vscode';
2import { Range, TextDocumentIdentifier } from 'vscode-languageclient';
3
4import { Server } from '../server';
5
6export const syntaxTreeUri = vscode.Uri.parse('rust-analyzer://syntaxtree');
7
8export class SyntaxTreeContentProvider
9 implements vscode.TextDocumentContentProvider {
10 public eventEmitter = new vscode.EventEmitter<vscode.Uri>();
11 public syntaxTree: string = 'Not available';
12
13 public provideTextDocumentContent(
14 uri: vscode.Uri,
15 ): vscode.ProviderResult<string> {
16 const editor = vscode.window.activeTextEditor;
17 if (editor == null) {
18 return '';
19 }
20
21 let range: Range | undefined;
22
23 // When the range based query is enabled we take the range of the selection
24 if (uri.query === 'range=true') {
25 range = editor.selection.isEmpty
26 ? undefined
27 : Server.client.code2ProtocolConverter.asRange(
28 editor.selection,
29 );
30 }
31
32 const request: SyntaxTreeParams = {
33 textDocument: { uri: editor.document.uri.toString() },
34 range,
35 };
36 return Server.client.sendRequest<SyntaxTreeResult>(
37 'rust-analyzer/syntaxTree',
38 request,
39 );
40 }
41
42 get onDidChange(): vscode.Event<vscode.Uri> {
43 return this.eventEmitter.event;
44 }
45}
46
47interface SyntaxTreeParams {
48 textDocument: TextDocumentIdentifier;
49 range?: Range;
50}
51
52type SyntaxTreeResult = string;
53
54// Opens the virtual file that will show the syntax tree
55//
56// The contents of the file come from the `TextDocumentContentProvider`
57export function createHandle(provider: SyntaxTreeContentProvider) {
58 return async () => {
59 const editor = vscode.window.activeTextEditor;
60 const rangeEnabled = !!(editor && !editor.selection.isEmpty);
61
62 const uri = rangeEnabled
63 ? vscode.Uri.parse(`${syntaxTreeUri.toString()}?range=true`)
64 : syntaxTreeUri;
65
66 const document = await vscode.workspace.openTextDocument(uri);
67
68 provider.eventEmitter.fire(uri);
69
70 return vscode.window.showTextDocument(
71 document,
72 vscode.ViewColumn.Two,
73 true,
74 );
75 };
76}
diff --git a/editors/code/src/commands/syntax_tree.ts b/editors/code/src/commands/syntax_tree.ts
new file mode 100644
index 000000000..e61fb36df
--- /dev/null
+++ b/editors/code/src/commands/syntax_tree.ts
@@ -0,0 +1,106 @@
1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient';
3
4import { Ctx, Cmd } from '../ctx';
5
6// Opens the virtual file that will show the syntax tree
7//
8// The contents of the file come from the `TextDocumentContentProvider`
9export function syntaxTree(ctx: Ctx): Cmd {
10 const stcp = new SyntaxTreeContentProvider(ctx);
11
12 ctx.pushCleanup(
13 vscode.workspace.registerTextDocumentContentProvider(
14 'rust-analyzer',
15 stcp,
16 ),
17 );
18
19 vscode.workspace.onDidChangeTextDocument(
20 (event: vscode.TextDocumentChangeEvent) => {
21 const doc = event.document;
22 if (doc.languageId !== 'rust') return;
23 afterLs(() => stcp.eventEmitter.fire(stcp.uri));
24 },
25 ctx.subscriptions,
26 );
27
28 vscode.window.onDidChangeActiveTextEditor(
29 (editor: vscode.TextEditor | undefined) => {
30 if (!editor || editor.document.languageId !== 'rust') return;
31 stcp.eventEmitter.fire(stcp.uri);
32 },
33 ctx.subscriptions,
34 );
35
36 return async () => {
37 const editor = vscode.window.activeTextEditor;
38 const rangeEnabled = !!(editor && !editor.selection.isEmpty);
39
40 const uri = rangeEnabled
41 ? vscode.Uri.parse(`${stcp.uri.toString()}?range=true`)
42 : stcp.uri;
43
44 const document = await vscode.workspace.openTextDocument(uri);
45
46 stcp.eventEmitter.fire(uri);
47
48 return vscode.window.showTextDocument(
49 document,
50 vscode.ViewColumn.Two,
51 true,
52 );
53 };
54}
55
56// We need to order this after LS updates, but there's no API for that.
57// Hence, good old setTimeout.
58function afterLs(f: () => any) {
59 setTimeout(f, 10);
60}
61
62interface SyntaxTreeParams {
63 textDocument: lc.TextDocumentIdentifier;
64 range?: lc.Range;
65}
66
67export class SyntaxTreeContentProvider
68 implements vscode.TextDocumentContentProvider {
69 ctx: Ctx;
70 uri = vscode.Uri.parse('rust-analyzer://syntaxtree');
71 eventEmitter = new vscode.EventEmitter<vscode.Uri>();
72 syntaxTree: string = 'Not available';
73
74 constructor(ctx: Ctx) {
75 this.ctx = ctx;
76 }
77
78 provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult<string> {
79 const editor = vscode.window.activeTextEditor;
80 if (editor == null) return '';
81
82 let range: lc.Range | undefined;
83
84 // When the range based query is enabled we take the range of the selection
85 if (uri.query === 'range=true') {
86 range = editor.selection.isEmpty
87 ? undefined
88 : this.ctx.client.code2ProtocolConverter.asRange(
89 editor.selection,
90 );
91 }
92
93 const request: SyntaxTreeParams = {
94 textDocument: { uri: editor.document.uri.toString() },
95 range,
96 };
97 return this.ctx.client.sendRequest<string>(
98 'rust-analyzer/syntaxTree',
99 request,
100 );
101 }
102
103 get onDidChange(): vscode.Event<vscode.Uri> {
104 return this.eventEmitter.event;
105 }
106}