Merge #1652
1652: Improve type hints behavior r=matklad a=SomeoneToIgnore This PR fixed the following type hints issues: * Restructures the `InlayKind` enum contents based on the discussion here: https://github.com/rust-analyzer/rust-analyzer/pull/1606#issuecomment-515968055 * Races described in #1639 * Caches the latest decorations received for each file to show them the next time the file is opened (instead of a new server request) Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
@@ -22,53 +22,56 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
|
||||
export class HintsUpdater {
|
||||
private displayHints = true;
|
||||
|
||||
public async loadHints(
|
||||
editor: vscode.TextEditor | undefined
|
||||
): Promise<void> {
|
||||
if (
|
||||
this.displayHints &&
|
||||
editor !== undefined &&
|
||||
this.isRustDocument(editor.document)
|
||||
) {
|
||||
await this.updateDecorationsFromServer(
|
||||
editor.document.uri.toString(),
|
||||
editor
|
||||
public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
|
||||
if (this.displayHints !== displayHints) {
|
||||
this.displayHints = displayHints;
|
||||
return this.refreshVisibleEditorsHints(
|
||||
displayHints ? undefined : []
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
|
||||
if (this.displayHints !== displayHints) {
|
||||
this.displayHints = displayHints;
|
||||
|
||||
if (displayHints) {
|
||||
return this.updateHints();
|
||||
} else {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor != null) {
|
||||
return editor.setDecorations(typeHintDecorationType, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> {
|
||||
public async refreshHintsForVisibleEditors(
|
||||
cause?: TextDocumentChangeEvent
|
||||
): Promise<void> {
|
||||
if (!this.displayHints) {
|
||||
return;
|
||||
}
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor == null) {
|
||||
if (
|
||||
cause !== undefined &&
|
||||
(cause.contentChanges.length === 0 ||
|
||||
!this.isRustDocument(cause.document))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const document = cause == null ? editor.document : cause.document;
|
||||
if (!this.isRustDocument(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 {
|
||||
promises.push(this.updateDecorationsFromServer(rustEditor));
|
||||
}
|
||||
}
|
||||
|
||||
return await this.updateDecorationsFromServer(
|
||||
document.uri.toString(),
|
||||
editor
|
||||
);
|
||||
for (const promise of promises) {
|
||||
await promise;
|
||||
}
|
||||
}
|
||||
|
||||
private isRustDocument(document: vscode.TextDocument): boolean {
|
||||
@@ -76,11 +79,10 @@ export class HintsUpdater {
|
||||
}
|
||||
|
||||
private async updateDecorationsFromServer(
|
||||
documentUri: string,
|
||||
editor: TextEditor
|
||||
): Promise<void> {
|
||||
const newHints = await this.queryHints(documentUri);
|
||||
if (newHints != null) {
|
||||
const newHints = await this.queryHints(editor.document.uri.toString());
|
||||
if (newHints !== null) {
|
||||
const newDecorations = newHints.map(hint => ({
|
||||
range: hint.range,
|
||||
renderOptions: { after: { contentText: `: ${hint.label}` } }
|
||||
|
||||
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
if (Server.config.displayInlayHints) {
|
||||
const hintsUpdater = new HintsUpdater();
|
||||
hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => {
|
||||
hintsUpdater.refreshHintsForVisibleEditors().then(() => {
|
||||
// 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();
|
||||
}
|
||||
);
|
||||
|
||||
disposeOnDeactivation(
|
||||
vscode.window.onDidChangeActiveTextEditor(editor =>
|
||||
hintsUpdater.loadHints(editor)
|
||||
vscode.window.onDidChangeVisibleTextEditors(_ =>
|
||||
hintsUpdater.refreshHintsForVisibleEditors()
|
||||
)
|
||||
);
|
||||
disposeOnDeactivation(
|
||||
vscode.workspace.onDidChangeTextDocument(e =>
|
||||
hintsUpdater.updateHints(e)
|
||||
hintsUpdater.refreshHintsForVisibleEditors(e)
|
||||
)
|
||||
);
|
||||
disposeOnDeactivation(
|
||||
|
||||
Reference in New Issue
Block a user