aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/inlay_hints.ts
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-03-24 23:28:57 +0000
committerGitHub <[email protected]>2020-03-24 23:28:57 +0000
commit6ad1a0711631d8017791a6dfe85bbe205d6c7414 (patch)
treece2d6448ff8770c8fe73086eefb85dab38d298d8 /editors/code/src/inlay_hints.ts
parentfae627174aecae0b4f4d2c087a856eda1a97a1ac (diff)
parent7b35da04bf56a5461321a6dca515dcd29f44b57f (diff)
Merge #3710
3710: Inlay hints for method chaining pattern r=matklad a=M-J-Hooper This PR adds inlay hints on method call chains: ![image](https://user-images.githubusercontent.com/13765376/77472008-8dc2a880-6e13-11ea-9c18-2c2e2b809799.png) It is not only explicit `MethodCall`s where this can be helpful. The heuristic used here is that whenever any expression is followed by a new line and then a dot, it resembles a call chain and type information can be #useful. Changes: - A new `InlayKind` for chaining. - New option for disabling this type of hints. - Tree traversal rules for identifying the chaining hints. - VSCode decorators in the extension layer (and associated types). Notes: - IntelliJ has additional rules and configuration on this topic. Eg. minimum length of chain to start displaying hints and only displaying distinct types in the chain. - I am checking for chaining on every `ast::Expr` in the tree; Are there performance concerns there? This is my first contribution (to RA and to Rust in general) so would appreciate any feedback. The only issue I can find the references this feature is #2741. Co-authored-by: Matt Hooper <[email protected]>
Diffstat (limited to 'editors/code/src/inlay_hints.ts')
-rw-r--r--editors/code/src/inlay_hints.ts32
1 files changed, 29 insertions, 3 deletions
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
index 17d0dfa33..542d1f367 100644
--- a/editors/code/src/inlay_hints.ts
+++ b/editors/code/src/inlay_hints.ts
@@ -10,7 +10,11 @@ export function activateInlayHints(ctx: Ctx) {
10 const maybeUpdater = { 10 const maybeUpdater = {
11 updater: null as null | HintsUpdater, 11 updater: null as null | HintsUpdater,
12 onConfigChange() { 12 onConfigChange() {
13 if (!ctx.config.inlayHints.typeHints && !ctx.config.inlayHints.parameterHints) { 13 if (
14 !ctx.config.inlayHints.typeHints &&
15 !ctx.config.inlayHints.parameterHints &&
16 !ctx.config.inlayHints.chainingHints
17 ) {
14 return this.dispose(); 18 return this.dispose();
15 } 19 }
16 if (!this.updater) this.updater = new HintsUpdater(ctx); 20 if (!this.updater) this.updater = new HintsUpdater(ctx);
@@ -63,6 +67,22 @@ const paramHints = {
63 } 67 }
64}; 68};
65 69
70const chainingHints = {
71 decorationType: vscode.window.createTextEditorDecorationType({
72 after: {
73 color: new vscode.ThemeColor('rust_analyzer.inlayHint'),
74 fontStyle: "normal",
75 }
76 }),
77
78 toDecoration(hint: ra.InlayHint.ChainingHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions {
79 return {
80 range: conv.asRange(hint.range),
81 renderOptions: { after: { contentText: ` ${hint.label}` } }
82 };
83 }
84};
85
66class HintsUpdater implements Disposable { 86class HintsUpdater implements Disposable {
67 private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile 87 private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile
68 private readonly disposables: Disposable[] = []; 88 private readonly disposables: Disposable[] = [];
@@ -95,7 +115,7 @@ class HintsUpdater implements Disposable {
95 115
96 dispose() { 116 dispose() {
97 this.sourceFiles.forEach(file => file.inlaysRequest?.cancel()); 117 this.sourceFiles.forEach(file => file.inlaysRequest?.cancel());
98 this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [] })); 118 this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [], chaining: [] }));
99 this.disposables.forEach(d => d.dispose()); 119 this.disposables.forEach(d => d.dispose());
100 } 120 }
101 121
@@ -154,10 +174,11 @@ class HintsUpdater implements Disposable {
154 private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) { 174 private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) {
155 editor.setDecorations(typeHints.decorationType, decorations.type); 175 editor.setDecorations(typeHints.decorationType, decorations.type);
156 editor.setDecorations(paramHints.decorationType, decorations.param); 176 editor.setDecorations(paramHints.decorationType, decorations.param);
177 editor.setDecorations(chainingHints.decorationType, decorations.chaining);
157 } 178 }
158 179
159 private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations { 180 private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations {
160 const decorations: InlaysDecorations = { type: [], param: [] }; 181 const decorations: InlaysDecorations = { type: [], param: [], chaining: [] };
161 const conv = this.ctx.client.protocol2CodeConverter; 182 const conv = this.ctx.client.protocol2CodeConverter;
162 183
163 for (const hint of hints) { 184 for (const hint of hints) {
@@ -170,6 +191,10 @@ class HintsUpdater implements Disposable {
170 decorations.param.push(paramHints.toDecoration(hint, conv)); 191 decorations.param.push(paramHints.toDecoration(hint, conv));
171 continue; 192 continue;
172 } 193 }
194 case ra.InlayHint.Kind.ChainingHint: {
195 decorations.chaining.push(chainingHints.toDecoration(hint, conv));
196 continue;
197 }
173 } 198 }
174 } 199 }
175 return decorations; 200 return decorations;
@@ -196,6 +221,7 @@ class HintsUpdater implements Disposable {
196interface InlaysDecorations { 221interface InlaysDecorations {
197 type: vscode.DecorationOptions[]; 222 type: vscode.DecorationOptions[];
198 param: vscode.DecorationOptions[]; 223 param: vscode.DecorationOptions[];
224 chaining: vscode.DecorationOptions[];
199} 225}
200 226
201interface RustSourceFile { 227interface RustSourceFile {