aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/code/package.json5
-rw-r--r--editors/code/src/commands/inlay_hints.ts76
-rw-r--r--editors/code/src/config.ts4
-rw-r--r--editors/code/src/extension.ts20
-rw-r--r--editors/code/src/server.ts3
-rw-r--r--editors/emacs/ra-emacs-lsp.el73
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({
22export class HintsUpdater { 22export 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