@21epub/epub-thirdparty
Version:
epub-thirdparty
234 lines (233 loc) • 10.3 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _CodeActionModel_isDisposed;
import { createCancelablePromise, TimeoutTimer } from '../../../base/common/async.js';
import { isPromiseCanceledError } from '../../../base/common/errors.js';
import { Emitter } from '../../../base/common/event.js';
import { Disposable, MutableDisposable } from '../../../base/common/lifecycle.js';
import { isEqual } from '../../../base/common/resources.js';
import { Range } from '../../common/core/range.js';
import { CodeActionProviderRegistry } from '../../common/modes.js';
import { RawContextKey } from '../../../platform/contextkey/common/contextkey.js';
import { Progress } from '../../../platform/progress/common/progress.js';
import { getCodeActions } from './codeAction.js';
export const SUPPORTED_CODE_ACTIONS = new RawContextKey('supportedCodeAction', '');
class CodeActionOracle extends Disposable {
constructor(_editor, _markerService, _signalChange, _delay = 250) {
super();
this._editor = _editor;
this._markerService = _markerService;
this._signalChange = _signalChange;
this._delay = _delay;
this._autoTriggerTimer = this._register(new TimeoutTimer());
this._register(this._markerService.onMarkerChanged(e => this._onMarkerChanges(e)));
this._register(this._editor.onDidChangeCursorPosition(() => this._onCursorChange()));
}
trigger(trigger) {
const selection = this._getRangeOfSelectionUnlessWhitespaceEnclosed(trigger);
return this._createEventAndSignalChange(trigger, selection);
}
_onMarkerChanges(resources) {
const model = this._editor.getModel();
if (!model) {
return;
}
if (resources.some(resource => isEqual(resource, model.uri))) {
this._autoTriggerTimer.cancelAndSet(() => {
this.trigger({ type: 2 /* Auto */ });
}, this._delay);
}
}
_onCursorChange() {
this._autoTriggerTimer.cancelAndSet(() => {
this.trigger({ type: 2 /* Auto */ });
}, this._delay);
}
_getRangeOfMarker(selection) {
const model = this._editor.getModel();
if (!model) {
return undefined;
}
for (const marker of this._markerService.read({ resource: model.uri })) {
const markerRange = model.validateRange(marker);
if (Range.intersectRanges(markerRange, selection)) {
return Range.lift(markerRange);
}
}
return undefined;
}
_getRangeOfSelectionUnlessWhitespaceEnclosed(trigger) {
if (!this._editor.hasModel()) {
return undefined;
}
const model = this._editor.getModel();
const selection = this._editor.getSelection();
if (selection.isEmpty() && trigger.type === 2 /* Auto */) {
const { lineNumber, column } = selection.getPosition();
const line = model.getLineContent(lineNumber);
if (line.length === 0) {
// empty line
return undefined;
}
else if (column === 1) {
// look only right
if (/\s/.test(line[0])) {
return undefined;
}
}
else if (column === model.getLineMaxColumn(lineNumber)) {
// look only left
if (/\s/.test(line[line.length - 1])) {
return undefined;
}
}
else {
// look left and right
if (/\s/.test(line[column - 2]) && /\s/.test(line[column - 1])) {
return undefined;
}
}
}
return selection;
}
_createEventAndSignalChange(trigger, selection) {
const model = this._editor.getModel();
if (!selection || !model) {
// cancel
this._signalChange(undefined);
return undefined;
}
const markerRange = this._getRangeOfMarker(selection);
const position = markerRange ? markerRange.getStartPosition() : selection.getStartPosition();
const e = {
trigger,
selection,
position
};
this._signalChange(e);
return e;
}
}
export var CodeActionsState;
(function (CodeActionsState) {
CodeActionsState.Empty = { type: 0 /* Empty */ };
class Triggered {
constructor(trigger, rangeOrSelection, position, _cancellablePromise) {
this.trigger = trigger;
this.rangeOrSelection = rangeOrSelection;
this.position = position;
this._cancellablePromise = _cancellablePromise;
this.type = 1 /* Triggered */;
this.actions = _cancellablePromise.catch((e) => {
if (isPromiseCanceledError(e)) {
return emptyCodeActionSet;
}
throw e;
});
}
cancel() {
this._cancellablePromise.cancel();
}
}
CodeActionsState.Triggered = Triggered;
})(CodeActionsState || (CodeActionsState = {}));
const emptyCodeActionSet = {
allActions: [],
validActions: [],
dispose: () => { },
documentation: [],
hasAutoFix: false
};
export class CodeActionModel extends Disposable {
constructor(_editor, _markerService, contextKeyService, _progressService) {
super();
this._editor = _editor;
this._markerService = _markerService;
this._progressService = _progressService;
this._codeActionOracle = this._register(new MutableDisposable());
this._state = CodeActionsState.Empty;
this._onDidChangeState = this._register(new Emitter());
this.onDidChangeState = this._onDidChangeState.event;
_CodeActionModel_isDisposed.set(this, false);
this._supportedCodeActions = SUPPORTED_CODE_ACTIONS.bindTo(contextKeyService);
this._register(this._editor.onDidChangeModel(() => this._update()));
this._register(this._editor.onDidChangeModelLanguage(() => this._update()));
this._register(CodeActionProviderRegistry.onDidChange(() => this._update()));
this._update();
}
dispose() {
if (__classPrivateFieldGet(this, _CodeActionModel_isDisposed, "f")) {
return;
}
__classPrivateFieldSet(this, _CodeActionModel_isDisposed, true, "f");
super.dispose();
this.setState(CodeActionsState.Empty, true);
}
_update() {
if (__classPrivateFieldGet(this, _CodeActionModel_isDisposed, "f")) {
return;
}
this._codeActionOracle.value = undefined;
this.setState(CodeActionsState.Empty);
const model = this._editor.getModel();
if (model
&& CodeActionProviderRegistry.has(model)
&& !this._editor.getOption(80 /* readOnly */)) {
const supportedActions = [];
for (const provider of CodeActionProviderRegistry.all(model)) {
if (Array.isArray(provider.providedCodeActionKinds)) {
supportedActions.push(...provider.providedCodeActionKinds);
}
}
this._supportedCodeActions.set(supportedActions.join(' '));
this._codeActionOracle.value = new CodeActionOracle(this._editor, this._markerService, trigger => {
var _a;
if (!trigger) {
this.setState(CodeActionsState.Empty);
return;
}
const actions = createCancelablePromise(token => getCodeActions(model, trigger.selection, trigger.trigger, Progress.None, token));
if (trigger.trigger.type === 1 /* Invoke */) {
(_a = this._progressService) === null || _a === void 0 ? void 0 : _a.showWhile(actions, 250);
}
this.setState(new CodeActionsState.Triggered(trigger.trigger, trigger.selection, trigger.position, actions));
}, undefined);
this._codeActionOracle.value.trigger({ type: 2 /* Auto */ });
}
else {
this._supportedCodeActions.reset();
}
}
trigger(trigger) {
if (this._codeActionOracle.value) {
this._codeActionOracle.value.trigger(trigger);
}
}
setState(newState, skipNotify) {
if (newState === this._state) {
return;
}
// Cancel old request
if (this._state.type === 1 /* Triggered */) {
this._state.cancel();
}
this._state = newState;
if (!skipNotify && !__classPrivateFieldGet(this, _CodeActionModel_isDisposed, "f")) {
this._onDidChangeState.fire(newState);
}
}
}
_CodeActionModel_isDisposed = new WeakMap();