Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/hover/browser/contentHoverComputer.ts
4779 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { coalesce } from '../../../../base/common/arrays.js';
7
import { CancellationToken } from '../../../../base/common/cancellation.js';
8
import { IActiveCodeEditor, ICodeEditor } from '../../../browser/editorBrowser.js';
9
import { IModelDecoration } from '../../../common/model.js';
10
import { HoverStartSource, IHoverComputer } from './hoverOperation.js';
11
import { HoverAnchor, HoverAnchorType, IEditorHoverParticipant, IHoverPart } from './hoverTypes.js';
12
import { AsyncIterableProducer } from '../../../../base/common/async.js';
13
14
export interface ContentHoverComputerOptions {
15
shouldFocus: boolean;
16
anchor: HoverAnchor;
17
source: HoverStartSource;
18
insistOnKeepingHoverVisible: boolean;
19
}
20
21
export class ContentHoverComputer implements IHoverComputer<ContentHoverComputerOptions, IHoverPart> {
22
23
constructor(
24
private readonly _editor: ICodeEditor,
25
private readonly _participants: readonly IEditorHoverParticipant[]
26
) {
27
}
28
29
private static _getLineDecorations(editor: IActiveCodeEditor, anchor: HoverAnchor): IModelDecoration[] {
30
if (anchor.type !== HoverAnchorType.Range && !anchor.supportsMarkerHover) {
31
return [];
32
}
33
34
const model = editor.getModel();
35
const lineNumber = anchor.range.startLineNumber;
36
37
if (lineNumber > model.getLineCount()) {
38
// invalid line
39
return [];
40
}
41
42
const maxColumn = model.getLineMaxColumn(lineNumber);
43
44
return editor.getLineDecorations(lineNumber).filter((d) => {
45
if (d.options.isWholeLine) {
46
return true;
47
}
48
49
const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
50
const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
51
52
if (d.options.showIfCollapsed) {
53
// Relax check around `showIfCollapsed` decorations to also include +/- 1 character
54
if (startColumn > anchor.range.startColumn + 1 || anchor.range.endColumn - 1 > endColumn) {
55
return false;
56
}
57
} else {
58
if (startColumn > anchor.range.startColumn || anchor.range.endColumn > endColumn) {
59
return false;
60
}
61
}
62
63
return true;
64
});
65
}
66
67
public computeAsync(options: ContentHoverComputerOptions, token: CancellationToken): AsyncIterableProducer<IHoverPart> {
68
const anchor = options.anchor;
69
70
if (!this._editor.hasModel() || !anchor) {
71
return AsyncIterableProducer.EMPTY;
72
}
73
74
const lineDecorations = ContentHoverComputer._getLineDecorations(this._editor, anchor);
75
76
return AsyncIterableProducer.merge(
77
this._participants.map((participant) => {
78
if (!participant.computeAsync) {
79
return AsyncIterableProducer.EMPTY;
80
}
81
return participant.computeAsync(anchor, lineDecorations, options.source, token);
82
})
83
);
84
}
85
86
public computeSync(options: ContentHoverComputerOptions): IHoverPart[] {
87
if (!this._editor.hasModel()) {
88
return [];
89
}
90
91
const anchor = options.anchor;
92
const lineDecorations = ContentHoverComputer._getLineDecorations(this._editor, anchor);
93
94
let result: IHoverPart[] = [];
95
for (const participant of this._participants) {
96
result = result.concat(participant.computeSync(anchor, lineDecorations, options.source));
97
}
98
99
return coalesce(result);
100
}
101
}
102
103
104