| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- import * as dom from '../../../../base/browser/dom.js';
- import { isNonEmptyArray } from '../../../../base/common/arrays.js';
- import { createCancelablePromise, disposableTimeout } from '../../../../base/common/async.js';
- import { onUnexpectedError } from '../../../../base/common/errors.js';
- import { Disposable, DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js';
- import { basename } from '../../../../base/common/resources.js';
- import { Range } from '../../../common/core/range.js';
- import { IMarkerDecorationsService } from '../../../common/services/markerDecorations.js';
- import { getCodeActions } from '../../codeAction/browser/codeAction.js';
- import { QuickFixAction, QuickFixController } from '../../codeAction/browser/codeActionCommands.js';
- import { CodeActionKind, CodeActionTriggerSource } from '../../codeAction/browser/types.js';
- import { MarkerController, NextMarkerAction } from '../../gotoError/browser/gotoError.js';
- import * as nls from '../../../../nls.js';
- import { IMarkerData, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
- import { IOpenerService } from '../../../../platform/opener/common/opener.js';
- import { Progress } from '../../../../platform/progress/common/progress.js';
- import { textLinkActiveForeground, textLinkForeground } from '../../../../platform/theme/common/colorRegistry.js';
- import { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';
- import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
- const $ = dom.$;
- export class MarkerHover {
- constructor(owner, range, marker) {
- this.owner = owner;
- this.range = range;
- this.marker = marker;
- }
- isValidForHoverAnchor(anchor) {
- return (anchor.type === 1 /* HoverAnchorType.Range */
- && this.range.startColumn <= anchor.range.startColumn
- && this.range.endColumn >= anchor.range.endColumn);
- }
- }
- const markerCodeActionTrigger = {
- type: 1 /* CodeActionTriggerType.Invoke */,
- filter: { include: CodeActionKind.QuickFix },
- triggerAction: CodeActionTriggerSource.QuickFixHover
- };
- let MarkerHoverParticipant = class MarkerHoverParticipant {
- constructor(_editor, _markerDecorationsService, _openerService, _languageFeaturesService) {
- this._editor = _editor;
- this._markerDecorationsService = _markerDecorationsService;
- this._openerService = _openerService;
- this._languageFeaturesService = _languageFeaturesService;
- this.hoverOrdinal = 5;
- this.recentMarkerCodeActionsInfo = undefined;
- }
- computeSync(anchor, lineDecorations) {
- if (!this._editor.hasModel() || anchor.type !== 1 /* HoverAnchorType.Range */) {
- return [];
- }
- const model = this._editor.getModel();
- const lineNumber = anchor.range.startLineNumber;
- const maxColumn = model.getLineMaxColumn(lineNumber);
- const result = [];
- for (const d of lineDecorations) {
- const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
- const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
- const marker = this._markerDecorationsService.getMarker(model.uri, d);
- if (!marker) {
- continue;
- }
- const range = new Range(anchor.range.startLineNumber, startColumn, anchor.range.startLineNumber, endColumn);
- result.push(new MarkerHover(this, range, marker));
- }
- return result;
- }
- renderHoverParts(context, hoverParts) {
- if (!hoverParts.length) {
- return Disposable.None;
- }
- const disposables = new DisposableStore();
- hoverParts.forEach(msg => context.fragment.appendChild(this.renderMarkerHover(msg, disposables)));
- const markerHoverForStatusbar = hoverParts.length === 1 ? hoverParts[0] : hoverParts.sort((a, b) => MarkerSeverity.compare(a.marker.severity, b.marker.severity))[0];
- this.renderMarkerStatusbar(context, markerHoverForStatusbar, disposables);
- return disposables;
- }
- renderMarkerHover(markerHover, disposables) {
- const hoverElement = $('div.hover-row');
- const markerElement = dom.append(hoverElement, $('div.marker.hover-contents'));
- const { source, message, code, relatedInformation } = markerHover.marker;
- this._editor.applyFontInfo(markerElement);
- const messageElement = dom.append(markerElement, $('span'));
- messageElement.style.whiteSpace = 'pre-wrap';
- messageElement.innerText = message;
- if (source || code) {
- // Code has link
- if (code && typeof code !== 'string') {
- const sourceAndCodeElement = $('span');
- if (source) {
- const sourceElement = dom.append(sourceAndCodeElement, $('span'));
- sourceElement.innerText = source;
- }
- const codeLink = dom.append(sourceAndCodeElement, $('a.code-link'));
- codeLink.setAttribute('href', code.target.toString());
- disposables.add(dom.addDisposableListener(codeLink, 'click', (e) => {
- this._openerService.open(code.target, { allowCommands: true });
- e.preventDefault();
- e.stopPropagation();
- }));
- const codeElement = dom.append(codeLink, $('span'));
- codeElement.innerText = code.value;
- const detailsElement = dom.append(markerElement, sourceAndCodeElement);
- detailsElement.style.opacity = '0.6';
- detailsElement.style.paddingLeft = '6px';
- }
- else {
- const detailsElement = dom.append(markerElement, $('span'));
- detailsElement.style.opacity = '0.6';
- detailsElement.style.paddingLeft = '6px';
- detailsElement.innerText = source && code ? `${source}(${code})` : source ? source : `(${code})`;
- }
- }
- if (isNonEmptyArray(relatedInformation)) {
- for (const { message, resource, startLineNumber, startColumn } of relatedInformation) {
- const relatedInfoContainer = dom.append(markerElement, $('div'));
- relatedInfoContainer.style.marginTop = '8px';
- const a = dom.append(relatedInfoContainer, $('a'));
- a.innerText = `${basename(resource)}(${startLineNumber}, ${startColumn}): `;
- a.style.cursor = 'pointer';
- disposables.add(dom.addDisposableListener(a, 'click', (e) => {
- e.stopPropagation();
- e.preventDefault();
- if (this._openerService) {
- this._openerService.open(resource, {
- fromUserGesture: true,
- editorOptions: { selection: { startLineNumber, startColumn } }
- }).catch(onUnexpectedError);
- }
- }));
- const messageElement = dom.append(relatedInfoContainer, $('span'));
- messageElement.innerText = message;
- this._editor.applyFontInfo(messageElement);
- }
- }
- return hoverElement;
- }
- renderMarkerStatusbar(context, markerHover, disposables) {
- if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) {
- context.statusBar.addAction({
- label: nls.localize('view problem', "View Problem"),
- commandId: NextMarkerAction.ID,
- run: () => {
- var _a;
- context.hide();
- (_a = MarkerController.get(this._editor)) === null || _a === void 0 ? void 0 : _a.showAtMarker(markerHover.marker);
- this._editor.focus();
- }
- });
- }
- if (!this._editor.getOption(83 /* EditorOption.readOnly */)) {
- const quickfixPlaceholderElement = context.statusBar.append($('div'));
- if (this.recentMarkerCodeActionsInfo) {
- if (IMarkerData.makeKey(this.recentMarkerCodeActionsInfo.marker) === IMarkerData.makeKey(markerHover.marker)) {
- if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
- quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
- }
- }
- else {
- this.recentMarkerCodeActionsInfo = undefined;
- }
- }
- const updatePlaceholderDisposable = this.recentMarkerCodeActionsInfo && !this.recentMarkerCodeActionsInfo.hasCodeActions ? Disposable.None : disposables.add(disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize('checkingForQuickFixes', "Checking for quick fixes..."), 200));
- if (!quickfixPlaceholderElement.textContent) {
- // Have some content in here to avoid flickering
- quickfixPlaceholderElement.textContent = String.fromCharCode(0xA0); //
- }
- const codeActionsPromise = this.getCodeActions(markerHover.marker);
- disposables.add(toDisposable(() => codeActionsPromise.cancel()));
- codeActionsPromise.then(actions => {
- updatePlaceholderDisposable.dispose();
- this.recentMarkerCodeActionsInfo = { marker: markerHover.marker, hasCodeActions: actions.validActions.length > 0 };
- if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
- actions.dispose();
- quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
- return;
- }
- quickfixPlaceholderElement.style.display = 'none';
- let showing = false;
- disposables.add(toDisposable(() => {
- if (!showing) {
- actions.dispose();
- }
- }));
- context.statusBar.addAction({
- label: nls.localize('quick fixes', "Quick Fix..."),
- commandId: QuickFixAction.Id,
- run: (target) => {
- showing = true;
- const controller = QuickFixController.get(this._editor);
- const elementPosition = dom.getDomNodePagePosition(target);
- // Hide the hover pre-emptively, otherwise the editor can close the code actions
- // context menu as well when using keyboard navigation
- context.hide();
- controller === null || controller === void 0 ? void 0 : controller.showCodeActions(markerCodeActionTrigger, actions, {
- x: elementPosition.left + 6,
- y: elementPosition.top + elementPosition.height + 6,
- width: elementPosition.width,
- height: elementPosition.height
- });
- }
- });
- }, onUnexpectedError);
- }
- }
- getCodeActions(marker) {
- return createCancelablePromise(cancellationToken => {
- return getCodeActions(this._languageFeaturesService.codeActionProvider, this._editor.getModel(), new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn), markerCodeActionTrigger, Progress.None, cancellationToken);
- });
- }
- };
- MarkerHoverParticipant = __decorate([
- __param(1, IMarkerDecorationsService),
- __param(2, IOpenerService),
- __param(3, ILanguageFeaturesService)
- ], MarkerHoverParticipant);
- export { MarkerHoverParticipant };
- registerThemingParticipant((theme, collector) => {
- const linkFg = theme.getColor(textLinkForeground);
- if (linkFg) {
- collector.addRule(`.monaco-hover .hover-contents a.code-link span { color: ${linkFg}; }`);
- }
- const activeLinkFg = theme.getColor(textLinkActiveForeground);
- if (activeLinkFg) {
- collector.addRule(`.monaco-hover .hover-contents a.code-link span:hover { color: ${activeLinkFg}; }`);
- }
- });
|