Path: blob/main/src/vs/editor/contrib/hover/browser/contentHoverComputer.ts
4779 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { coalesce } from '../../../../base/common/arrays.js';6import { CancellationToken } from '../../../../base/common/cancellation.js';7import { IActiveCodeEditor, ICodeEditor } from '../../../browser/editorBrowser.js';8import { IModelDecoration } from '../../../common/model.js';9import { HoverStartSource, IHoverComputer } from './hoverOperation.js';10import { HoverAnchor, HoverAnchorType, IEditorHoverParticipant, IHoverPart } from './hoverTypes.js';11import { AsyncIterableProducer } from '../../../../base/common/async.js';1213export interface ContentHoverComputerOptions {14shouldFocus: boolean;15anchor: HoverAnchor;16source: HoverStartSource;17insistOnKeepingHoverVisible: boolean;18}1920export class ContentHoverComputer implements IHoverComputer<ContentHoverComputerOptions, IHoverPart> {2122constructor(23private readonly _editor: ICodeEditor,24private readonly _participants: readonly IEditorHoverParticipant[]25) {26}2728private static _getLineDecorations(editor: IActiveCodeEditor, anchor: HoverAnchor): IModelDecoration[] {29if (anchor.type !== HoverAnchorType.Range && !anchor.supportsMarkerHover) {30return [];31}3233const model = editor.getModel();34const lineNumber = anchor.range.startLineNumber;3536if (lineNumber > model.getLineCount()) {37// invalid line38return [];39}4041const maxColumn = model.getLineMaxColumn(lineNumber);4243return editor.getLineDecorations(lineNumber).filter((d) => {44if (d.options.isWholeLine) {45return true;46}4748const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;49const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;5051if (d.options.showIfCollapsed) {52// Relax check around `showIfCollapsed` decorations to also include +/- 1 character53if (startColumn > anchor.range.startColumn + 1 || anchor.range.endColumn - 1 > endColumn) {54return false;55}56} else {57if (startColumn > anchor.range.startColumn || anchor.range.endColumn > endColumn) {58return false;59}60}6162return true;63});64}6566public computeAsync(options: ContentHoverComputerOptions, token: CancellationToken): AsyncIterableProducer<IHoverPart> {67const anchor = options.anchor;6869if (!this._editor.hasModel() || !anchor) {70return AsyncIterableProducer.EMPTY;71}7273const lineDecorations = ContentHoverComputer._getLineDecorations(this._editor, anchor);7475return AsyncIterableProducer.merge(76this._participants.map((participant) => {77if (!participant.computeAsync) {78return AsyncIterableProducer.EMPTY;79}80return participant.computeAsync(anchor, lineDecorations, options.source, token);81})82);83}8485public computeSync(options: ContentHoverComputerOptions): IHoverPart[] {86if (!this._editor.hasModel()) {87return [];88}8990const anchor = options.anchor;91const lineDecorations = ContentHoverComputer._getLineDecorations(this._editor, anchor);9293let result: IHoverPart[] = [];94for (const participant of this._participants) {95result = result.concat(participant.computeSync(anchor, lineDecorations, options.source));96}9798return coalesce(result);99}100}101102103104