]> git.lizzy.rs Git - rust.git/blob - editors/code/src/commands/syntax_tree.ts
Reformat with tsfmt
[rust.git] / editors / code / src / commands / syntax_tree.ts
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 tdcp = new TextDocumentContentProvider(ctx);
11
12     ctx.pushCleanup(
13         vscode.workspace.registerTextDocumentContentProvider(
14             'rust-analyzer',
15             tdcp,
16         ),
17     );
18
19     vscode.workspace.onDidChangeTextDocument(
20         (event: vscode.TextDocumentChangeEvent) => {
21             const doc = event.document;
22             if (doc.languageId !== 'rust') return;
23             afterLs(() => tdcp.eventEmitter.fire(tdcp.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             tdcp.eventEmitter.fire(tdcp.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(`${tdcp.uri.toString()}?range=true`)
42             : tdcp.uri;
43
44         const document = await vscode.workspace.openTextDocument(uri);
45
46         tdcp.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 class TextDocumentContentProvider
68     implements vscode.TextDocumentContentProvider {
69     private ctx: Ctx;
70     uri = vscode.Uri.parse('rust-analyzer://syntaxtree');
71     eventEmitter = new vscode.EventEmitter<vscode.Uri>();
72
73     constructor(ctx: Ctx) {
74         this.ctx = ctx;
75     }
76
77     provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult<string> {
78         const editor = vscode.window.activeTextEditor;
79         if (editor == null) return '';
80
81         let range: lc.Range | undefined;
82
83         // When the range based query is enabled we take the range of the selection
84         if (uri.query === 'range=true') {
85             range = editor.selection.isEmpty
86                 ? undefined
87                 : this.ctx.client.code2ProtocolConverter.asRange(
88                     editor.selection,
89                 );
90         }
91
92         const request: SyntaxTreeParams = {
93             textDocument: { uri: editor.document.uri.toString() },
94             range,
95         };
96         return this.ctx.client.sendRequest<string>(
97             'rust-analyzer/syntaxTree',
98             request,
99         );
100     }
101
102     get onDidChange(): vscode.Event<vscode.Uri> {
103         return this.eventEmitter.event;
104     }
105 }