diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/code/package.json | 5 | ||||
-rw-r--r-- | editors/code/src/commands/inlay_hints.ts | 76 | ||||
-rw-r--r-- | editors/code/src/config.ts | 4 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 20 | ||||
-rw-r--r-- | editors/code/src/server.ts | 3 | ||||
-rw-r--r-- | editors/emacs/ra-emacs-lsp.el | 73 |
6 files changed, 93 insertions, 88 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index 808dc5dc1..48ab886bf 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -197,6 +197,11 @@ | |||
197 | ], | 197 | ], |
198 | "description": "Whether to run `cargo watch` on startup" | 198 | "description": "Whether to run `cargo watch` on startup" |
199 | }, | 199 | }, |
200 | "rust-analyzer.excludeGlobs": { | ||
201 | "type": "array", | ||
202 | "default": "[]", | ||
203 | "description": "Paths to exclude from analysis" | ||
204 | }, | ||
200 | "rust-analyzer.cargo-watch.arguments": { | 205 | "rust-analyzer.cargo-watch.arguments": { |
201 | "type": "string", | 206 | "type": "string", |
202 | "description": "`cargo-watch` arguments. (e.g: `--features=\"shumway,pdf\"` will run as `cargo watch -x \"check --features=\"shumway,pdf\"\"` )", | 207 | "description": "`cargo-watch` arguments. (e.g: `--features=\"shumway,pdf\"` will run as `cargo watch -x \"check --features=\"shumway,pdf\"\"` )", |
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index 3ba9da48b..5393a2bc9 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -22,53 +22,56 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ | |||
22 | export class HintsUpdater { | 22 | export class HintsUpdater { |
23 | private displayHints = true; | 23 | private displayHints = true; |
24 | 24 | ||
25 | public async loadHints( | ||
26 | editor: vscode.TextEditor | undefined | ||
27 | ): Promise<void> { | ||
28 | if ( | ||
29 | this.displayHints && | ||
30 | editor !== undefined && | ||
31 | this.isRustDocument(editor.document) | ||
32 | ) { | ||
33 | await this.updateDecorationsFromServer( | ||
34 | editor.document.uri.toString(), | ||
35 | editor | ||
36 | ); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { | 25 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { |
41 | if (this.displayHints !== displayHints) { | 26 | if (this.displayHints !== displayHints) { |
42 | this.displayHints = displayHints; | 27 | this.displayHints = displayHints; |
43 | 28 | return this.refreshVisibleEditorsHints( | |
44 | if (displayHints) { | 29 | displayHints ? undefined : [] |
45 | return this.updateHints(); | 30 | ); |
46 | } else { | ||
47 | const editor = vscode.window.activeTextEditor; | ||
48 | if (editor != null) { | ||
49 | return editor.setDecorations(typeHintDecorationType, []); | ||
50 | } | ||
51 | } | ||
52 | } | 31 | } |
53 | } | 32 | } |
54 | 33 | ||
55 | public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> { | 34 | public async refreshHintsForVisibleEditors( |
35 | cause?: TextDocumentChangeEvent | ||
36 | ): Promise<void> { | ||
56 | if (!this.displayHints) { | 37 | if (!this.displayHints) { |
57 | return; | 38 | return; |
58 | } | 39 | } |
59 | const editor = vscode.window.activeTextEditor; | 40 | if ( |
60 | if (editor == null) { | 41 | cause !== undefined && |
42 | (cause.contentChanges.length === 0 || | ||
43 | !this.isRustDocument(cause.document)) | ||
44 | ) { | ||
61 | return; | 45 | return; |
62 | } | 46 | } |
63 | const document = cause == null ? editor.document : cause.document; | 47 | return this.refreshVisibleEditorsHints(); |
64 | if (!this.isRustDocument(document)) { | 48 | } |
65 | return; | 49 | |
50 | private async refreshVisibleEditorsHints( | ||
51 | newDecorations?: vscode.DecorationOptions[] | ||
52 | ) { | ||
53 | const promises: Array<Promise<void>> = []; | ||
54 | |||
55 | for (const rustEditor of vscode.window.visibleTextEditors.filter( | ||
56 | editor => this.isRustDocument(editor.document) | ||
57 | )) { | ||
58 | if (newDecorations !== undefined) { | ||
59 | promises.push( | ||
60 | Promise.resolve( | ||
61 | rustEditor.setDecorations( | ||
62 | typeHintDecorationType, | ||
63 | newDecorations | ||
64 | ) | ||
65 | ) | ||
66 | ); | ||
67 | } else { | ||
68 | promises.push(this.updateDecorationsFromServer(rustEditor)); | ||
69 | } | ||
66 | } | 70 | } |
67 | 71 | ||
68 | return await this.updateDecorationsFromServer( | 72 | for (const promise of promises) { |
69 | document.uri.toString(), | 73 | await promise; |
70 | editor | 74 | } |
71 | ); | ||
72 | } | 75 | } |
73 | 76 | ||
74 | private isRustDocument(document: vscode.TextDocument): boolean { | 77 | private isRustDocument(document: vscode.TextDocument): boolean { |
@@ -76,11 +79,10 @@ export class HintsUpdater { | |||
76 | } | 79 | } |
77 | 80 | ||
78 | private async updateDecorationsFromServer( | 81 | private async updateDecorationsFromServer( |
79 | documentUri: string, | ||
80 | editor: TextEditor | 82 | editor: TextEditor |
81 | ): Promise<void> { | 83 | ): Promise<void> { |
82 | const newHints = await this.queryHints(documentUri); | 84 | const newHints = await this.queryHints(editor.document.uri.toString()); |
83 | if (newHints != null) { | 85 | if (newHints !== null) { |
84 | const newDecorations = newHints.map(hint => ({ | 86 | const newDecorations = newHints.map(hint => ({ |
85 | range: hint.range, | 87 | range: hint.range, |
86 | renderOptions: { after: { contentText: `: ${hint.label}` } } | 88 | renderOptions: { after: { contentText: `: ${hint.label}` } } |
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 4d58a1a93..4df6b50ef 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -22,6 +22,7 @@ export class Config { | |||
22 | public showWorkspaceLoadedNotification = true; | 22 | public showWorkspaceLoadedNotification = true; |
23 | public lruCapacity: null | number = null; | 23 | public lruCapacity: null | number = null; |
24 | public displayInlayHints = true; | 24 | public displayInlayHints = true; |
25 | public excludeGlobs = []; | ||
25 | public cargoWatchOptions: CargoWatchOptions = { | 26 | public cargoWatchOptions: CargoWatchOptions = { |
26 | enableOnStartup: 'ask', | 27 | enableOnStartup: 'ask', |
27 | trace: 'off', | 28 | trace: 'off', |
@@ -128,5 +129,8 @@ export class Config { | |||
128 | if (config.has('displayInlayHints')) { | 129 | if (config.has('displayInlayHints')) { |
129 | this.displayInlayHints = config.get('displayInlayHints') as boolean; | 130 | this.displayInlayHints = config.get('displayInlayHints') as boolean; |
130 | } | 131 | } |
132 | if (config.has('excludeGlobs')) { | ||
133 | this.excludeGlobs = config.get('excludeGlobs') || []; | ||
134 | } | ||
131 | } | 135 | } |
132 | } | 136 | } |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index c6efc2e7e..39fe6efd8 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) { | |||
151 | 151 | ||
152 | if (Server.config.displayInlayHints) { | 152 | if (Server.config.displayInlayHints) { |
153 | const hintsUpdater = new HintsUpdater(); | 153 | const hintsUpdater = new HintsUpdater(); |
154 | hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => { | 154 | hintsUpdater.refreshHintsForVisibleEditors().then(() => { |
155 | // vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors() | ||
156 | // so update the hints once when the focus changes to guarantee their presence | ||
157 | let editorChangeDisposable: vscode.Disposable | null = null; | ||
158 | editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor( | ||
159 | _ => { | ||
160 | if (editorChangeDisposable !== null) { | ||
161 | editorChangeDisposable.dispose(); | ||
162 | } | ||
163 | return hintsUpdater.refreshHintsForVisibleEditors(); | ||
164 | } | ||
165 | ); | ||
166 | |||
155 | disposeOnDeactivation( | 167 | disposeOnDeactivation( |
156 | vscode.window.onDidChangeActiveTextEditor(editor => | 168 | vscode.window.onDidChangeVisibleTextEditors(_ => |
157 | hintsUpdater.loadHints(editor) | 169 | hintsUpdater.refreshHintsForVisibleEditors() |
158 | ) | 170 | ) |
159 | ); | 171 | ); |
160 | disposeOnDeactivation( | 172 | disposeOnDeactivation( |
161 | vscode.workspace.onDidChangeTextDocument(e => | 173 | vscode.workspace.onDidChangeTextDocument(e => |
162 | hintsUpdater.updateHints(e) | 174 | hintsUpdater.refreshHintsForVisibleEditors(e) |
163 | ) | 175 | ) |
164 | ); | 176 | ); |
165 | disposeOnDeactivation( | 177 | disposeOnDeactivation( |
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 7029142fd..2b4c25c28 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts | |||
@@ -36,7 +36,8 @@ export class Server { | |||
36 | publishDecorations: true, | 36 | publishDecorations: true, |
37 | showWorkspaceLoaded: | 37 | showWorkspaceLoaded: |
38 | Server.config.showWorkspaceLoadedNotification, | 38 | Server.config.showWorkspaceLoadedNotification, |
39 | lruCapacity: Server.config.lruCapacity | 39 | lruCapacity: Server.config.lruCapacity, |
40 | excludeGlobs: Server.config.excludeGlobs | ||
40 | }, | 41 | }, |
41 | traceOutputChannel | 42 | traceOutputChannel |
42 | }; | 43 | }; |
diff --git a/editors/emacs/ra-emacs-lsp.el b/editors/emacs/ra-emacs-lsp.el index d7656476e..79822c8ce 100644 --- a/editors/emacs/ra-emacs-lsp.el +++ b/editors/emacs/ra-emacs-lsp.el | |||
@@ -14,7 +14,7 @@ | |||
14 | ;; - 'hover' type information & documentation (with lsp-ui) | 14 | ;; - 'hover' type information & documentation (with lsp-ui) |
15 | ;; - implements source changes (for code actions etc.), except for file system changes | 15 | ;; - implements source changes (for code actions etc.), except for file system changes |
16 | ;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key) | 16 | ;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key) |
17 | ;; - implements extendSelection (either bind rust-analyzer-extend-selection to a key, or use expand-region) | 17 | ;; - implements selectionRanges (either bind lsp-extend-selection to a key, or use expand-region) |
18 | ;; - provides rust-analyzer-inlay-hints-mode for inline type hints | 18 | ;; - provides rust-analyzer-inlay-hints-mode for inline type hints |
19 | 19 | ||
20 | ;; What's missing: | 20 | ;; What's missing: |
@@ -79,6 +79,10 @@ | |||
79 | :ignore-messages nil | 79 | :ignore-messages nil |
80 | :server-id 'rust-analyzer)) | 80 | :server-id 'rust-analyzer)) |
81 | 81 | ||
82 | (defun rust-analyzer--initialized? () | ||
83 | (when-let ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))) | ||
84 | (eq 'initialized (lsp--workspace-status workspace)))) | ||
85 | |||
82 | (with-eval-after-load 'company-lsp | 86 | (with-eval-after-load 'company-lsp |
83 | ;; company-lsp provides a snippet handler for rust by default that adds () after function calls, which RA does better | 87 | ;; company-lsp provides a snippet handler for rust by default that adds () after function calls, which RA does better |
84 | (setq company-lsp--snippet-functions (cl-delete "rust" company-lsp--snippet-functions :key #'car :test #'equal))) | 88 | (setq company-lsp--snippet-functions (cl-delete "rust" company-lsp--snippet-functions :key #'car :test #'equal))) |
@@ -99,39 +103,13 @@ | |||
99 | (rust-analyzer--join-lines-params))) | 103 | (rust-analyzer--join-lines-params))) |
100 | (rust-analyzer--apply-source-change))) | 104 | (rust-analyzer--apply-source-change))) |
101 | 105 | ||
102 | ;; extend selection | 106 | ;; selection ranges |
103 | |||
104 | (defun rust-analyzer-extend-selection () | ||
105 | (interactive) | ||
106 | (-let (((&hash "start" "end") (rust-analyzer--extend-selection))) | ||
107 | (rust-analyzer--goto-lsp-loc start) | ||
108 | (set-mark (point)) | ||
109 | (rust-analyzer--goto-lsp-loc end) | ||
110 | (exchange-point-and-mark))) | ||
111 | |||
112 | (defun rust-analyzer--extend-selection-params () | ||
113 | "Extend selection params." | ||
114 | (list :textDocument (lsp--text-document-identifier) | ||
115 | :selections | ||
116 | (vector | ||
117 | (if (use-region-p) | ||
118 | (lsp--region-to-range (region-beginning) (region-end)) | ||
119 | (lsp--region-to-range (point) (point)))))) | ||
120 | |||
121 | (defun rust-analyzer--extend-selection () | ||
122 | (-> | ||
123 | (lsp-send-request | ||
124 | (lsp-make-request | ||
125 | "rust-analyzer/extendSelection" | ||
126 | (rust-analyzer--extend-selection-params))) | ||
127 | (ht-get "selections") | ||
128 | (seq-first))) | ||
129 | 107 | ||
130 | (defun rust-analyzer--add-er-expansion () | 108 | (defun rust-analyzer--add-er-expansion () |
131 | (make-variable-buffer-local 'er/try-expand-list) | 109 | (make-variable-buffer-local 'er/try-expand-list) |
132 | (setq er/try-expand-list (append | 110 | (setq er/try-expand-list (append |
133 | er/try-expand-list | 111 | er/try-expand-list |
134 | '(rust-analyzer-extend-selection)))) | 112 | '(lsp-extend-selection)))) |
135 | 113 | ||
136 | (with-eval-after-load 'expand-region | 114 | (with-eval-after-load 'expand-region |
137 | ;; add the expansion for all existing rust-mode buffers. If expand-region is | 115 | ;; add the expansion for all existing rust-mode buffers. If expand-region is |
@@ -229,21 +207,22 @@ | |||
229 | (pop-to-buffer buf)))))) | 207 | (pop-to-buffer buf)))))) |
230 | 208 | ||
231 | ;; inlay hints | 209 | ;; inlay hints |
232 | (defun rust-analyzer--update-inlay-hints () | 210 | (defun rust-analyzer--update-inlay-hints (buffer) |
233 | (lsp-send-request-async | 211 | (if (and (rust-analyzer--initialized?) (eq buffer (current-buffer))) |
234 | (lsp-make-request "rust-analyzer/inlayHints" | 212 | (lsp-send-request-async |
235 | (list :textDocument (lsp--text-document-identifier))) | 213 | (lsp-make-request "rust-analyzer/inlayHints" |
236 | (lambda (res) | 214 | (list :textDocument (lsp--text-document-identifier))) |
237 | (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) | 215 | (lambda (res) |
238 | (dolist (hint res) | 216 | (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) |
239 | (-let* (((&hash "range" "label" "kind") hint) | 217 | (dolist (hint res) |
240 | ((beg . end) (lsp--range-to-region range)) | 218 | (-let* (((&hash "range" "label" "kind") hint) |
241 | (overlay (make-overlay beg end))) | 219 | ((beg . end) (lsp--range-to-region range)) |
242 | (overlay-put overlay 'rust-analyzer--inlay-hint t) | 220 | (overlay (make-overlay beg end))) |
243 | (overlay-put overlay 'evaporate t) | 221 | (overlay-put overlay 'rust-analyzer--inlay-hint t) |
244 | (overlay-put overlay 'after-string (propertize (concat ": " label) | 222 | (overlay-put overlay 'evaporate t) |
245 | 'font-lock-face 'font-lock-comment-face))))) | 223 | (overlay-put overlay 'after-string (propertize (concat ": " label) |
246 | 'tick) | 224 | 'font-lock-face 'font-lock-comment-face))))) |
225 | 'tick)) | ||
247 | nil) | 226 | nil) |
248 | 227 | ||
249 | (defvar-local rust-analyzer--inlay-hints-timer nil) | 228 | (defvar-local rust-analyzer--inlay-hints-timer nil) |
@@ -252,17 +231,19 @@ | |||
252 | (when rust-analyzer--inlay-hints-timer | 231 | (when rust-analyzer--inlay-hints-timer |
253 | (cancel-timer rust-analyzer--inlay-hints-timer)) | 232 | (cancel-timer rust-analyzer--inlay-hints-timer)) |
254 | (setq rust-analyzer--inlay-hints-timer | 233 | (setq rust-analyzer--inlay-hints-timer |
255 | (run-with-idle-timer 0.1 nil #'rust-analyzer--update-inlay-hints))) | 234 | (run-with-idle-timer 0.1 nil #'rust-analyzer--update-inlay-hints (current-buffer)))) |
256 | 235 | ||
257 | (define-minor-mode rust-analyzer-inlay-hints-mode | 236 | (define-minor-mode rust-analyzer-inlay-hints-mode |
258 | "Mode for showing inlay hints." | 237 | "Mode for showing inlay hints." |
259 | nil nil nil | 238 | nil nil nil |
260 | (cond | 239 | (cond |
261 | (rust-analyzer-inlay-hints-mode | 240 | (rust-analyzer-inlay-hints-mode |
262 | (rust-analyzer--update-inlay-hints) | 241 | (rust-analyzer--update-inlay-hints (current-buffer)) |
242 | (add-hook 'lsp-after-initialize-hook #'rust-analyzer--inlay-hints-change-handler nil t) | ||
263 | (add-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler nil t)) | 243 | (add-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler nil t)) |
264 | (t | 244 | (t |
265 | (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) | 245 | (remove-overlays (point-min) (point-max) 'rust-analyzer--inlay-hint t) |
246 | (remove-hook 'lsp-after-initialize-hook #'rust-analyzer--inlay-hints-change-handler t) | ||
266 | (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t)))) | 247 | (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t)))) |
267 | 248 | ||
268 | 249 | ||