]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/editors/code/src/ctx.ts
Rollup merge of #98441 - calebzulawski:simd_as, r=oli-obk
[rust.git] / src / tools / rust-analyzer / 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 { ServerStatusParams } from "./lsp_ext";
9
10 export type Workspace =
11     | {
12           kind: "Workspace Folder";
13       }
14     | {
15           kind: "Detached Files";
16           files: vscode.TextDocument[];
17       };
18
19 export class Ctx {
20     private constructor(
21         readonly config: Config,
22         private readonly extCtx: vscode.ExtensionContext,
23         readonly client: lc.LanguageClient,
24         readonly serverPath: string,
25         readonly statusBar: vscode.StatusBarItem
26     ) {}
27
28     static async create(
29         config: Config,
30         extCtx: vscode.ExtensionContext,
31         serverPath: string,
32         workspace: Workspace
33     ): Promise<Ctx> {
34         const client = await createClient(serverPath, workspace, config.serverExtraEnv);
35
36         const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
37         extCtx.subscriptions.push(statusBar);
38         statusBar.text = "rust-analyzer";
39         statusBar.tooltip = "ready";
40         statusBar.command = "rust-analyzer.analyzerStatus";
41         statusBar.show();
42
43         const res = new Ctx(config, extCtx, client, serverPath, statusBar);
44
45         res.pushCleanup(client.start());
46         await client.onReady();
47         client.onNotification(ra.serverStatus, (params) => res.setServerStatus(params));
48         return res;
49     }
50
51     get activeRustEditor(): RustEditor | undefined {
52         const editor = vscode.window.activeTextEditor;
53         return editor && isRustEditor(editor) ? editor : undefined;
54     }
55
56     get visibleRustEditors(): RustEditor[] {
57         return vscode.window.visibleTextEditors.filter(isRustEditor);
58     }
59
60     registerCommand(name: string, factory: (ctx: Ctx) => Cmd) {
61         const fullName = `rust-analyzer.${name}`;
62         const cmd = factory(this);
63         const d = vscode.commands.registerCommand(fullName, cmd);
64         this.pushCleanup(d);
65     }
66
67     get extensionPath(): string {
68         return this.extCtx.extensionPath;
69     }
70
71     get globalState(): vscode.Memento {
72         return this.extCtx.globalState;
73     }
74
75     get subscriptions(): Disposable[] {
76         return this.extCtx.subscriptions;
77     }
78
79     setServerStatus(status: ServerStatusParams) {
80         let icon = "";
81         const statusBar = this.statusBar;
82         switch (status.health) {
83             case "ok":
84                 statusBar.tooltip = status.message ?? "Ready";
85                 statusBar.command = undefined;
86                 statusBar.color = undefined;
87                 statusBar.backgroundColor = undefined;
88                 break;
89             case "warning":
90                 statusBar.tooltip =
91                     (status.message ? status.message + "\n" : "") + "Click to reload.";
92
93                 statusBar.command = "rust-analyzer.reloadWorkspace";
94                 statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
95                 statusBar.backgroundColor = new vscode.ThemeColor(
96                     "statusBarItem.warningBackground"
97                 );
98                 icon = "$(warning) ";
99                 break;
100             case "error":
101                 statusBar.tooltip =
102                     (status.message ? status.message + "\n" : "") + "Click to reload.";
103
104                 statusBar.command = "rust-analyzer.reloadWorkspace";
105                 statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
106                 statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
107                 icon = "$(error) ";
108                 break;
109         }
110         if (!status.quiescent) icon = "$(sync~spin) ";
111         statusBar.text = `${icon}rust-analyzer`;
112     }
113
114     pushCleanup(d: Disposable) {
115         this.extCtx.subscriptions.push(d);
116     }
117 }
118
119 export interface Disposable {
120     dispose(): void;
121 }
122 export type Cmd = (...args: any[]) => unknown;