mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Refactor inlay hints
This commit is contained in:
parent
efbbc903e6
commit
ac8a142ddd
1 changed files with 70 additions and 106 deletions
|
@ -1,39 +1,29 @@
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as lc from 'vscode-languageclient';
|
import * as lc from 'vscode-languageclient';
|
||||||
import { Server } from './server';
|
|
||||||
import { Ctx } from './ctx';
|
import { Ctx } from './ctx';
|
||||||
|
|
||||||
export function activateInlayHints(ctx: Ctx) {
|
export function activateInlayHints(ctx: Ctx) {
|
||||||
const hintsUpdater = new HintsUpdater();
|
const hintsUpdater = new HintsUpdater(ctx);
|
||||||
hintsUpdater.refreshHintsForVisibleEditors().then(() => {
|
console.log('activateInlayHints');
|
||||||
// vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors()
|
|
||||||
// so update the hints once when the focus changes to guarantee their presence
|
|
||||||
let editorChangeDisposable: vscode.Disposable | null = null;
|
|
||||||
editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor(
|
|
||||||
_ => {
|
|
||||||
if (editorChangeDisposable !== null) {
|
|
||||||
editorChangeDisposable.dispose();
|
|
||||||
}
|
|
||||||
return hintsUpdater.refreshHintsForVisibleEditors();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.pushCleanup(
|
vscode.window.onDidChangeVisibleTextEditors(async _ => {
|
||||||
vscode.window.onDidChangeVisibleTextEditors(_ =>
|
await hintsUpdater.refresh();
|
||||||
hintsUpdater.refreshHintsForVisibleEditors(),
|
}, ctx.subscriptions);
|
||||||
),
|
|
||||||
);
|
vscode.workspace.onDidChangeTextDocument(async e => {
|
||||||
ctx.pushCleanup(
|
if (e.contentChanges.length === 0) return;
|
||||||
vscode.workspace.onDidChangeTextDocument(e =>
|
if (e.document.languageId !== 'rust') return;
|
||||||
hintsUpdater.refreshHintsForVisibleEditors(e),
|
await hintsUpdater.refresh();
|
||||||
),
|
}, ctx.subscriptions);
|
||||||
);
|
|
||||||
ctx.pushCleanup(
|
vscode.workspace.onDidChangeConfiguration(_ => {
|
||||||
vscode.workspace.onDidChangeConfiguration(_ =>
|
hintsUpdater.setEnabled(ctx.config.displayInlayHints);
|
||||||
hintsUpdater.toggleHintsDisplay(ctx.config.displayInlayHints),
|
}, ctx.subscriptions);
|
||||||
),
|
|
||||||
);
|
// XXX: don't await here;
|
||||||
});
|
// Who knows what happens if an exception is thrown here...
|
||||||
|
hintsUpdater.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InlayHintsParams {
|
interface InlayHintsParams {
|
||||||
|
@ -53,69 +43,34 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
|
||||||
});
|
});
|
||||||
|
|
||||||
class HintsUpdater {
|
class HintsUpdater {
|
||||||
private displayHints = true;
|
private ctx: Ctx;
|
||||||
|
private enabled = true;
|
||||||
|
|
||||||
public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
|
constructor(ctx: Ctx) {
|
||||||
if (this.displayHints !== displayHints) {
|
this.ctx = ctx;
|
||||||
this.displayHints = displayHints;
|
|
||||||
return this.refreshVisibleEditorsHints(
|
|
||||||
displayHints ? undefined : [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refreshHintsForVisibleEditors(
|
async setEnabled(enabled: boolean) {
|
||||||
cause?: vscode.TextDocumentChangeEvent,
|
if (this.enabled == enabled) return;
|
||||||
): Promise<void> {
|
this.enabled = enabled;
|
||||||
if (!this.displayHints) return;
|
|
||||||
|
|
||||||
if (
|
if (this.enabled) {
|
||||||
cause !== undefined &&
|
await this.refresh();
|
||||||
(cause.contentChanges.length === 0 ||
|
|
||||||
!this.isRustDocument(cause.document))
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return this.refreshVisibleEditorsHints();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async refreshVisibleEditorsHints(
|
|
||||||
newDecorations?: vscode.DecorationOptions[],
|
|
||||||
) {
|
|
||||||
const promises: Array<Promise<void>> = [];
|
|
||||||
|
|
||||||
for (const rustEditor of vscode.window.visibleTextEditors.filter(
|
|
||||||
editor => this.isRustDocument(editor.document),
|
|
||||||
)) {
|
|
||||||
if (newDecorations !== undefined) {
|
|
||||||
promises.push(
|
|
||||||
Promise.resolve(
|
|
||||||
rustEditor.setDecorations(
|
|
||||||
typeHintDecorationType,
|
|
||||||
newDecorations,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
promises.push(this.updateDecorationsFromServer(rustEditor));
|
this.allEditors.forEach(it => this.setDecorations(it, []));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const promise of promises) {
|
async refresh() {
|
||||||
await promise;
|
if (!this.enabled) return;
|
||||||
}
|
const promises = this.allEditors.map(it => this.refreshEditor(it));
|
||||||
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isRustDocument(document: vscode.TextDocument): boolean {
|
private async refreshEditor(editor: vscode.TextEditor): Promise<void> {
|
||||||
return document && document.languageId === 'rust';
|
|
||||||
}
|
|
||||||
|
|
||||||
private async updateDecorationsFromServer(
|
|
||||||
editor: vscode.TextEditor,
|
|
||||||
): Promise<void> {
|
|
||||||
const newHints = await this.queryHints(editor.document.uri.toString());
|
const newHints = await this.queryHints(editor.document.uri.toString());
|
||||||
if (newHints !== null) {
|
|
||||||
const newDecorations = newHints.map(hint => ({
|
const newDecorations = (newHints ? newHints : []).map(hint => ({
|
||||||
range: hint.range,
|
range: hint.range,
|
||||||
renderOptions: {
|
renderOptions: {
|
||||||
after: {
|
after: {
|
||||||
|
@ -123,25 +78,34 @@ class HintsUpdater {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
return editor.setDecorations(
|
this.setDecorations(editor, newDecorations);
|
||||||
typeHintDecorationType,
|
}
|
||||||
newDecorations,
|
|
||||||
|
private get allEditors(): vscode.TextEditor[] {
|
||||||
|
return vscode.window.visibleTextEditors.filter(
|
||||||
|
editor => editor.document.languageId === 'rust',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setDecorations(
|
||||||
|
editor: vscode.TextEditor,
|
||||||
|
decorations: vscode.DecorationOptions[],
|
||||||
|
) {
|
||||||
|
editor.setDecorations(
|
||||||
|
typeHintDecorationType,
|
||||||
|
this.enabled ? decorations : [],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
|
private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
|
||||||
const request: InlayHintsParams = {
|
const request: InlayHintsParams = {
|
||||||
textDocument: { uri: documentUri },
|
textDocument: { uri: documentUri },
|
||||||
};
|
};
|
||||||
const client = Server.client;
|
await this.ctx.client.onReady();
|
||||||
return client
|
|
||||||
.onReady()
|
return this.ctx.client.sendRequest<InlayHint[] | null>(
|
||||||
.then(() =>
|
|
||||||
client.sendRequest<InlayHint[] | null>(
|
|
||||||
'rust-analyzer/inlayHints',
|
'rust-analyzer/inlayHints',
|
||||||
request,
|
request,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue