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:
bors[bot]
2019-08-06 16:50:49 +00:00
5 changed files with 100 additions and 114 deletions

View File

@@ -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}` } }

View File

@@ -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(