diff options
-rw-r--r-- | editors/code/package.json | 2 | ||||
-rw-r--r-- | editors/code/src/commands/analyzer_status.ts | 17 | ||||
-rw-r--r-- | editors/code/src/commands/index.ts | 18 | ||||
-rw-r--r-- | editors/code/src/commands/join_lines.ts | 45 | ||||
-rw-r--r-- | editors/code/src/commands/matching_brace.ts | 15 | ||||
-rw-r--r-- | editors/code/src/commands/on_enter.ts | 51 | ||||
-rw-r--r-- | editors/code/src/commands/parent_module.ts | 54 | ||||
-rw-r--r-- | editors/code/src/commands/syntaxTree.ts | 76 | ||||
-rw-r--r-- | editors/code/src/commands/syntax_tree.ts | 106 | ||||
-rw-r--r-- | editors/code/src/ctx.ts | 26 | ||||
-rw-r--r-- | editors/code/src/events/change_active_text_editor.ts | 9 | ||||
-rw-r--r-- | editors/code/src/events/change_text_document.ts | 24 | ||||
-rw-r--r-- | editors/code/src/events/index.ts | 3 | ||||
-rw-r--r-- | editors/code/src/main.ts | 64 | ||||
-rw-r--r-- | editors/code/src/source_change.ts (renamed from editors/code/src/commands/apply_source_change.ts) | 10 |
15 files changed, 240 insertions, 280 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index 6662747f6..46d55e32d 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -19,7 +19,7 @@ | |||
19 | "vscode:prepublish": "rollup -c", | 19 | "vscode:prepublish": "rollup -c", |
20 | "package": "vsce package", | 20 | "package": "vsce package", |
21 | "watch": "tsc -watch -p ./", | 21 | "watch": "tsc -watch -p ./", |
22 | "prettier": "prettier --write **/*.ts" | 22 | "prettier": "prettier --write '**/*.ts'" |
23 | }, | 23 | }, |
24 | "dependencies": { | 24 | "dependencies": { |
25 | "jsonc-parser": "^2.1.0", | 25 | "jsonc-parser": "^2.1.0", |
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 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | |||
2 | import { Ctx, Cmd } from '../ctx'; | 3 | import { 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 | ||
40 | class TextDocumentContentProvider | 38 | class 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/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 @@ | |||
1 | import { Ctx, Cmd } from '../ctx' | 1 | import { Ctx, Cmd } from '../ctx'; |
2 | 2 | ||
3 | import { analyzerStatus } from './analyzer_status'; | 3 | import { analyzerStatus } from './analyzer_status'; |
4 | import { matchingBrace } from './matching_brace'; | 4 | import { matchingBrace } from './matching_brace'; |
5 | import * as applySourceChange from './apply_source_change'; | 5 | import { joinLines } from './join_lines'; |
6 | import { onEnter } from './on_enter'; | ||
7 | import { parentModule } from './parent_module'; | ||
8 | import { syntaxTree } from './syntax_tree'; | ||
6 | import * as expandMacro from './expand_macro'; | 9 | import * as expandMacro from './expand_macro'; |
7 | import * as inlayHints from './inlay_hints'; | 10 | import * as inlayHints from './inlay_hints'; |
8 | import * as joinLines from './join_lines'; | ||
9 | import * as onEnter from './on_enter'; | ||
10 | import * as parentModule from './parent_module'; | ||
11 | import * as runnables from './runnables'; | 11 | import * as runnables from './runnables'; |
12 | import * as syntaxTree from './syntaxTree'; | ||
13 | 12 | ||
14 | function collectGarbage(ctx: Ctx): Cmd { | 13 | function 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 | ||
18 | export { | 19 | export { |
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 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as lc from 'vscode-languageclient'; |
2 | 2 | ||
3 | import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; | 3 | import { Ctx, Cmd } from '../ctx'; |
4 | import { Server } from '../server'; | 4 | import { applySourceChange, SourceChange } from '../source_change'; |
5 | import { | ||
6 | handle as applySourceChange, | ||
7 | SourceChange, | ||
8 | } from './apply_source_change'; | ||
9 | 5 | ||
10 | interface JoinLinesParams { | 6 | export 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 | ||
15 | export 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, | 23 | interface 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 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import { Position, TextDocumentIdentifier } from 'vscode-languageclient'; | 2 | import * as lc from 'vscode-languageclient'; |
3 | |||
3 | import { Ctx, Cmd } from '../ctx'; | 4 | import { Ctx, Cmd } from '../ctx'; |
4 | 5 | ||
5 | export function matchingBrace(ctx: Ctx): Cmd { | 6 | export 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 | ||
30 | interface FindMatchingBraceParams { | 33 | interface 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 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import * as lc from 'vscode-languageclient'; | 1 | import * as lc from 'vscode-languageclient'; |
3 | import { Server } from '../server'; | ||
4 | import { | ||
5 | handle as applySourceChange, | ||
6 | SourceChange, | ||
7 | } from './apply_source_change'; | ||
8 | 2 | ||
9 | export async function handle(event: { text: string }): Promise<boolean> { | 3 | import { applySourceChange, SourceChange } from '../source_change'; |
10 | const editor = vscode.window.activeTextEditor; | 4 | import { Cmd, Ctx } from '../ctx'; |
11 | if ( | 5 | |
12 | editor == null || | 6 | export 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 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | |||
3 | import * as lc from 'vscode-languageclient'; | 2 | import * as lc from 'vscode-languageclient'; |
4 | import { Server } from '../server'; | ||
5 | 3 | ||
6 | export async function handle() { | 4 | import { Ctx, Cmd } from '../ctx'; |
7 | const editor = vscode.window.activeTextEditor; | 5 | |
8 | if (editor == null || editor.document.languageId !== 'rust') { | 6 | export 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 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; | ||
3 | |||
4 | import { Server } from '../server'; | ||
5 | |||
6 | export const syntaxTreeUri = vscode.Uri.parse('rust-analyzer://syntaxtree'); | ||
7 | |||
8 | export 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 | |||
47 | interface SyntaxTreeParams { | ||
48 | textDocument: TextDocumentIdentifier; | ||
49 | range?: Range; | ||
50 | } | ||
51 | |||
52 | type 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` | ||
57 | export 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 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import * as lc from 'vscode-languageclient'; | ||
3 | |||
4 | import { 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` | ||
9 | export 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. | ||
58 | function afterLs(f: () => any) { | ||
59 | setTimeout(f, 10); | ||
60 | } | ||
61 | |||
62 | interface SyntaxTreeParams { | ||
63 | textDocument: lc.TextDocumentIdentifier; | ||
64 | range?: lc.Range; | ||
65 | } | ||
66 | |||
67 | export 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 | } | ||
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 712337fe7..c3a3583b5 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts | |||
@@ -27,6 +27,32 @@ export class Ctx { | |||
27 | this.pushCleanup(d); | 27 | this.pushCleanup(d); |
28 | } | 28 | } |
29 | 29 | ||
30 | overrideCommand(name: string, factory: (ctx: Ctx) => Cmd) { | ||
31 | const defaultCmd = `default:${name}`; | ||
32 | const override = factory(this); | ||
33 | const original = (...args: any[]) => | ||
34 | vscode.commands.executeCommand(defaultCmd, ...args); | ||
35 | try { | ||
36 | const d = vscode.commands.registerCommand( | ||
37 | name, | ||
38 | async (...args: any[]) => { | ||
39 | if (!(await override(...args))) { | ||
40 | return await original(...args); | ||
41 | } | ||
42 | }, | ||
43 | ); | ||
44 | this.pushCleanup(d); | ||
45 | } catch (_) { | ||
46 | vscode.window.showWarningMessage( | ||
47 | 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings', | ||
48 | ); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | get subscriptions(): { dispose(): any }[] { | ||
53 | return this.extCtx.subscriptions; | ||
54 | } | ||
55 | |||
30 | pushCleanup(d: { dispose(): any }) { | 56 | pushCleanup(d: { dispose(): any }) { |
31 | this.extCtx.subscriptions.push(d); | 57 | this.extCtx.subscriptions.push(d); |
32 | } | 58 | } |
diff --git a/editors/code/src/events/change_active_text_editor.ts b/editors/code/src/events/change_active_text_editor.ts index 74b91bd48..4384ee567 100644 --- a/editors/code/src/events/change_active_text_editor.ts +++ b/editors/code/src/events/change_active_text_editor.ts | |||
@@ -1,21 +1,14 @@ | |||
1 | import { TextEditor } from 'vscode'; | 1 | import { TextEditor } from 'vscode'; |
2 | import { TextDocumentIdentifier } from 'vscode-languageclient'; | 2 | import { TextDocumentIdentifier } from 'vscode-languageclient'; |
3 | |||
4 | import { | ||
5 | SyntaxTreeContentProvider, | ||
6 | syntaxTreeUri, | ||
7 | } from '../commands/syntaxTree'; | ||
8 | import { Decoration } from '../highlighting'; | 3 | import { Decoration } from '../highlighting'; |
9 | import { Server } from '../server'; | 4 | import { Server } from '../server'; |
10 | 5 | ||
11 | export function makeHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { | 6 | export function makeHandler() { |
12 | return async function handle(editor: TextEditor | undefined) { | 7 | return async function handle(editor: TextEditor | undefined) { |
13 | if (!editor || editor.document.languageId !== 'rust') { | 8 | if (!editor || editor.document.languageId !== 'rust') { |
14 | return; | 9 | return; |
15 | } | 10 | } |
16 | 11 | ||
17 | syntaxTreeProvider.eventEmitter.fire(syntaxTreeUri); | ||
18 | |||
19 | if (!Server.config.highlightingOn) { | 12 | if (!Server.config.highlightingOn) { |
20 | return; | 13 | return; |
21 | } | 14 | } |
diff --git a/editors/code/src/events/change_text_document.ts b/editors/code/src/events/change_text_document.ts deleted file mode 100644 index 2e998e889..000000000 --- a/editors/code/src/events/change_text_document.ts +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | |||
3 | import { | ||
4 | SyntaxTreeContentProvider, | ||
5 | syntaxTreeUri, | ||
6 | } from '../commands/syntaxTree'; | ||
7 | |||
8 | export function createHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { | ||
9 | return (event: vscode.TextDocumentChangeEvent) => { | ||
10 | const doc = event.document; | ||
11 | if (doc.languageId !== 'rust') { | ||
12 | return; | ||
13 | } | ||
14 | afterLs(() => { | ||
15 | syntaxTreeProvider.eventEmitter.fire(syntaxTreeUri); | ||
16 | }); | ||
17 | }; | ||
18 | } | ||
19 | |||
20 | // We need to order this after LS updates, but there's no API for that. | ||
21 | // Hence, good old setTimeout. | ||
22 | function afterLs(f: () => any) { | ||
23 | setTimeout(f, 10); | ||
24 | } | ||
diff --git a/editors/code/src/events/index.ts b/editors/code/src/events/index.ts index 4c154563f..be135474d 100644 --- a/editors/code/src/events/index.ts +++ b/editors/code/src/events/index.ts | |||
@@ -1,4 +1,3 @@ | |||
1 | import * as changeActiveTextEditor from './change_active_text_editor'; | 1 | import * as changeActiveTextEditor from './change_active_text_editor'; |
2 | import * as changeTextDocument from './change_text_document'; | ||
3 | 2 | ||
4 | export { changeActiveTextEditor, changeTextDocument }; | 3 | export { changeActiveTextEditor }; |
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index a4149a059..d92cd164f 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -4,7 +4,6 @@ import * as lc from 'vscode-languageclient'; | |||
4 | import * as commands from './commands'; | 4 | import * as commands from './commands'; |
5 | import { ExpandMacroContentProvider } from './commands/expand_macro'; | 5 | import { ExpandMacroContentProvider } from './commands/expand_macro'; |
6 | import { HintsUpdater } from './commands/inlay_hints'; | 6 | import { HintsUpdater } from './commands/inlay_hints'; |
7 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | ||
8 | import { StatusDisplay } from './commands/watch_status'; | 7 | import { StatusDisplay } from './commands/watch_status'; |
9 | import * as events from './events'; | 8 | import * as events from './events'; |
10 | import * as notifications from './notifications'; | 9 | import * as notifications from './notifications'; |
@@ -18,6 +17,9 @@ export async function activate(context: vscode.ExtensionContext) { | |||
18 | ctx.registerCommand('analyzerStatus', commands.analyzerStatus); | 17 | ctx.registerCommand('analyzerStatus', commands.analyzerStatus); |
19 | ctx.registerCommand('collectGarbage', commands.collectGarbage); | 18 | ctx.registerCommand('collectGarbage', commands.collectGarbage); |
20 | ctx.registerCommand('matchingBrace', commands.matchingBrace); | 19 | ctx.registerCommand('matchingBrace', commands.matchingBrace); |
20 | ctx.registerCommand('joinLines', commands.joinLines); | ||
21 | ctx.registerCommand('parentModule', commands.parentModule); | ||
22 | ctx.registerCommand('syntaxTree', commands.syntaxTree); | ||
21 | 23 | ||
22 | function disposeOnDeactivation(disposable: vscode.Disposable) { | 24 | function disposeOnDeactivation(disposable: vscode.Disposable) { |
23 | context.subscriptions.push(disposable); | 25 | context.subscriptions.push(disposable); |
@@ -26,46 +28,12 @@ export async function activate(context: vscode.ExtensionContext) { | |||
26 | function registerCommand(name: string, f: any) { | 28 | function registerCommand(name: string, f: any) { |
27 | disposeOnDeactivation(vscode.commands.registerCommand(name, f)); | 29 | disposeOnDeactivation(vscode.commands.registerCommand(name, f)); |
28 | } | 30 | } |
29 | function overrideCommand( | ||
30 | name: string, | ||
31 | f: (...args: any[]) => Promise<boolean>, | ||
32 | ) { | ||
33 | const defaultCmd = `default:${name}`; | ||
34 | const original = (...args: any[]) => | ||
35 | vscode.commands.executeCommand(defaultCmd, ...args); | ||
36 | |||
37 | try { | ||
38 | registerCommand(name, async (...args: any[]) => { | ||
39 | const editor = vscode.window.activeTextEditor; | ||
40 | if ( | ||
41 | !editor || | ||
42 | !editor.document || | ||
43 | editor.document.languageId !== 'rust' | ||
44 | ) { | ||
45 | return await original(...args); | ||
46 | } | ||
47 | if (!(await f(...args))) { | ||
48 | return await original(...args); | ||
49 | } | ||
50 | }); | ||
51 | } catch (_) { | ||
52 | vscode.window.showWarningMessage( | ||
53 | 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings', | ||
54 | ); | ||
55 | } | ||
56 | } | ||
57 | 31 | ||
58 | // Commands are requests from vscode to the language server | 32 | // Commands are requests from vscode to the language server |
59 | registerCommand('rust-analyzer.joinLines', commands.joinLines.handle); | ||
60 | registerCommand('rust-analyzer.parentModule', commands.parentModule.handle); | ||
61 | registerCommand('rust-analyzer.run', commands.runnables.handle); | 33 | registerCommand('rust-analyzer.run', commands.runnables.handle); |
62 | // Unlike the above this does not send requests to the language server | 34 | // Unlike the above this does not send requests to the language server |
63 | registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle); | 35 | registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle); |
64 | registerCommand( | 36 | registerCommand( |
65 | 'rust-analyzer.applySourceChange', | ||
66 | commands.applySourceChange.handle, | ||
67 | ); | ||
68 | registerCommand( | ||
69 | 'rust-analyzer.showReferences', | 37 | 'rust-analyzer.showReferences', |
70 | (uri: string, position: lc.Position, locations: lc.Location[]) => { | 38 | (uri: string, position: lc.Position, locations: lc.Location[]) => { |
71 | vscode.commands.executeCommand( | 39 | vscode.commands.executeCommand( |
@@ -78,7 +46,7 @@ export async function activate(context: vscode.ExtensionContext) { | |||
78 | ); | 46 | ); |
79 | 47 | ||
80 | if (Server.config.enableEnhancedTyping) { | 48 | if (Server.config.enableEnhancedTyping) { |
81 | overrideCommand('type', commands.onEnter.handle); | 49 | ctx.overrideCommand('type', commands.onEnter); |
82 | } | 50 | } |
83 | 51 | ||
84 | const watchStatus = new StatusDisplay( | 52 | const watchStatus = new StatusDisplay( |
@@ -87,10 +55,7 @@ export async function activate(context: vscode.ExtensionContext) { | |||
87 | disposeOnDeactivation(watchStatus); | 55 | disposeOnDeactivation(watchStatus); |
88 | 56 | ||
89 | // Notifications are events triggered by the language server | 57 | // Notifications are events triggered by the language server |
90 | const allNotifications: Iterable<[ | 58 | const allNotifications: [string, lc.GenericNotificationHandler][] = [ |
91 | string, | ||
92 | lc.GenericNotificationHandler, | ||
93 | ]> = [ | ||
94 | [ | 59 | [ |
95 | 'rust-analyzer/publishDecorations', | 60 | 'rust-analyzer/publishDecorations', |
96 | notifications.publishDecorations.handle, | 61 | notifications.publishDecorations.handle, |
@@ -100,42 +65,25 @@ export async function activate(context: vscode.ExtensionContext) { | |||
100 | params => watchStatus.handleProgressNotification(params), | 65 | params => watchStatus.handleProgressNotification(params), |
101 | ], | 66 | ], |
102 | ]; | 67 | ]; |
103 | const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); | ||
104 | const expandMacroContentProvider = new ExpandMacroContentProvider(); | 68 | const expandMacroContentProvider = new ExpandMacroContentProvider(); |
105 | 69 | ||
106 | // The events below are plain old javascript events, triggered and handled by vscode | 70 | // The events below are plain old javascript events, triggered and handled by vscode |
107 | vscode.window.onDidChangeActiveTextEditor( | 71 | vscode.window.onDidChangeActiveTextEditor( |
108 | events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider), | 72 | events.changeActiveTextEditor.makeHandler(), |
109 | ); | 73 | ); |
110 | 74 | ||
111 | disposeOnDeactivation( | 75 | disposeOnDeactivation( |
112 | vscode.workspace.registerTextDocumentContentProvider( | 76 | vscode.workspace.registerTextDocumentContentProvider( |
113 | 'rust-analyzer', | 77 | 'rust-analyzer', |
114 | syntaxTreeContentProvider, | ||
115 | ), | ||
116 | ); | ||
117 | disposeOnDeactivation( | ||
118 | vscode.workspace.registerTextDocumentContentProvider( | ||
119 | 'rust-analyzer', | ||
120 | expandMacroContentProvider, | 78 | expandMacroContentProvider, |
121 | ), | 79 | ), |
122 | ); | 80 | ); |
123 | 81 | ||
124 | registerCommand( | 82 | registerCommand( |
125 | 'rust-analyzer.syntaxTree', | ||
126 | commands.syntaxTree.createHandle(syntaxTreeContentProvider), | ||
127 | ); | ||
128 | registerCommand( | ||
129 | 'rust-analyzer.expandMacro', | 83 | 'rust-analyzer.expandMacro', |
130 | commands.expandMacro.createHandle(expandMacroContentProvider), | 84 | commands.expandMacro.createHandle(expandMacroContentProvider), |
131 | ); | 85 | ); |
132 | 86 | ||
133 | vscode.workspace.onDidChangeTextDocument( | ||
134 | events.changeTextDocument.createHandler(syntaxTreeContentProvider), | ||
135 | null, | ||
136 | context.subscriptions, | ||
137 | ); | ||
138 | |||
139 | const startServer = () => Server.start(allNotifications); | 87 | const startServer = () => Server.start(allNotifications); |
140 | const reloadCommand = () => reloadServer(startServer); | 88 | const reloadCommand = () => reloadServer(startServer); |
141 | 89 | ||
diff --git a/editors/code/src/commands/apply_source_change.ts b/editors/code/src/source_change.ts index 8167398b1..a4f9068b2 100644 --- a/editors/code/src/commands/apply_source_change.ts +++ b/editors/code/src/source_change.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import * as lc from 'vscode-languageclient'; | 2 | import * as lc from 'vscode-languageclient'; |
3 | 3 | ||
4 | import { Server } from '../server'; | 4 | import { Ctx } from './ctx'; |
5 | 5 | ||
6 | export interface SourceChange { | 6 | export interface SourceChange { |
7 | label: string; | 7 | label: string; |
@@ -9,8 +9,8 @@ export interface SourceChange { | |||
9 | cursorPosition?: lc.TextDocumentPositionParams; | 9 | cursorPosition?: lc.TextDocumentPositionParams; |
10 | } | 10 | } |
11 | 11 | ||
12 | export async function handle(change: SourceChange) { | 12 | export async function applySourceChange(ctx: Ctx, change: SourceChange) { |
13 | const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit( | 13 | const wsEdit = ctx.client.protocol2CodeConverter.asWorkspaceEdit( |
14 | change.workspaceEdit, | 14 | change.workspaceEdit, |
15 | ); | 15 | ); |
16 | let created; | 16 | let created; |
@@ -32,10 +32,10 @@ export async function handle(change: SourceChange) { | |||
32 | const doc = await vscode.workspace.openTextDocument(toOpenUri); | 32 | const doc = await vscode.workspace.openTextDocument(toOpenUri); |
33 | await vscode.window.showTextDocument(doc); | 33 | await vscode.window.showTextDocument(doc); |
34 | } else if (toReveal) { | 34 | } else if (toReveal) { |
35 | const uri = Server.client.protocol2CodeConverter.asUri( | 35 | const uri = ctx.client.protocol2CodeConverter.asUri( |
36 | toReveal.textDocument.uri, | 36 | toReveal.textDocument.uri, |
37 | ); | 37 | ); |
38 | const position = Server.client.protocol2CodeConverter.asPosition( | 38 | const position = ctx.client.protocol2CodeConverter.asPosition( |
39 | toReveal.position, | 39 | toReveal.position, |
40 | ); | 40 | ); |
41 | const editor = vscode.window.activeTextEditor; | 41 | const editor = vscode.window.activeTextEditor; |