]> git.lizzy.rs Git - rust.git/blob - editors/code/src/ctx.ts
Merge #7068
[rust.git] / editors / code / src / ctx.ts
1 import * as vscode from 'vscode';
2 import * as lc from 'vscode-languageclient/node';
3 import * as ra from './lsp_ext';
4
5 import { Config } from './config';
6 import { createClient } from './client';
7 import { isRustEditor, RustEditor } from './util';
8 import { Status } from './lsp_ext';
9
10 export class Ctx {
11     private constructor(
12         readonly config: Config,
13         private readonly extCtx: vscode.ExtensionContext,
14         readonly client: lc.LanguageClient,
15         readonly serverPath: string,
16         readonly statusBar: vscode.StatusBarItem,
17     ) {
18
19     }
20
21     static async create(
22         config: Config,
23         extCtx: vscode.ExtensionContext,
24         serverPath: string,
25         cwd: string,
26     ): Promise<Ctx> {
27         const client = createClient(serverPath, cwd, config.serverExtraEnv);
28
29         const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
30         extCtx.subscriptions.push(statusBar);
31         statusBar.text = "rust-analyzer";
32         statusBar.tooltip = "ready";
33         statusBar.show();
34
35         const res = new Ctx(config, extCtx, client, serverPath, statusBar);
36
37         res.pushCleanup(client.start());
38         await client.onReady();
39         client.onNotification(ra.status, (params) => res.setStatus(params.status));
40         return res;
41     }
42
43     get activeRustEditor(): RustEditor | undefined {
44         const editor = vscode.window.activeTextEditor;
45         return editor && isRustEditor(editor)
46             ? editor
47             : undefined;
48     }
49
50     get visibleRustEditors(): RustEditor[] {
51         return vscode.window.visibleTextEditors.filter(isRustEditor);
52     }
53
54     registerCommand(name: string, factory: (ctx: Ctx) => Cmd) {
55         const fullName = `rust-analyzer.${name}`;
56         const cmd = factory(this);
57         const d = vscode.commands.registerCommand(fullName, cmd);
58         this.pushCleanup(d);
59     }
60
61     get globalState(): vscode.Memento {
62         return this.extCtx.globalState;
63     }
64
65     get subscriptions(): Disposable[] {
66         return this.extCtx.subscriptions;
67     }
68
69     setStatus(status: Status) {
70         switch (status) {
71             case "loading":
72                 this.statusBar.text = "$(sync~spin) rust-analyzer";
73                 this.statusBar.tooltip = "Loading the project";
74                 this.statusBar.command = undefined;
75                 this.statusBar.color = undefined;
76                 break;
77             case "ready":
78                 this.statusBar.text = "rust-analyzer";
79                 this.statusBar.tooltip = "Ready";
80                 this.statusBar.command = undefined;
81                 this.statusBar.color = undefined;
82                 break;
83             case "invalid":
84                 this.statusBar.text = "$(error) rust-analyzer";
85                 this.statusBar.tooltip = "Failed to load the project";
86                 this.statusBar.command = undefined;
87                 this.statusBar.color = new vscode.ThemeColor("notificationsErrorIcon.foreground");
88                 break;
89             case "needsReload":
90                 this.statusBar.text = "$(warning) rust-analyzer";
91                 this.statusBar.tooltip = "Click to reload";
92                 this.statusBar.command = "rust-analyzer.reloadWorkspace";
93                 this.statusBar.color = new vscode.ThemeColor("notificationsWarningIcon.foreground");
94                 break;
95         }
96     }
97
98     pushCleanup(d: Disposable) {
99         this.extCtx.subscriptions.push(d);
100     }
101 }
102
103 export interface Disposable {
104     dispose(): void;
105 }
106 export type Cmd = (...args: any[]) => unknown;