aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/main.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/main.ts')
-rw-r--r--editors/code/src/main.ts203
1 files changed, 203 insertions, 0 deletions
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
new file mode 100644
index 000000000..1da10ebd0
--- /dev/null
+++ b/editors/code/src/main.ts
@@ -0,0 +1,203 @@
1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient';
3
4import * as commands from './commands';
5import { ExpandMacroContentProvider } from './commands/expand_macro';
6import { HintsUpdater } from './commands/inlay_hints';
7import { SyntaxTreeContentProvider } from './commands/syntaxTree';
8import { StatusDisplay } from './commands/watch_status';
9import * as events from './events';
10import * as notifications from './notifications';
11import { Server } from './server';
12
13export async function activate(context: vscode.ExtensionContext) {
14 function disposeOnDeactivation(disposable: vscode.Disposable) {
15 context.subscriptions.push(disposable);
16 }
17
18 function registerCommand(name: string, f: any) {
19 disposeOnDeactivation(vscode.commands.registerCommand(name, f));
20 }
21 function overrideCommand(
22 name: string,
23 f: (...args: any[]) => Promise<boolean>,
24 ) {
25 const defaultCmd = `default:${name}`;
26 const original = (...args: any[]) =>
27 vscode.commands.executeCommand(defaultCmd, ...args);
28
29 try {
30 registerCommand(name, async (...args: any[]) => {
31 const editor = vscode.window.activeTextEditor;
32 if (
33 !editor ||
34 !editor.document ||
35 editor.document.languageId !== 'rust'
36 ) {
37 return await original(...args);
38 }
39 if (!(await f(...args))) {
40 return await original(...args);
41 }
42 });
43 } catch (_) {
44 vscode.window.showWarningMessage(
45 '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',
46 );
47 }
48 }
49
50 // Commands are requests from vscode to the language server
51 registerCommand(
52 'rust-analyzer.analyzerStatus',
53 commands.analyzerStatus.makeCommand(context),
54 );
55 registerCommand('rust-analyzer.collectGarbage', () =>
56 Server.client.sendRequest<null>('rust-analyzer/collectGarbage', null),
57 );
58 registerCommand(
59 'rust-analyzer.matchingBrace',
60 commands.matchingBrace.handle,
61 );
62 registerCommand('rust-analyzer.joinLines', commands.joinLines.handle);
63 registerCommand('rust-analyzer.parentModule', commands.parentModule.handle);
64 registerCommand('rust-analyzer.run', commands.runnables.handle);
65 // Unlike the above this does not send requests to the language server
66 registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle);
67 registerCommand(
68 'rust-analyzer.applySourceChange',
69 commands.applySourceChange.handle,
70 );
71 registerCommand(
72 'rust-analyzer.showReferences',
73 (uri: string, position: lc.Position, locations: lc.Location[]) => {
74 vscode.commands.executeCommand(
75 'editor.action.showReferences',
76 vscode.Uri.parse(uri),
77 Server.client.protocol2CodeConverter.asPosition(position),
78 locations.map(Server.client.protocol2CodeConverter.asLocation),
79 );
80 },
81 );
82
83 if (Server.config.enableEnhancedTyping) {
84 overrideCommand('type', commands.onEnter.handle);
85 }
86
87 const watchStatus = new StatusDisplay(
88 Server.config.cargoWatchOptions.command,
89 );
90 disposeOnDeactivation(watchStatus);
91
92 // Notifications are events triggered by the language server
93 const allNotifications: Iterable<[
94 string,
95 lc.GenericNotificationHandler,
96 ]> = [
97 [
98 'rust-analyzer/publishDecorations',
99 notifications.publishDecorations.handle,
100 ],
101 [
102 '$/progress',
103 params => watchStatus.handleProgressNotification(params),
104 ],
105 ];
106 const syntaxTreeContentProvider = new SyntaxTreeContentProvider();
107 const expandMacroContentProvider = new ExpandMacroContentProvider();
108
109 // The events below are plain old javascript events, triggered and handled by vscode
110 vscode.window.onDidChangeActiveTextEditor(
111 events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider),
112 );
113
114 disposeOnDeactivation(
115 vscode.workspace.registerTextDocumentContentProvider(
116 'rust-analyzer',
117 syntaxTreeContentProvider,
118 ),
119 );
120 disposeOnDeactivation(
121 vscode.workspace.registerTextDocumentContentProvider(
122 'rust-analyzer',
123 expandMacroContentProvider,
124 ),
125 );
126
127 registerCommand(
128 'rust-analyzer.syntaxTree',
129 commands.syntaxTree.createHandle(syntaxTreeContentProvider),
130 );
131 registerCommand(
132 'rust-analyzer.expandMacro',
133 commands.expandMacro.createHandle(expandMacroContentProvider),
134 );
135
136 vscode.workspace.onDidChangeTextDocument(
137 events.changeTextDocument.createHandler(syntaxTreeContentProvider),
138 null,
139 context.subscriptions,
140 );
141
142 const startServer = () => Server.start(allNotifications);
143 const reloadCommand = () => reloadServer(startServer);
144
145 vscode.commands.registerCommand('rust-analyzer.reload', reloadCommand);
146
147 // Start the language server, finally!
148 try {
149 await startServer();
150 } catch (e) {
151 vscode.window.showErrorMessage(e.message);
152 }
153
154 if (Server.config.displayInlayHints) {
155 const hintsUpdater = new HintsUpdater();
156 hintsUpdater.refreshHintsForVisibleEditors().then(() => {
157 // vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors()
158 // so update the hints once when the focus changes to guarantee their presence
159 let editorChangeDisposable: vscode.Disposable | null = null;
160 editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor(
161 _ => {
162 if (editorChangeDisposable !== null) {
163 editorChangeDisposable.dispose();
164 }
165 return hintsUpdater.refreshHintsForVisibleEditors();
166 },
167 );
168
169 disposeOnDeactivation(
170 vscode.window.onDidChangeVisibleTextEditors(_ =>
171 hintsUpdater.refreshHintsForVisibleEditors(),
172 ),
173 );
174 disposeOnDeactivation(
175 vscode.workspace.onDidChangeTextDocument(e =>
176 hintsUpdater.refreshHintsForVisibleEditors(e),
177 ),
178 );
179 disposeOnDeactivation(
180 vscode.workspace.onDidChangeConfiguration(_ =>
181 hintsUpdater.toggleHintsDisplay(
182 Server.config.displayInlayHints,
183 ),
184 ),
185 );
186 });
187 }
188}
189
190export function deactivate(): Thenable<void> {
191 if (!Server.client) {
192 return Promise.resolve();
193 }
194 return Server.client.stop();
195}
196
197async function reloadServer(startServer: () => Promise<void>) {
198 if (Server.client != null) {
199 vscode.window.showInformationMessage('Reloading rust-analyzer...');
200 await Server.client.stop();
201 await startServer();
202 }
203}