Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/vs/editor/common/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,9 @@ export interface HoverContext<THover = Hover> {

export interface HoverVerbosityRequest<THover = Hover> {
/**
* Whether to increase or decrease the hover's verbosity
* The delta by which to increase/decrease the hover verbosity level
*/
action: HoverVerbosityAction;
verbosityDelta: number;
/**
* The previous hover for the same position
*/
Expand Down
50 changes: 33 additions & 17 deletions src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as dom from 'vs/base/browser/dom';
import { asArray, compareBy, numberComparator } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IMarkdownString, isEmptyMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { MarkdownRenderer } from 'vs/editor/browser/widget/markdownRenderer/browser/markdownRenderer';
Expand Down Expand Up @@ -212,6 +212,7 @@ class MarkdownRenderedHoverParts extends Disposable {

private _renderedHoverParts: RenderedHoverPart[];
private _hoverFocusInfo: FocusedHoverInfo = { hoverPartIndex: -1, focusRemains: false };
private _ongoingHoverOperations: Map<HoverProvider, { verbosityDelta: number; tokenSource: CancellationTokenSource }> = new Map();
Comment thread
aiday-mar marked this conversation as resolved.

constructor(
hoverParts: MarkdownHover[], // we own!
Expand All @@ -231,6 +232,9 @@ class MarkdownRenderedHoverParts extends Disposable {
renderedHoverPart.disposables.dispose();
});
}));
this._register(toDisposable(() => {
this._ongoingHoverOperations.forEach(operation => { operation.tokenSource.dispose(true); });
}));
}

private _renderHoverParts(
Expand Down Expand Up @@ -351,33 +355,45 @@ class MarkdownRenderedHoverParts extends Disposable {
if (!hoverRenderedPart || !hoverRenderedPart.hoverSource?.supportsVerbosityAction(action)) {
return;
}
const hoverPosition = hoverRenderedPart.hoverSource.hoverPosition;
const hoverProvider = hoverRenderedPart.hoverSource.hoverProvider;
const hover = hoverRenderedPart.hoverSource.hover;
const hoverContext: HoverContext = { verbosityRequest: { action, previousHover: hover } };

let newHover: Hover | null | undefined;
try {
newHover = await Promise.resolve(hoverProvider.provideHover(model, hoverPosition, CancellationToken.None, hoverContext));
} catch (e) {
onUnexpectedExternalError(e);
}
const hoverSource = hoverRenderedPart.hoverSource;
const newHover = await this._fetchHover(hoverSource, model, action);
if (!newHover) {
return;
}

const hoverSource = new HoverSource(newHover, hoverProvider, hoverPosition);
const renderedHoverPart = this._renderHoverPart(
const newHoverSource = new HoverSource(newHover, hoverSource.hoverProvider, hoverSource.hoverPosition);
const newHoverRenderedPart = this._renderHoverPart(
hoverFocusedPartIndex,
newHover.contents,
hoverSource,
newHoverSource,
this._onFinishedRendering
);
this._replaceRenderedHoverPartAtIndex(hoverFocusedPartIndex, renderedHoverPart);
this._replaceRenderedHoverPartAtIndex(hoverFocusedPartIndex, newHoverRenderedPart);
this._focusOnHoverPartWithIndex(hoverFocusedPartIndex);
this._onFinishedRendering();
}

private async _fetchHover(hoverSource: HoverSource, model: ITextModel, action: HoverVerbosityAction): Promise<Hover | null | undefined> {
let verbosityDelta = action === HoverVerbosityAction.Increase ? 1 : -1;
const provider = hoverSource.hoverProvider;
const ongoingHoverOperation = this._ongoingHoverOperations.get(provider);
if (ongoingHoverOperation) {
ongoingHoverOperation.tokenSource.cancel();
verbosityDelta += ongoingHoverOperation.verbosityDelta;
}
const tokenSource = new CancellationTokenSource();
this._ongoingHoverOperations.set(provider, { verbosityDelta, tokenSource });
const context: HoverContext = { verbosityRequest: { verbosityDelta, previousHover: hoverSource.hover } };
let hover: Hover | null | undefined;
try {
hover = await Promise.resolve(provider.provideHover(model, hoverSource.hoverPosition, tokenSource.token, context));
} catch (e) {
onUnexpectedExternalError(e);
}
tokenSource.dispose();
this._ongoingHoverOperations.delete(provider);
return hover;
}

private _replaceRenderedHoverPartAtIndex(index: number, renderedHoverPart: RenderedHoverPart): void {
if (index >= this._renderHoverParts.length || index < 0) {
return;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6885,9 +6885,9 @@ declare namespace monaco.languages {

export interface HoverVerbosityRequest<THover = Hover> {
/**
* Whether to increase or decrease the hover's verbosity
* The delta by which to increase/decrease the hover verbosity level
*/
action: HoverVerbosityAction;
verbosityDelta: number;
/**
* The previous hover for the same position
*/
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
provideHover: async (model: ITextModel, position: EditorPosition, token: CancellationToken, context?: languages.HoverContext<HoverWithId>): Promise<HoverWithId | undefined> => {
const serializedContext: languages.HoverContext<{ id: number }> = {
verbosityRequest: context?.verbosityRequest ? {
action: context.verbosityRequest.action,
verbosityDelta: context.verbosityRequest.verbosityDelta,
previousHover: { id: context.verbosityRequest.previousHover.id }
} : undefined,
};
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class HoverAdapter {
if (!previousHover) {
throw new Error(`Hover with id ${previousHoverId} not found`);
}
const hoverContext: vscode.HoverContext = { action: context.verbosityRequest.action, previousHover };
const hoverContext: vscode.HoverContext = { verbosityDelta: context.verbosityRequest.verbosityDelta, previousHover };
value = await this._provider.provideHover(doc, pos, token, hoverContext);
} else {
value = await this._provider.provideHover(doc, pos, token);
Expand Down
4 changes: 2 additions & 2 deletions src/vscode-dts/vscode.proposed.editorHoverVerbosityLevel.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ declare module 'vscode' {
export interface HoverContext {

/**
* Whether to increase or decrease the hover's verbosity
* The delta by which to increase/decrease the hover verbosity level
*/
readonly action?: HoverVerbosityAction;
readonly verbosityDelta?: number;

/**
* The previous hover sent for the same position
Expand Down