diff options
Diffstat (limited to 'editors/code/src/main.ts')
-rw-r--r-- | editors/code/src/main.ts | 203 |
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 @@ | |||
1 | import * as vscode from 'vscode'; | ||
2 | import * as lc from 'vscode-languageclient'; | ||
3 | |||
4 | import * as commands from './commands'; | ||
5 | import { ExpandMacroContentProvider } from './commands/expand_macro'; | ||
6 | import { HintsUpdater } from './commands/inlay_hints'; | ||
7 | import { SyntaxTreeContentProvider } from './commands/syntaxTree'; | ||
8 | import { StatusDisplay } from './commands/watch_status'; | ||
9 | import * as events from './events'; | ||
10 | import * as notifications from './notifications'; | ||
11 | import { Server } from './server'; | ||
12 | |||
13 | export 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 | |||
190 | export function deactivate(): Thenable<void> { | ||
191 | if (!Server.client) { | ||
192 | return Promise.resolve(); | ||
193 | } | ||
194 | return Server.client.stop(); | ||
195 | } | ||
196 | |||
197 | async 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 | } | ||