Path: blob/main/extensions/copilot/test/simulation/fixtures/edit/issue-7996/codeEditorWidget.ts
13405 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 * as dom from '../../../../base/browser/dom.js';6import { IKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';7import { IMouseWheelEvent } from '../../../../base/browser/mouseEvent.js';8import { Color } from '../../../../base/common/color.js';9import { onUnexpectedError } from '../../../../base/common/errors.js';10import { Emitter, EmitterOptions, Event, EventDeliveryQueue, createEventDeliveryQueue } from '../../../../base/common/event.js';11import { hash } from '../../../../base/common/hash.js';12import { Disposable, DisposableStore, IDisposable, dispose } from '../../../../base/common/lifecycle.js';13import { Schemas } from '../../../../base/common/network.js';14import * as nls from '../../../../nls.js';15import { IAccessibilityService } from '../../../../platform/accessibility/common/accessibility.js';16import { MenuId } from '../../../../platform/actions/common/actions.js';17import { ICommandService } from '../../../../platform/commands/common/commands.js';18import { ContextKeyValue, IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';19import { IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';20import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js';21import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';22import { editorErrorForeground, editorHintForeground, editorInfoForeground, editorWarningForeground } from '../../../../platform/theme/common/colorRegistry.js';23import { IThemeService, registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';24import { IEditorConfiguration } from '../../../common/config/editorConfiguration.js';25import { ConfigurationChangedEvent, EditorLayoutInfo, EditorOption, FindComputedEditorOptionValueById, IComputedEditorOptions, IEditorOptions, filterValidationDecorations } from '../../../common/config/editorOptions.js';26import { CursorColumns } from '../../../common/core/cursorColumns.js';27import { IDimension } from '../../../common/core/dimension.js';28import { editorUnnecessaryCodeOpacity } from '../../../common/core/editorColorRegistry.js';29import { IPosition, Position } from '../../../common/core/position.js';30import { IRange, Range } from '../../../common/core/range.js';31import { ISelection, Selection } from '../../../common/core/selection.js';32import { IWordAtPosition } from '../../../common/core/wordHelper.js';33import { WordOperations } from '../../../common/cursor/cursorWordOperations.js';34import { CursorChangeReason, ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from '../../../common/cursorEvents.js';35import { InternalEditorAction } from '../../../common/editorAction.js';36import * as editorCommon from '../../../common/editorCommon.js';37import { EditorContextKeys } from '../../../common/editorContextKeys.js';38import { ILanguageConfigurationService } from '../../../common/languages/languageConfigurationRegistry.js';39import { EndOfLinePreference, IAttachedView, ICursorStateComputer, IIdentifiedSingleEditOperation, IModelDecoration, IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from '../../../common/model.js';40import { ClassName } from '../../../common/model/intervalTree.js';41import { ModelDecorationOptions } from '../../../common/model/textModel.js';42import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';43import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent } from '../../../common/textModelEvents.js';44import { VerticalRevealType } from '../../../common/viewEvents.js';45import { IEditorWhitespace, IViewModel } from '../../../common/viewModel.js';46import { MonospaceLineBreaksComputerFactory } from '../../../common/viewModel/monospaceLineBreaksComputer.js';47import { ViewModel } from '../../../common/viewModel/viewModelImpl.js';48import { OutgoingViewModelEventKind } from '../../../common/viewModelEventDispatcher.js';49import { applyFontInfo } from '../../config/domFontInfo.js';50import { EditorConfiguration, IEditorConstructionOptions } from '../../config/editorConfiguration.js';51import { TabFocus } from '../../config/tabFocus.js';52import * as editorBrowser from '../../editorBrowser.js';53import { EditorExtensionsRegistry, IEditorContributionDescription } from '../../editorExtensions.js';54import { ICodeEditorService } from '../../services/codeEditorService.js';55import '../../services/markerDecorations.js';56import { IContentWidgetData, IGlyphMarginWidgetData, IOverlayWidgetData, View } from '../../view.js';57import { DOMLineBreaksComputerFactory } from '../../view/domLineBreaksComputer.js';58import { ICommandDelegate } from '../../view/viewController.js';59import { ViewUserInputEvents } from '../../view/viewUserInputEvents.js';60import { CodeEditorContributions } from './codeEditorContributions.js';61import './editor.css';6263export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeEditor {6465private static readonly dropIntoEditorDecorationOptions = ModelDecorationOptions.register({66description: 'workbench-dnd-target',67className: 'dnd-target'68});6970//#region Eventing7172private readonly _deliveryQueue = createEventDeliveryQueue();73protected readonly _contributions: CodeEditorContributions = this._register(new CodeEditorContributions());7475private readonly _onDidDispose: Emitter<void> = this._register(new Emitter<void>());76public readonly onDidDispose: Event<void> = this._onDidDispose.event;7778private readonly _onDidChangeModelContent: Emitter<IModelContentChangedEvent> = this._register(new Emitter<IModelContentChangedEvent>({ deliveryQueue: this._deliveryQueue }));79public readonly onDidChangeModelContent: Event<IModelContentChangedEvent> = this._onDidChangeModelContent.event;8081private readonly _onDidChangeModelLanguage: Emitter<IModelLanguageChangedEvent> = this._register(new Emitter<IModelLanguageChangedEvent>({ deliveryQueue: this._deliveryQueue }));82public readonly onDidChangeModelLanguage: Event<IModelLanguageChangedEvent> = this._onDidChangeModelLanguage.event;8384private readonly _onDidChangeModelLanguageConfiguration: Emitter<IModelLanguageConfigurationChangedEvent> = this._register(new Emitter<IModelLanguageConfigurationChangedEvent>({ deliveryQueue: this._deliveryQueue }));85public readonly onDidChangeModelLanguageConfiguration: Event<IModelLanguageConfigurationChangedEvent> = this._onDidChangeModelLanguageConfiguration.event;8687private readonly _onDidChangeModelOptions: Emitter<IModelOptionsChangedEvent> = this._register(new Emitter<IModelOptionsChangedEvent>({ deliveryQueue: this._deliveryQueue }));88public readonly onDidChangeModelOptions: Event<IModelOptionsChangedEvent> = this._onDidChangeModelOptions.event;8990private readonly _onDidChangeModelDecorations: Emitter<IModelDecorationsChangedEvent> = this._register(new Emitter<IModelDecorationsChangedEvent>({ deliveryQueue: this._deliveryQueue }));91public readonly onDidChangeModelDecorations: Event<IModelDecorationsChangedEvent> = this._onDidChangeModelDecorations.event;9293private readonly _onDidChangeModelTokens: Emitter<IModelTokensChangedEvent> = this._register(new Emitter<IModelTokensChangedEvent>({ deliveryQueue: this._deliveryQueue }));94public readonly onDidChangeModelTokens: Event<IModelTokensChangedEvent> = this._onDidChangeModelTokens.event;9596private readonly _onDidChangeConfiguration: Emitter<ConfigurationChangedEvent> = this._register(new Emitter<ConfigurationChangedEvent>({ deliveryQueue: this._deliveryQueue }));97public readonly onDidChangeConfiguration: Event<ConfigurationChangedEvent> = this._onDidChangeConfiguration.event;9899protected readonly _onWillChangeModel: Emitter<editorCommon.IModelChangedEvent> = this._register(new Emitter<editorCommon.IModelChangedEvent>({ deliveryQueue: this._deliveryQueue }));100public readonly onWillChangeModel: Event<editorCommon.IModelChangedEvent> = this._onWillChangeModel.event;101102protected readonly _onDidChangeModel: Emitter<editorCommon.IModelChangedEvent> = this._register(new Emitter<editorCommon.IModelChangedEvent>({ deliveryQueue: this._deliveryQueue }));103public readonly onDidChangeModel: Event<editorCommon.IModelChangedEvent> = this._onDidChangeModel.event;104105private readonly _onDidChangeCursorPosition: Emitter<ICursorPositionChangedEvent> = this._register(new Emitter<ICursorPositionChangedEvent>({ deliveryQueue: this._deliveryQueue }));106public readonly onDidChangeCursorPosition: Event<ICursorPositionChangedEvent> = this._onDidChangeCursorPosition.event;107108private readonly _onDidChangeCursorSelection: Emitter<ICursorSelectionChangedEvent> = this._register(new Emitter<ICursorSelectionChangedEvent>({ deliveryQueue: this._deliveryQueue }));109public readonly onDidChangeCursorSelection: Event<ICursorSelectionChangedEvent> = this._onDidChangeCursorSelection.event;110111private readonly _onDidAttemptReadOnlyEdit: Emitter<void> = this._register(new InteractionEmitter<void>(this._contributions, this._deliveryQueue));112public readonly onDidAttemptReadOnlyEdit: Event<void> = this._onDidAttemptReadOnlyEdit.event;113114private readonly _onDidLayoutChange: Emitter<EditorLayoutInfo> = this._register(new Emitter<EditorLayoutInfo>({ deliveryQueue: this._deliveryQueue }));115public readonly onDidLayoutChange: Event<EditorLayoutInfo> = this._onDidLayoutChange.event;116117private readonly _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter({ deliveryQueue: this._deliveryQueue }));118public readonly onDidFocusEditorText: Event<void> = this._editorTextFocus.onDidChangeToTrue;119public readonly onDidBlurEditorText: Event<void> = this._editorTextFocus.onDidChangeToFalse;120121private readonly _editorWidgetFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter({ deliveryQueue: this._deliveryQueue }));122public readonly onDidFocusEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToTrue;123public readonly onDidBlurEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToFalse;124125private readonly _onWillType: Emitter<string> = this._register(new InteractionEmitter<string>(this._contributions, this._deliveryQueue));126public readonly onWillType = this._onWillType.event;127128private readonly _onDidType: Emitter<string> = this._register(new InteractionEmitter<string>(this._contributions, this._deliveryQueue));129public readonly onDidType = this._onDidType.event;130131private readonly _onDidCompositionStart: Emitter<void> = this._register(new InteractionEmitter<void>(this._contributions, this._deliveryQueue));132public readonly onDidCompositionStart = this._onDidCompositionStart.event;133134private readonly _onDidCompositionEnd: Emitter<void> = this._register(new InteractionEmitter<void>(this._contributions, this._deliveryQueue));135public readonly onDidCompositionEnd = this._onDidCompositionEnd.event;136137private readonly _onDidPaste: Emitter<editorBrowser.IPasteEvent> = this._register(new InteractionEmitter<editorBrowser.IPasteEvent>(this._contributions, this._deliveryQueue));138public readonly onDidPaste = this._onDidPaste.event;139140private readonly _onMouseUp: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IEditorMouseEvent>(this._contributions, this._deliveryQueue));141public readonly onMouseUp: Event<editorBrowser.IEditorMouseEvent> = this._onMouseUp.event;142143private readonly _onMouseDown: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IEditorMouseEvent>(this._contributions, this._deliveryQueue));144public readonly onMouseDown: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDown.event;145146private readonly _onMouseDrag: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IEditorMouseEvent>(this._contributions, this._deliveryQueue));147public readonly onMouseDrag: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDrag.event;148149private readonly _onMouseDrop: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IPartialEditorMouseEvent>(this._contributions, this._deliveryQueue));150public readonly onMouseDrop: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseDrop.event;151152private readonly _onMouseDropCanceled: Emitter<void> = this._register(new InteractionEmitter<void>(this._contributions, this._deliveryQueue));153public readonly onMouseDropCanceled: Event<void> = this._onMouseDropCanceled.event;154155private readonly _onDropIntoEditor = this._register(new InteractionEmitter<{ readonly position: IPosition; readonly event: DragEvent }>(this._contributions, this._deliveryQueue));156public readonly onDropIntoEditor = this._onDropIntoEditor.event;157158private readonly _onContextMenu: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IEditorMouseEvent>(this._contributions, this._deliveryQueue));159public readonly onContextMenu: Event<editorBrowser.IEditorMouseEvent> = this._onContextMenu.event;160161private readonly _onMouseMove: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IEditorMouseEvent>(this._contributions, this._deliveryQueue));162public readonly onMouseMove: Event<editorBrowser.IEditorMouseEvent> = this._onMouseMove.event;163164private readonly _onMouseLeave: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new InteractionEmitter<editorBrowser.IPartialEditorMouseEvent>(this._contributions, this._deliveryQueue));165public readonly onMouseLeave: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseLeave.event;166167private readonly _onMouseWheel: Emitter<IMouseWheelEvent> = this._register(new InteractionEmitter<IMouseWheelEvent>(this._contributions, this._deliveryQueue));168public readonly onMouseWheel: Event<IMouseWheelEvent> = this._onMouseWheel.event;169170private readonly _onKeyUp: Emitter<IKeyboardEvent> = this._register(new InteractionEmitter<IKeyboardEvent>(this._contributions, this._deliveryQueue));171public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;172173private readonly _onKeyDown: Emitter<IKeyboardEvent> = this._register(new InteractionEmitter<IKeyboardEvent>(this._contributions, this._deliveryQueue));174public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;175176private readonly _onDidContentSizeChange: Emitter<editorCommon.IContentSizeChangedEvent> = this._register(new Emitter<editorCommon.IContentSizeChangedEvent>({ deliveryQueue: this._deliveryQueue }));177public readonly onDidContentSizeChange: Event<editorCommon.IContentSizeChangedEvent> = this._onDidContentSizeChange.event;178179private readonly _onDidScrollChange: Emitter<editorCommon.IScrollEvent> = this._register(new Emitter<editorCommon.IScrollEvent>({ deliveryQueue: this._deliveryQueue }));180public readonly onDidScrollChange: Event<editorCommon.IScrollEvent> = this._onDidScrollChange.event;181182private readonly _onDidChangeViewZones: Emitter<void> = this._register(new Emitter<void>({ deliveryQueue: this._deliveryQueue }));183public readonly onDidChangeViewZones: Event<void> = this._onDidChangeViewZones.event;184185private readonly _onDidChangeHiddenAreas: Emitter<void> = this._register(new Emitter<void>({ deliveryQueue: this._deliveryQueue }));186public readonly onDidChangeHiddenAreas: Event<void> = this._onDidChangeHiddenAreas.event;187188private _updateCounter = 0;189190private readonly _onBeginUpdate: Emitter<void> = this._register(new Emitter<void>());191public readonly onBeginUpdate: Event<void> = this._onBeginUpdate.event;192193private readonly _onEndUpdate: Emitter<void> = this._register(new Emitter<void>());194public readonly onEndUpdate: Event<void> = this._onEndUpdate.event;195196//#endregion197198public get isSimpleWidget(): boolean {199return this._configuration.isSimpleWidget;200}201202public get contextMenuId(): MenuId {203return this._configuration.contextMenuId;204}205206private readonly _telemetryData?: object;207208private readonly _domElement: HTMLElement;209private readonly _overflowWidgetsDomNode: HTMLElement | undefined;210private readonly _id: number;211private readonly _configuration: IEditorConfiguration;212private _contributionsDisposable: IDisposable | undefined;213214protected readonly _actions = new Map<string, editorCommon.IEditorAction>();215216// --- Members logically associated to a model217protected _modelData: ModelData | null;218219protected readonly _instantiationService: IInstantiationService;220protected readonly _contextKeyService: IContextKeyService;221get contextKeyService() { return this._contextKeyService; }222private readonly _notificationService: INotificationService;223protected readonly _codeEditorService: ICodeEditorService;224private readonly _commandService: ICommandService;225private readonly _themeService: IThemeService;226227private readonly _focusTracker: CodeEditorWidgetFocusTracker;228229private _contentWidgets: { [key: string]: IContentWidgetData };230private _overlayWidgets: { [key: string]: IOverlayWidgetData };231private _glyphMarginWidgets: { [key: string]: IGlyphMarginWidgetData };232233/**234* map from "parent" decoration type to live decoration ids.235*/236private _decorationTypeKeysToIds: { [decorationTypeKey: string]: string[] };237private _decorationTypeSubtypes: { [decorationTypeKey: string]: { [subtype: string]: boolean } };238239private _bannerDomNode: HTMLElement | null = null;240241private _dropIntoEditorDecorations: EditorDecorationsCollection = this.createDecorationsCollection();242243constructor(244domElement: HTMLElement,245_options: Readonly<IEditorConstructionOptions>,246codeEditorWidgetOptions: ICodeEditorWidgetOptions,247@IInstantiationService instantiationService: IInstantiationService,248@ICodeEditorService codeEditorService: ICodeEditorService,249@ICommandService commandService: ICommandService,250@IContextKeyService contextKeyService: IContextKeyService,251@IThemeService themeService: IThemeService,252@INotificationService notificationService: INotificationService,253@IAccessibilityService accessibilityService: IAccessibilityService,254@ILanguageConfigurationService private readonly languageConfigurationService: ILanguageConfigurationService,255@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,256) {257super();258codeEditorService.willCreateCodeEditor();259260const options = { ..._options };261262this._domElement = domElement;263this._overflowWidgetsDomNode = options.overflowWidgetsDomNode;264delete options.overflowWidgetsDomNode;265this._id = (++EDITOR_ID);266this._decorationTypeKeysToIds = {};267this._decorationTypeSubtypes = {};268this._telemetryData = codeEditorWidgetOptions.telemetryData;269270this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false,271codeEditorWidgetOptions.contextMenuId ?? (codeEditorWidgetOptions.isSimpleWidget ? MenuId.SimpleEditorContext : MenuId.EditorContext),272options, accessibilityService));273this._register(this._configuration.onDidChange((e) => {274this._onDidChangeConfiguration.fire(e);275276const options = this._configuration.options;277if (e.hasChanged(EditorOption.layoutInfo)) {278const layoutInfo = options.get(EditorOption.layoutInfo);279this._onDidLayoutChange.fire(layoutInfo);280}281}));282283this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));284this._notificationService = notificationService;285this._codeEditorService = codeEditorService;286this._commandService = commandService;287this._themeService = themeService;288this._register(new EditorContextKeysManager(this, this._contextKeyService));289this._register(new EditorModeContext(this, this._contextKeyService, languageFeaturesService));290291this._instantiationService = this._register(instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService])));292293this._modelData = null;294295this._focusTracker = new CodeEditorWidgetFocusTracker(domElement, this._overflowWidgetsDomNode);296this._register(this._focusTracker.onChange(() => {297this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());298}));299300this._contentWidgets = {};301this._overlayWidgets = {};302this._glyphMarginWidgets = {};303304let contributions: IEditorContributionDescription[];305if (Array.isArray(codeEditorWidgetOptions.contributions)) {306contributions = codeEditorWidgetOptions.contributions;307} else {308contributions = EditorExtensionsRegistry.getEditorContributions();309}310this._contributions.initialize(this, contributions, this._instantiationService);311312for (const action of EditorExtensionsRegistry.getEditorActions()) {313if (this._actions.has(action.id)) {314onUnexpectedError(new Error(`Cannot have two actions with the same id ${action.id}`));315continue;316}317const internalAction = new InternalEditorAction(318action.id,319action.label,320action.alias,321action.metadata,322action.precondition ?? undefined,323(args: unknown): Promise<void> => {324return this._instantiationService.invokeFunction((accessor) => {325return Promise.resolve(action.runEditorCommand(accessor, this, args));326});327},328this._contextKeyService329);330this._actions.set(internalAction.id, internalAction);331}332333const isDropIntoEnabled = () => {334return !this._configuration.options.get(EditorOption.readOnly)335&& this._configuration.options.get(EditorOption.dropIntoEditor).enabled;336};337338this._register(new dom.DragAndDropObserver(this._domElement, {339onDragOver: e => {340if (!isDropIntoEnabled()) {341return;342}343344const target = this.getTargetAtClientPoint(e.clientX, e.clientY);345if (target?.position) {346this.showDropIndicatorAt(target.position);347}348},349onDrop: async e => {350if (!isDropIntoEnabled()) {351return;352}353354this.removeDropIndicator();355356if (!e.dataTransfer) {357return;358}359360const target = this.getTargetAtClientPoint(e.clientX, e.clientY);361if (target?.position) {362this._onDropIntoEditor.fire({ position: target.position, event: e });363}364},365onDragLeave: () => {366this.removeDropIndicator();367},368onDragEnd: () => {369this.removeDropIndicator();370},371}));372373this._codeEditorService.addCodeEditor(this);374}375376public writeScreenReaderContent(reason: string): void {377this._modelData?.view.writeScreenReaderContent(reason);378}379380protected _createConfiguration(isSimpleWidget: boolean, contextMenuId: MenuId, options: Readonly<IEditorConstructionOptions>, accessibilityService: IAccessibilityService): EditorConfiguration {381return new EditorConfiguration(isSimpleWidget, contextMenuId, options, this._domElement, accessibilityService);382}383384public getId(): string {385return this.getEditorType() + ':' + this._id;386}387388public getEditorType(): string {389return editorCommon.EditorType.ICodeEditor;390}391392public override dispose(): void {393this._codeEditorService.removeCodeEditor(this);394395this._focusTracker.dispose();396this._actions.clear();397this._contentWidgets = {};398this._overlayWidgets = {};399400this._removeDecorationTypes();401this._postDetachModelCleanup(this._detachModel());402403this._onDidDispose.fire();404405super.dispose();406}407408public invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T {409return this._instantiationService.invokeFunction(fn);410}411412public updateOptions(newOptions: Readonly<IEditorOptions> | undefined): void {413this._configuration.updateOptions(newOptions || {});414}415416public getOptions(): IComputedEditorOptions {417return this._configuration.options;418}419420public getOption<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T> {421return this._configuration.options.get(id);422}423424public getRawOptions(): IEditorOptions {425return this._configuration.getRawOptions();426}427428public getOverflowWidgetsDomNode(): HTMLElement | undefined {429return this._overflowWidgetsDomNode;430}431432public getConfiguredWordAtPosition(position: Position): IWordAtPosition | null {433if (!this._modelData) {434return null;435}436return WordOperations.getWordAtPosition(this._modelData.model, this._configuration.options.get(EditorOption.wordSeparators), this._configuration.options.get(EditorOption.wordSegmenterLocales), position);437}438439public getValue(options: { preserveBOM: boolean; lineEnding: string } | null = null): string {440if (!this._modelData) {441return '';442}443444const preserveBOM: boolean = (options && options.preserveBOM) ? true : false;445let eolPreference = EndOfLinePreference.TextDefined;446if (options && options.lineEnding && options.lineEnding === '\n') {447eolPreference = EndOfLinePreference.LF;448} else if (options && options.lineEnding && options.lineEnding === '\r\n') {449eolPreference = EndOfLinePreference.CRLF;450}451return this._modelData.model.getValue(eolPreference, preserveBOM);452}453454public setValue(newValue: string): void {455try {456this._beginUpdate();457if (!this._modelData) {458return;459}460this._modelData.model.setValue(newValue);461} finally {462this._endUpdate();463}464}465466public getModel(): ITextModel | null {467if (!this._modelData) {468return null;469}470return this._modelData.model;471}472473public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null = null): void {474try {475this._beginUpdate();476const model = <ITextModel | null>_model;477if (this._modelData === null && model === null) {478// Current model is the new model479return;480}481if (this._modelData && this._modelData.model === model) {482// Current model is the new model483return;484}485486const e: editorCommon.IModelChangedEvent = {487oldModelUrl: this._modelData?.model.uri || null,488newModelUrl: model?.uri || null489};490this._onWillChangeModel.fire(e);491492const hasTextFocus = this.hasTextFocus();493const detachedModel = this._detachModel();494this._attachModel(model);495if (hasTextFocus && this.hasModel()) {496this.focus();497}498499this._removeDecorationTypes();500this._onDidChangeModel.fire(e);501this._postDetachModelCleanup(detachedModel);502503this._contributionsDisposable = this._contributions.onAfterModelAttached();504} finally {505this._endUpdate();506}507}508509private _removeDecorationTypes(): void {510this._decorationTypeKeysToIds = {};511if (this._decorationTypeSubtypes) {512for (const decorationType in this._decorationTypeSubtypes) {513const subTypes = this._decorationTypeSubtypes[decorationType];514for (const subType in subTypes) {515this._removeDecorationType(decorationType + '-' + subType);516}517}518this._decorationTypeSubtypes = {};519}520}521522public getVisibleRanges(): Range[] {523if (!this._modelData) {524return [];525}526return this._modelData.viewModel.getVisibleRanges();527}528529public getVisibleRangesPlusViewportAboveBelow(): Range[] {530if (!this._modelData) {531return [];532}533return this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow();534}535536public getWhitespaces(): IEditorWhitespace[] {537if (!this._modelData) {538return [];539}540return this._modelData.viewModel.viewLayout.getWhitespaces();541}542543private static _getVerticalOffsetAfterPosition(modelData: ModelData, modelLineNumber: number, modelColumn: number, includeViewZones: boolean): number {544const modelPosition = modelData.model.validatePosition({545lineNumber: modelLineNumber,546column: modelColumn547});548const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);549return modelData.viewModel.viewLayout.getVerticalOffsetAfterLineNumber(viewPosition.lineNumber, includeViewZones);550}551552public getTopForLineNumber(lineNumber: number, includeViewZones: boolean = false): number {553if (!this._modelData) {554return -1;555}556return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, 1, includeViewZones);557}558559public getTopForPosition(lineNumber: number, column: number): number {560if (!this._modelData) {561return -1;562}563return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, column, false);564}565566private static _getVerticalOffsetForPosition(modelData: ModelData, modelLineNumber: number, modelColumn: number, includeViewZones: boolean = false): number {567const modelPosition = modelData.model.validatePosition({568lineNumber: modelLineNumber,569column: modelColumn570});571const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);572return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber, includeViewZones);573}574575public getBottomForLineNumber(lineNumber: number, includeViewZones: boolean = false): number {576if (!this._modelData) {577return -1;578}579const maxCol = this._modelData.model.getLineMaxColumn(lineNumber);580return CodeEditorWidget._getVerticalOffsetAfterPosition(this._modelData, lineNumber, maxCol, includeViewZones);581}582583public setHiddenAreas(ranges: IRange[], source?: unknown): void {584this._modelData?.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)), source);585}586587public getVisibleColumnFromPosition(rawPosition: IPosition): number {588if (!this._modelData) {589return rawPosition.column;590}591592const position = this._modelData.model.validatePosition(rawPosition);593const tabSize = this._modelData.model.getOptions().tabSize;594595return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1;596}597598public getStatusbarColumn(rawPosition: IPosition): number {599if (!this._modelData) {600return rawPosition.column;601}602603const position = this._modelData.model.validatePosition(rawPosition);604const tabSize = this._modelData.model.getOptions().tabSize;605606return CursorColumns.toStatusbarColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize);607}608609public getPosition(): Position | null {610if (!this._modelData) {611return null;612}613return this._modelData.viewModel.getPosition();614}615616public setPosition(position: IPosition, source: string = 'api'): void {617if (!this._modelData) {618return;619}620if (!Position.isIPosition(position)) {621throw new Error('Invalid arguments');622}623this._modelData.viewModel.setSelections(source, [{624selectionStartLineNumber: position.lineNumber,625selectionStartColumn: position.column,626positionLineNumber: position.lineNumber,627positionColumn: position.column628}]);629}630631private _sendRevealRange(modelRange: Range, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {632if (!this._modelData) {633return;634}635if (!Range.isIRange(modelRange)) {636throw new Error('Invalid arguments');637}638const validatedModelRange = this._modelData.model.validateRange(modelRange);639const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);640641this._modelData.viewModel.revealRange('api', revealHorizontal, viewRange, verticalType, scrollType);642}643644public revealLine(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {645this._revealLine(lineNumber, VerticalRevealType.Simple, scrollType);646}647648public revealLineInCenter(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {649this._revealLine(lineNumber, VerticalRevealType.Center, scrollType);650}651652public revealLineInCenterIfOutsideViewport(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {653this._revealLine(lineNumber, VerticalRevealType.CenterIfOutsideViewport, scrollType);654}655656public revealLineNearTop(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {657this._revealLine(lineNumber, VerticalRevealType.NearTop, scrollType);658}659660private _revealLine(lineNumber: number, revealType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {661if (typeof lineNumber !== 'number') {662throw new Error('Invalid arguments');663}664665this._sendRevealRange(666new Range(lineNumber, 1, lineNumber, 1),667revealType,668false,669scrollType670);671}672673public revealPosition(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {674this._revealPosition(675position,676VerticalRevealType.Simple,677true,678scrollType679);680}681682public revealPositionInCenter(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {683this._revealPosition(684position,685VerticalRevealType.Center,686true,687scrollType688);689}690691public revealPositionInCenterIfOutsideViewport(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {692this._revealPosition(693position,694VerticalRevealType.CenterIfOutsideViewport,695true,696scrollType697);698}699700public revealPositionNearTop(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {701this._revealPosition(702position,703VerticalRevealType.NearTop,704true,705scrollType706);707}708709private _revealPosition(position: IPosition, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {710if (!Position.isIPosition(position)) {711throw new Error('Invalid arguments');712}713714this._sendRevealRange(715new Range(position.lineNumber, position.column, position.lineNumber, position.column),716verticalType,717revealHorizontal,718scrollType719);720}721722public getSelection(): Selection | null {723if (!this._modelData) {724return null;725}726return this._modelData.viewModel.getSelection();727}728729public getSelections(): Selection[] | null {730if (!this._modelData) {731return null;732}733return this._modelData.viewModel.getSelections();734}735736public setSelection(range: IRange, source?: string): void;737public setSelection(editorRange: Range, source?: string): void;738public setSelection(selection: ISelection, source?: string): void;739public setSelection(editorSelection: Selection, source?: string): void;740public setSelection(something: any, source: string = 'api'): void {741const isSelection = Selection.isISelection(something);742const isRange = Range.isIRange(something);743744if (!isSelection && !isRange) {745throw new Error('Invalid arguments');746}747748if (isSelection) {749this._setSelectionImpl(<ISelection>something, source);750} else if (isRange) {751// act as if it was an IRange752const selection: ISelection = {753selectionStartLineNumber: something.startLineNumber,754selectionStartColumn: something.startColumn,755positionLineNumber: something.endLineNumber,756positionColumn: something.endColumn757};758this._setSelectionImpl(selection, source);759}760}761762private _setSelectionImpl(sel: ISelection, source: string): void {763if (!this._modelData) {764return;765}766const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);767this._modelData.viewModel.setSelections(source, [selection]);768}769770public revealLines(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {771this._revealLines(772startLineNumber,773endLineNumber,774VerticalRevealType.Simple,775scrollType776);777}778779public revealLinesInCenter(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {780this._revealLines(781startLineNumber,782endLineNumber,783VerticalRevealType.Center,784scrollType785);786}787788public revealLinesInCenterIfOutsideViewport(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {789this._revealLines(790startLineNumber,791endLineNumber,792VerticalRevealType.CenterIfOutsideViewport,793scrollType794);795}796797public revealLinesNearTop(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {798this._revealLines(799startLineNumber,800endLineNumber,801VerticalRevealType.NearTop,802scrollType803);804}805806private _revealLines(startLineNumber: number, endLineNumber: number, verticalType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {807if (typeof startLineNumber !== 'number' || typeof endLineNumber !== 'number') {808throw new Error('Invalid arguments');809}810811this._sendRevealRange(812new Range(startLineNumber, 1, endLineNumber, 1),813verticalType,814false,815scrollType816);817}818819public revealRange(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth, revealVerticalInCenter: boolean = false, revealHorizontal: boolean = true): void {820this._revealRange(821range,822revealVerticalInCenter ? VerticalRevealType.Center : VerticalRevealType.Simple,823revealHorizontal,824scrollType825);826}827828public revealRangeInCenter(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {829this._revealRange(830range,831VerticalRevealType.Center,832true,833scrollType834);835}836837public revealRangeInCenterIfOutsideViewport(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {838this._revealRange(839range,840VerticalRevealType.CenterIfOutsideViewport,841true,842scrollType843);844}845846public revealRangeNearTop(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {847this._revealRange(848range,849VerticalRevealType.NearTop,850true,851scrollType852);853}854855public revealRangeNearTopIfOutsideViewport(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {856this._revealRange(857range,858VerticalRevealType.NearTopIfOutsideViewport,859true,860scrollType861);862}863864public revealRangeAtTop(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {865this._revealRange(866range,867VerticalRevealType.Top,868true,869scrollType870);871}872873private _revealRange(range: IRange, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {874if (!Range.isIRange(range)) {875throw new Error('Invalid arguments');876}877878this._sendRevealRange(879Range.lift(range),880verticalType,881revealHorizontal,882scrollType883);884}885886public setSelections(ranges: readonly ISelection[], source: string = 'api', reason = CursorChangeReason.NotSet): void {887if (!this._modelData) {888return;889}890if (!ranges || ranges.length === 0) {891throw new Error('Invalid arguments');892}893for (let i = 0, len = ranges.length; i < len; i++) {894if (!Selection.isISelection(ranges[i])) {895throw new Error('Invalid arguments');896}897}898this._modelData.viewModel.setSelections(source, ranges, reason);899}900901public getContentWidth(): number {902if (!this._modelData) {903return -1;904}905return this._modelData.viewModel.viewLayout.getContentWidth();906}907908public getScrollWidth(): number {909if (!this._modelData) {910return -1;911}912return this._modelData.viewModel.viewLayout.getScrollWidth();913}914public getScrollLeft(): number {915if (!this._modelData) {916return -1;917}918return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();919}920921public getContentHeight(): number {922if (!this._modelData) {923return -1;924}925return this._modelData.viewModel.viewLayout.getContentHeight();926}927928public getScrollHeight(): number {929if (!this._modelData) {930return -1;931}932return this._modelData.viewModel.viewLayout.getScrollHeight();933}934public getScrollTop(): number {935if (!this._modelData) {936return -1;937}938return this._modelData.viewModel.viewLayout.getCurrentScrollTop();939}940941public setScrollLeft(newScrollLeft: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {942if (!this._modelData) {943return;944}945if (typeof newScrollLeft !== 'number') {946throw new Error('Invalid arguments');947}948this._modelData.viewModel.viewLayout.setScrollPosition({949scrollLeft: newScrollLeft950}, scrollType);951}952public setScrollTop(newScrollTop: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {953if (!this._modelData) {954return;955}956if (typeof newScrollTop !== 'number') {957throw new Error('Invalid arguments');958}959this._modelData.viewModel.viewLayout.setScrollPosition({960scrollTop: newScrollTop961}, scrollType);962}963public setScrollPosition(position: editorCommon.INewScrollPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {964if (!this._modelData) {965return;966}967this._modelData.viewModel.viewLayout.setScrollPosition(position, scrollType);968}969public hasPendingScrollAnimation(): boolean {970if (!this._modelData) {971return false;972}973return this._modelData.viewModel.viewLayout.hasPendingScrollAnimation();974}975976public saveViewState(): editorCommon.ICodeEditorViewState | null {977if (!this._modelData) {978return null;979}980const contributionsState = this._contributions.saveViewState();981const cursorState = this._modelData.viewModel.saveCursorState();982const viewState = this._modelData.viewModel.saveState();983return {984cursorState: cursorState,985viewState: viewState,986contributionsState: contributionsState987};988}989990public restoreViewState(s: editorCommon.IEditorViewState | null): void {991if (!this._modelData || !this._modelData.hasRealView) {992return;993}994const codeEditorState = s as editorCommon.ICodeEditorViewState | null;995if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) {996const cursorState = <any>codeEditorState.cursorState;997if (Array.isArray(cursorState)) {998if (cursorState.length > 0) {999this._modelData.viewModel.restoreCursorState(<editorCommon.ICursorState[]>cursorState);1000}1001} else {1002// Backwards compatibility1003this._modelData.viewModel.restoreCursorState([<editorCommon.ICursorState>cursorState]);1004}10051006this._contributions.restoreViewState(codeEditorState.contributionsState || {});1007const reducedState = this._modelData.viewModel.reduceRestoreState(codeEditorState.viewState);1008this._modelData.view.restoreState(reducedState);1009}1010}10111012public handleInitialized(): void {1013this._getViewModel()?.visibleLinesStabilized();1014}10151016public onVisible(): void {1017this._modelData?.view.refreshFocusState();1018}10191020public onHide(): void {1021this._modelData?.view.refreshFocusState();1022this._focusTracker.refreshState();1023}10241025public getContribution<T extends editorCommon.IEditorContribution>(id: string): T | null {1026return this._contributions.get(id) as T | null;1027}10281029public getActions(): editorCommon.IEditorAction[] {1030return Array.from(this._actions.values());1031}10321033public getSupportedActions(): editorCommon.IEditorAction[] {1034let result = this.getActions();10351036result = result.filter(action => action.isSupported());10371038return result;1039}10401041public getAction(id: string): editorCommon.IEditorAction | null {1042return this._actions.get(id) || null;1043}10441045public trigger(source: string | null | undefined, handlerId: string, payload: any): void {1046payload = payload || {};10471048try {1049this._beginUpdate();10501051switch (handlerId) {1052case editorCommon.Handler.CompositionStart:1053this._startComposition();1054return;1055case editorCommon.Handler.CompositionEnd:1056this._endComposition(source);1057return;1058case editorCommon.Handler.Type: {1059const args = <Partial<editorCommon.TypePayload>>payload;1060this._type(source, args.text || '');1061return;1062}1063case editorCommon.Handler.ReplacePreviousChar: {1064const args = <Partial<editorCommon.ReplacePreviousCharPayload>>payload;1065this._compositionType(source, args.text || '', args.replaceCharCnt || 0, 0, 0);1066return;1067}1068case editorCommon.Handler.CompositionType: {1069const args = <Partial<editorCommon.CompositionTypePayload>>payload;1070this._compositionType(source, args.text || '', args.replacePrevCharCnt || 0, args.replaceNextCharCnt || 0, args.positionDelta || 0);1071return;1072}1073case editorCommon.Handler.Paste: {1074const args = <Partial<editorBrowser.PastePayload>>payload;1075this._paste(source, args.text || '', args.pasteOnNewLine || false, args.multicursorText || null, args.mode || null, args.clipboardEvent);1076return;1077}1078case editorCommon.Handler.Cut:1079this._cut(source);1080return;1081}10821083const action = this.getAction(handlerId);1084if (action) {1085Promise.resolve(action.run(payload)).then(undefined, onUnexpectedError);1086return;1087}10881089if (!this._modelData) {1090return;1091}10921093if (this._triggerEditorCommand(source, handlerId, payload)) {1094return;1095}10961097this._triggerCommand(handlerId, payload);1098} finally {1099this._endUpdate();1100}1101}11021103protected _triggerCommand(handlerId: string, payload: any): void {1104this._commandService.executeCommand(handlerId, payload);1105}11061107private _startComposition(): void {1108if (!this._modelData) {1109return;1110}1111this._modelData.viewModel.startComposition();1112this._onDidCompositionStart.fire();1113}11141115private _endComposition(source: string | null | undefined): void {1116if (!this._modelData) {1117return;1118}1119this._modelData.viewModel.endComposition(source);1120this._onDidCompositionEnd.fire();1121}11221123private _type(source: string | null | undefined, text: string): void {1124if (!this._modelData || text.length === 0) {1125return;1126}1127if (source === 'keyboard') {1128this._onWillType.fire(text);1129}1130this._modelData.viewModel.type(text, source);1131if (source === 'keyboard') {1132this._onDidType.fire(text);1133}1134}11351136private _compositionType(source: string | null | undefined, text: string, replacePrevCharCnt: number, replaceNextCharCnt: number, positionDelta: number): void {1137if (!this._modelData) {1138return;1139}1140this._modelData.viewModel.compositionType(text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source);1141}11421143private _paste(source: string | null | undefined, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null, clipboardEvent?: ClipboardEvent): void {1144if (!this._modelData) {1145return;1146}1147const viewModel = this._modelData.viewModel;1148const startPosition = viewModel.getSelection().getStartPosition();1149viewModel.paste(text, pasteOnNewLine, multicursorText, source);1150const endPosition = viewModel.getSelection().getStartPosition();1151if (source === 'keyboard') {1152this._onDidPaste.fire({1153clipboardEvent,1154range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),1155languageId: mode1156});1157}1158}11591160private _cut(source: string | null | undefined): void {1161if (!this._modelData) {1162return;1163}1164this._modelData.viewModel.cut(source);1165}11661167private _triggerEditorCommand(source: string | null | undefined, handlerId: string, payload: any): boolean {1168const command = EditorExtensionsRegistry.getEditorCommand(handlerId);1169if (command) {1170payload = payload || {};1171payload.source = source;1172this._instantiationService.invokeFunction((accessor) => {1173Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);1174});1175return true;1176}11771178return false;1179}11801181public _getViewModel(): IViewModel | null {1182if (!this._modelData) {1183return null;1184}1185return this._modelData.viewModel;1186}11871188public pushUndoStop(): boolean {1189if (!this._modelData) {1190return false;1191}1192if (this._configuration.options.get(EditorOption.readOnly)) {1193// read only editor => sorry!1194return false;1195}1196this._modelData.model.pushStackElement();1197return true;1198}11991200public popUndoStop(): boolean {1201if (!this._modelData) {1202return false;1203}1204if (this._configuration.options.get(EditorOption.readOnly)) {1205// read only editor => sorry!1206return false;1207}1208this._modelData.model.popStackElement();1209return true;1210}12111212public executeEdits(source: string | null | undefined, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean {1213if (!this._modelData) {1214return false;1215}1216if (this._configuration.options.get(EditorOption.readOnly)) {1217// read only editor => sorry!1218return false;1219}12201221let cursorStateComputer: ICursorStateComputer;1222if (!endCursorState) {1223cursorStateComputer = () => null;1224} else if (Array.isArray(endCursorState)) {1225cursorStateComputer = () => endCursorState;1226} else {1227cursorStateComputer = endCursorState;1228}12291230this._modelData.viewModel.executeEdits(source, edits, cursorStateComputer);1231return true;1232}12331234public executeCommand(source: string | null | undefined, command: editorCommon.ICommand): void {1235if (!this._modelData) {1236return;1237}1238this._modelData.viewModel.executeCommand(command, source);1239}12401241public executeCommands(source: string | null | undefined, commands: editorCommon.ICommand[]): void {1242if (!this._modelData) {1243return;1244}1245this._modelData.viewModel.executeCommands(commands, source);1246}12471248public createDecorationsCollection(decorations?: IModelDeltaDecoration[]): EditorDecorationsCollection {1249return new EditorDecorationsCollection(this, decorations);1250}12511252public changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {1253if (!this._modelData) {1254// callback will not be called1255return null;1256}1257return this._modelData.model.changeDecorations(callback, this._id);1258}12591260public getLineDecorations(lineNumber: number): IModelDecoration[] | null {1261if (!this._modelData) {1262return null;1263}1264return this._modelData.model.getLineDecorations(lineNumber, this._id, filterValidationDecorations(this._configuration.options));1265}12661267public getDecorationsInRange(range: Range): IModelDecoration[] | null {1268if (!this._modelData) {1269return null;1270}1271return this._modelData.model.getDecorationsInRange(range, this._id, filterValidationDecorations(this._configuration.options));1272}12731274/**1275* @deprecated1276*/1277public deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[] {1278if (!this._modelData) {1279return [];1280}12811282if (oldDecorations.length === 0 && newDecorations.length === 0) {1283return oldDecorations;1284}12851286return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);1287}12881289public removeDecorations(decorationIds: string[]): void {1290if (!this._modelData || decorationIds.length === 0) {1291return;1292}12931294this._modelData.model.changeDecorations((changeAccessor) => {1295changeAccessor.deltaDecorations(decorationIds, []);1296});1297}12981299public setDecorationsByType(description: string, decorationTypeKey: string, decorationOptions: editorCommon.IDecorationOptions[]): void {13001301const newDecorationsSubTypes: { [key: string]: boolean } = {};1302const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};1303this._decorationTypeSubtypes[decorationTypeKey] = newDecorationsSubTypes;13041305const newModelDecorations: IModelDeltaDecoration[] = [];13061307for (const decorationOption of decorationOptions) {1308let typeKey = decorationTypeKey;1309if (decorationOption.renderOptions) {1310// identify custom render options by a hash code over all keys and values1311// For custom render options register a decoration type if necessary1312const subType = hash(decorationOption.renderOptions).toString(16);1313// The fact that `decorationTypeKey` appears in the typeKey has no influence1314// it is just a mechanism to get predictable and unique keys (repeatable for the same options and unique across clients)1315typeKey = decorationTypeKey + '-' + subType;1316if (!oldDecorationsSubTypes[subType] && !newDecorationsSubTypes[subType]) {1317// decoration type did not exist before, register new one1318this._registerDecorationType(description, typeKey, decorationOption.renderOptions, decorationTypeKey);1319}1320newDecorationsSubTypes[subType] = true;1321}1322const opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage);1323if (decorationOption.hoverMessage) {1324opts.hoverMessage = decorationOption.hoverMessage;1325}1326newModelDecorations.push({ range: decorationOption.range, options: opts });1327}13281329// remove decoration sub types that are no longer used, deregister decoration type if necessary1330for (const subType in oldDecorationsSubTypes) {1331if (!newDecorationsSubTypes[subType]) {1332this._removeDecorationType(decorationTypeKey + '-' + subType);1333}1334}13351336// update all decorations1337const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];1338this.changeDecorations(accessor => this._decorationTypeKeysToIds[decorationTypeKey] = accessor.deltaDecorations(oldDecorationsIds, newModelDecorations));1339}13401341public setDecorationsByTypeFast(decorationTypeKey: string, ranges: IRange[]): void {13421343// remove decoration sub types that are no longer used, deregister decoration type if necessary1344const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};1345for (const subType in oldDecorationsSubTypes) {1346this._removeDecorationType(decorationTypeKey + '-' + subType);1347}1348this._decorationTypeSubtypes[decorationTypeKey] = {};13491350const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false));1351const newModelDecorations: IModelDeltaDecoration[] = new Array<IModelDeltaDecoration>(ranges.length);1352for (let i = 0, len = ranges.length; i < len; i++) {1353newModelDecorations[i] = { range: ranges[i], options: opts };1354}13551356// update all decorations1357const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];1358this.changeDecorations(accessor => this._decorationTypeKeysToIds[decorationTypeKey] = accessor.deltaDecorations(oldDecorationsIds, newModelDecorations));1359}13601361public removeDecorationsByType(decorationTypeKey: string): void {1362// remove decorations for type and sub type1363const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];1364if (oldDecorationsIds) {1365this.changeDecorations(accessor => accessor.deltaDecorations(oldDecorationsIds, []));1366}1367if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {1368delete this._decorationTypeKeysToIds[decorationTypeKey];1369}1370if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {1371delete this._decorationTypeSubtypes[decorationTypeKey];1372}1373}13741375public getLayoutInfo(): EditorLayoutInfo {1376const options = this._configuration.options;1377const layoutInfo = options.get(EditorOption.layoutInfo);1378return layoutInfo;1379}13801381public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler | null {1382if (!this._modelData || !this._modelData.hasRealView) {1383return null;1384}1385return this._modelData.view.createOverviewRuler(cssClassName);1386}13871388public getContainerDomNode(): HTMLElement {1389return this._domElement;1390}13911392public getDomNode(): HTMLElement | null {1393if (!this._modelData || !this._modelData.hasRealView) {1394return null;1395}1396return this._modelData.view.domNode.domNode;1397}13981399public delegateVerticalScrollbarPointerDown(browserEvent: PointerEvent): void {1400if (!this._modelData || !this._modelData.hasRealView) {1401return;1402}1403this._modelData.view.delegateVerticalScrollbarPointerDown(browserEvent);1404}14051406public delegateScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) {1407if (!this._modelData || !this._modelData.hasRealView) {1408return;1409}1410this._modelData.view.delegateScrollFromMouseWheelEvent(browserEvent);1411}14121413public layout(dimension?: IDimension, postponeRendering: boolean = false): void {1414this._configuration.observeContainer(dimension);1415if (!postponeRendering) {1416this.render();1417}1418}14191420public focus(): void {1421if (!this._modelData || !this._modelData.hasRealView) {1422return;1423}1424this._modelData.view.focus();1425}14261427public hasTextFocus(): boolean {1428if (!this._modelData || !this._modelData.hasRealView) {1429return false;1430}1431return this._modelData.view.isFocused();1432}14331434public hasWidgetFocus(): boolean {1435return this._focusTracker && this._focusTracker.hasFocus();1436}14371438public addContentWidget(widget: editorBrowser.IContentWidget): void {1439const widgetData: IContentWidgetData = {1440widget: widget,1441position: widget.getPosition()1442};14431444if (this._contentWidgets.hasOwnProperty(widget.getId())) {1445console.warn('Overwriting a content widget with the same id:' + widget.getId());1446}14471448this._contentWidgets[widget.getId()] = widgetData;14491450if (this._modelData && this._modelData.hasRealView) {1451this._modelData.view.addContentWidget(widgetData);1452}1453}14541455public layoutContentWidget(widget: editorBrowser.IContentWidget): void {1456const widgetId = widget.getId();1457if (this._contentWidgets.hasOwnProperty(widgetId)) {1458const widgetData = this._contentWidgets[widgetId];1459widgetData.position = widget.getPosition();1460if (this._modelData && this._modelData.hasRealView) {1461this._modelData.view.layoutContentWidget(widgetData);1462}1463}1464}14651466public removeContentWidget(widget: editorBrowser.IContentWidget): void {1467const widgetId = widget.getId();1468if (this._contentWidgets.hasOwnProperty(widgetId)) {1469const widgetData = this._contentWidgets[widgetId];1470delete this._contentWidgets[widgetId];1471if (this._modelData && this._modelData.hasRealView) {1472this._modelData.view.removeContentWidget(widgetData);1473}1474}1475}14761477public addOverlayWidget(widget: editorBrowser.IOverlayWidget): void {1478const widgetData: IOverlayWidgetData = {1479widget: widget,1480position: widget.getPosition()1481};14821483if (this._overlayWidgets.hasOwnProperty(widget.getId())) {1484console.warn('Overwriting an overlay widget with the same id.');1485}14861487this._overlayWidgets[widget.getId()] = widgetData;1488if (this._modelData && this._modelData.hasRealView) {1489this._modelData.view.addOverlayWidget(widgetData);1490}1491}14921493public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void {1494const widgetId = widget.getId();1495if (this._overlayWidgets.hasOwnProperty(widgetId)) {1496const widgetData = this._overlayWidgets[widgetId];1497widgetData.position = widget.getPosition();1498if (this._modelData && this._modelData.hasRealView) {1499this._modelData.view.layoutOverlayWidget(widgetData);1500}1501}1502}15031504public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void {1505const widgetId = widget.getId();1506if (this._overlayWidgets.hasOwnProperty(widgetId)) {1507const widgetData = this._overlayWidgets[widgetId];1508delete this._overlayWidgets[widgetId];1509if (this._modelData && this._modelData.hasRealView) {1510this._modelData.view.removeOverlayWidget(widgetData);1511}1512}1513}15141515public addGlyphMarginWidget(widget: editorBrowser.IGlyphMarginWidget): void {1516const widgetData: IGlyphMarginWidgetData = {1517widget: widget,1518position: widget.getPosition()1519};15201521if (this._glyphMarginWidgets.hasOwnProperty(widget.getId())) {1522console.warn('Overwriting a glyph margin widget with the same id.');1523}15241525this._glyphMarginWidgets[widget.getId()] = widgetData;15261527if (this._modelData && this._modelData.hasRealView) {1528this._modelData.view.addGlyphMarginWidget(widgetData);1529}1530}15311532public layoutGlyphMarginWidget(widget: editorBrowser.IGlyphMarginWidget): void {1533const widgetId = widget.getId();1534if (this._glyphMarginWidgets.hasOwnProperty(widgetId)) {1535const widgetData = this._glyphMarginWidgets[widgetId];1536widgetData.position = widget.getPosition();1537if (this._modelData && this._modelData.hasRealView) {1538this._modelData.view.layoutGlyphMarginWidget(widgetData);1539}1540}1541}15421543public removeGlyphMarginWidget(widget: editorBrowser.IGlyphMarginWidget): void {1544const widgetId = widget.getId();1545if (this._glyphMarginWidgets.hasOwnProperty(widgetId)) {1546const widgetData = this._glyphMarginWidgets[widgetId];1547delete this._glyphMarginWidgets[widgetId];1548if (this._modelData && this._modelData.hasRealView) {1549this._modelData.view.removeGlyphMarginWidget(widgetData);1550}1551}1552}15531554public changeViewZones(callback: (accessor: editorBrowser.IViewZoneChangeAccessor) => void): void {1555if (!this._modelData || !this._modelData.hasRealView) {1556return;1557}1558this._modelData.view.change(callback);1559}15601561public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {1562if (!this._modelData || !this._modelData.hasRealView) {1563return null;1564}1565return this._modelData.view.getTargetAtClientPoint(clientX, clientY);1566}15671568public getScrolledVisiblePosition(rawPosition: IPosition): { top: number; left: number; height: number } | null {1569if (!this._modelData || !this._modelData.hasRealView) {1570return null;1571}15721573const position = this._modelData.model.validatePosition(rawPosition);1574const options = this._configuration.options;1575const layoutInfo = options.get(EditorOption.layoutInfo);15761577const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop();1578const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft();15791580return {1581top: top,1582left: left,1583height: options.get(EditorOption.lineHeight)1584};1585}15861587public getOffsetForColumn(lineNumber: number, column: number): number {1588if (!this._modelData || !this._modelData.hasRealView) {1589return -1;1590}1591return this._modelData.view.getOffsetForColumn(lineNumber, column);1592}15931594public render(forceRedraw: boolean = false): void {1595if (!this._modelData || !this._modelData.hasRealView) {1596return;1597}1598this._modelData.viewModel.batchEvents(() => {1599this._modelData!.view.render(true, forceRedraw);1600});1601}16021603public setAriaOptions(options: editorBrowser.IEditorAriaOptions): void {1604if (!this._modelData || !this._modelData.hasRealView) {1605return;1606}1607this._modelData.view.setAriaOptions(options);1608}16091610public applyFontInfo(target: HTMLElement): void {1611applyFontInfo(target, this._configuration.options.get(EditorOption.fontInfo));1612}16131614public setBanner(domNode: HTMLElement | null, domNodeHeight: number): void {1615if (this._bannerDomNode && this._domElement.contains(this._bannerDomNode)) {1616this._bannerDomNode.remove();1617}16181619this._bannerDomNode = domNode;1620this._configuration.setReservedHeight(domNode ? domNodeHeight : 0);16211622if (this._bannerDomNode) {1623this._domElement.prepend(this._bannerDomNode);1624}1625}16261627protected _attachModel(model: ITextModel | null): void {1628if (!model) {1629this._modelData = null;1630return;1631}16321633const listenersToRemove: IDisposable[] = [];16341635this._domElement.setAttribute('data-mode-id', model.getLanguageId());1636this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());1637this._configuration.setModelLineCount(model.getLineCount());16381639const attachedView = model.onBeforeAttached();16401641const viewModel = new ViewModel(1642this._id,1643this._configuration,1644model,1645DOMLineBreaksComputerFactory.create(dom.getWindow(this._domElement)),1646MonospaceLineBreaksComputerFactory.create(this._configuration.options),1647(callback) => dom.scheduleAtNextAnimationFrame(dom.getWindow(this._domElement), callback),1648this.languageConfigurationService,1649this._themeService,1650attachedView,1651{1652batchChanges: (cb) => {1653try {1654this._beginUpdate();1655return cb();1656} finally {1657this._endUpdate();1658}1659},1660}1661);16621663// Someone might destroy the model from under the editor, so prevent any exceptions by setting a null model1664listenersToRemove.push(model.onWillDispose(() => this.setModel(null)));16651666listenersToRemove.push(viewModel.onEvent((e) => {1667switch (e.kind) {1668case OutgoingViewModelEventKind.ContentSizeChanged:1669this._onDidContentSizeChange.fire(e);1670break;1671case OutgoingViewModelEventKind.FocusChanged:1672this._editorTextFocus.setValue(e.hasFocus);1673break;1674case OutgoingViewModelEventKind.ScrollChanged:1675this._onDidScrollChange.fire(e);1676break;1677case OutgoingViewModelEventKind.ViewZonesChanged:1678this._onDidChangeViewZones.fire();1679break;1680case OutgoingViewModelEventKind.HiddenAreasChanged:1681this._onDidChangeHiddenAreas.fire();1682break;1683case OutgoingViewModelEventKind.ReadOnlyEditAttempt:1684this._onDidAttemptReadOnlyEdit.fire();1685break;1686case OutgoingViewModelEventKind.CursorStateChanged: {1687if (e.reachedMaxCursorCount) {16881689const multiCursorLimit = this.getOption(EditorOption.multiCursorLimit);1690const message = nls.localize('cursors.maximum', "The number of cursors has been limited to {0}. Consider using [find and replace](https://code.visualstudio.com/docs/editor/codebasics#_find-and-replace) for larger changes or increase the editor multi cursor limit setting.", multiCursorLimit);1691this._notificationService.prompt(Severity.Warning, message, [1692{1693label: 'Find and Replace',1694run: () => {1695this._commandService.executeCommand('editor.action.startFindReplaceAction');1696}1697},1698{1699label: nls.localize('goToSetting', 'Increase Multi Cursor Limit'),1700run: () => {1701this._commandService.executeCommand('workbench.action.openSettings2', {1702query: 'editor.multiCursorLimit'1703});1704}1705}1706]);1707}17081709const positions: Position[] = [];1710for (let i = 0, len = e.selections.length; i < len; i++) {1711positions[i] = e.selections[i].getPosition();1712}17131714const e1: ICursorPositionChangedEvent = {1715position: positions[0],1716secondaryPositions: positions.slice(1),1717reason: e.reason,1718source: e.source1719};1720this._onDidChangeCursorPosition.fire(e1);17211722const e2: ICursorSelectionChangedEvent = {1723selection: e.selections[0],1724secondarySelections: e.selections.slice(1),1725modelVersionId: e.modelVersionId,1726oldSelections: e.oldSelections,1727oldModelVersionId: e.oldModelVersionId,1728source: e.source,1729reason: e.reason1730};1731this._onDidChangeCursorSelection.fire(e2);17321733break;1734}1735case OutgoingViewModelEventKind.ModelDecorationsChanged:1736this._onDidChangeModelDecorations.fire(e.event);1737break;1738case OutgoingViewModelEventKind.ModelLanguageChanged:1739this._domElement.setAttribute('data-mode-id', model.getLanguageId());1740this._onDidChangeModelLanguage.fire(e.event);1741break;1742case OutgoingViewModelEventKind.ModelLanguageConfigurationChanged:1743this._onDidChangeModelLanguageConfiguration.fire(e.event);1744break;1745case OutgoingViewModelEventKind.ModelContentChanged:1746this._onDidChangeModelContent.fire(e.event);1747break;1748case OutgoingViewModelEventKind.ModelOptionsChanged:1749this._onDidChangeModelOptions.fire(e.event);1750break;1751case OutgoingViewModelEventKind.ModelTokensChanged:1752this._onDidChangeModelTokens.fire(e.event);1753break;17541755}1756}));17571758const [view, hasRealView] = this._createView(viewModel);1759if (hasRealView) {1760this._domElement.appendChild(view.domNode.domNode);17611762let keys = Object.keys(this._contentWidgets);1763for (let i = 0, len = keys.length; i < len; i++) {1764const widgetId = keys[i];1765view.addContentWidget(this._contentWidgets[widgetId]);1766}17671768keys = Object.keys(this._overlayWidgets);1769for (let i = 0, len = keys.length; i < len; i++) {1770const widgetId = keys[i];1771view.addOverlayWidget(this._overlayWidgets[widgetId]);1772}17731774keys = Object.keys(this._glyphMarginWidgets);1775for (let i = 0, len = keys.length; i < len; i++) {1776const widgetId = keys[i];1777view.addGlyphMarginWidget(this._glyphMarginWidgets[widgetId]);1778}17791780view.render(false, true);1781view.domNode.domNode.setAttribute('data-uri', model.uri.toString());1782}17831784this._modelData = new ModelData(model, viewModel, view, hasRealView, listenersToRemove, attachedView);1785}17861787protected _createView(viewModel: ViewModel): [View, boolean] {1788let commandDelegate: ICommandDelegate;1789if (this.isSimpleWidget) {1790commandDelegate = {1791paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {1792this._paste('keyboard', text, pasteOnNewLine, multicursorText, mode);1793},1794type: (text: string) => {1795this._type('keyboard', text);1796},1797compositionType: (text: string, replacePrevCharCnt: number, replaceNextCharCnt: number, positionDelta: number) => {1798this._compositionType('keyboard', text, replacePrevCharCnt, replaceNextCharCnt, positionDelta);1799},1800startComposition: () => {1801this._startComposition();1802},1803endComposition: () => {1804this._endComposition('keyboard');1805},1806cut: () => {1807this._cut('keyboard');1808}1809};1810} else {1811commandDelegate = {1812paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {1813const payload: editorBrowser.PastePayload = { text, pasteOnNewLine, multicursorText, mode };1814this._commandService.executeCommand(editorCommon.Handler.Paste, payload);1815},1816type: (text: string) => {1817const payload: editorCommon.TypePayload = { text };1818this._commandService.executeCommand(editorCommon.Handler.Type, payload);1819},1820compositionType: (text: string, replacePrevCharCnt: number, replaceNextCharCnt: number, positionDelta: number) => {1821// Try if possible to go through the existing `replacePreviousChar` command1822if (replaceNextCharCnt || positionDelta) {1823// must be handled through the new command1824const payload: editorCommon.CompositionTypePayload = { text, replacePrevCharCnt, replaceNextCharCnt, positionDelta };1825this._commandService.executeCommand(editorCommon.Handler.CompositionType, payload);1826} else {1827const payload: editorCommon.ReplacePreviousCharPayload = { text, replaceCharCnt: replacePrevCharCnt };1828this._commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, payload);1829}1830},1831startComposition: () => {1832this._commandService.executeCommand(editorCommon.Handler.CompositionStart, {});1833},1834endComposition: () => {1835this._commandService.executeCommand(editorCommon.Handler.CompositionEnd, {});1836},1837cut: () => {1838this._commandService.executeCommand(editorCommon.Handler.Cut, {});1839}1840};1841}18421843const viewUserInputEvents = new ViewUserInputEvents(viewModel.coordinatesConverter);1844viewUserInputEvents.onKeyDown = (e) => this._onKeyDown.fire(e);1845viewUserInputEvents.onKeyUp = (e) => this._onKeyUp.fire(e);1846viewUserInputEvents.onContextMenu = (e) => this._onContextMenu.fire(e);1847viewUserInputEvents.onMouseMove = (e) => this._onMouseMove.fire(e);1848viewUserInputEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);1849viewUserInputEvents.onMouseDown = (e) => this._onMouseDown.fire(e);1850viewUserInputEvents.onMouseUp = (e) => this._onMouseUp.fire(e);1851viewUserInputEvents.onMouseDrag = (e) => this._onMouseDrag.fire(e);1852viewUserInputEvents.onMouseDrop = (e) => this._onMouseDrop.fire(e);1853viewUserInputEvents.onMouseDropCanceled = (e) => this._onMouseDropCanceled.fire(e);1854viewUserInputEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);18551856const view = new View(1857commandDelegate,1858this._configuration,1859this._themeService.getColorTheme(),1860viewModel,1861viewUserInputEvents,1862this._overflowWidgetsDomNode,1863this._instantiationService1864);18651866return [view, true];1867}18681869protected _postDetachModelCleanup(detachedModel: ITextModel | null): void {1870detachedModel?.removeAllDecorationsWithOwnerId(this._id);1871}18721873private _detachModel(): ITextModel | null {1874this._contributionsDisposable?.dispose();1875this._contributionsDisposable = undefined;1876if (!this._modelData) {1877return null;1878}1879const model = this._modelData.model;1880const removeDomNode = this._modelData.hasRealView ? this._modelData.view.domNode.domNode : null;18811882this._modelData.dispose();1883this._modelData = null;18841885this._domElement.removeAttribute('data-mode-id');1886if (removeDomNode && this._domElement.contains(removeDomNode)) {1887removeDomNode.remove();1888}1889if (this._bannerDomNode && this._domElement.contains(this._bannerDomNode)) {1890this._bannerDomNode.remove();1891}1892return model;1893}18941895private _registerDecorationType(description: string, key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void {1896this._codeEditorService.registerDecorationType(description, key, options, parentTypeKey, this);1897}18981899private _removeDecorationType(key: string): void {1900this._codeEditorService.removeDecorationType(key);1901}19021903private _resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions {1904return this._codeEditorService.resolveDecorationOptions(typeKey, writable);1905}19061907public getTelemetryData(): { [key: string]: any } | undefined {1908return this._telemetryData;1909}19101911public hasModel(): this is editorBrowser.IActiveCodeEditor {1912return (this._modelData !== null);1913}19141915private showDropIndicatorAt(position: Position): void {1916const newDecorations: IModelDeltaDecoration[] = [{1917range: new Range(position.lineNumber, position.column, position.lineNumber, position.column),1918options: CodeEditorWidget.dropIntoEditorDecorationOptions1919}];19201921this._dropIntoEditorDecorations.set(newDecorations);1922this.revealPosition(position, editorCommon.ScrollType.Immediate);1923}19241925private removeDropIndicator(): void {1926this._dropIntoEditorDecorations.clear();1927}19281929public setContextValue(key: string, value: ContextKeyValue): void {1930this._contextKeyService.createKey(key, value);1931}19321933private _beginUpdate(): void {1934this._updateCounter++;1935if (this._updateCounter === 1) {1936this._onBeginUpdate.fire();1937}1938}19391940private _endUpdate(): void {1941this._updateCounter--;1942if (this._updateCounter === 0) {1943this._onEndUpdate.fire();1944}1945}1946}19471948let EDITOR_ID = 0;19491950export interface ICodeEditorWidgetOptions {1951/**1952* Is this a simple widget (not a real code editor)?1953* Defaults to false.1954*/1955isSimpleWidget?: boolean;19561957/**1958* Contributions to instantiate.1959* When provided, only the contributions included will be instantiated.1960* To include the defaults, those must be provided as well via [...EditorExtensionsRegistry.getEditorContributions()]1961* Defaults to EditorExtensionsRegistry.getEditorContributions().1962*/1963contributions?: IEditorContributionDescription[];19641965/**1966* Telemetry data associated with this CodeEditorWidget.1967* Defaults to null.1968*/1969telemetryData?: object;19701971/**1972* The ID of the context menu.1973* Defaults to MenuId.SimpleEditorContext or MenuId.EditorContext depending on whether the widget is simple.1974*/1975contextMenuId?: MenuId;1976}19771978class ModelData {1979constructor(1980public readonly model: ITextModel,1981public readonly viewModel: ViewModel,1982public readonly view: View,1983public readonly hasRealView: boolean,1984public readonly listenersToRemove: IDisposable[],1985public readonly attachedView: IAttachedView,1986) {1987}19881989public dispose(): void {1990dispose(this.listenersToRemove);1991this.model.onBeforeDetached(this.attachedView);1992if (this.hasRealView) {1993this.view.dispose();1994}1995this.viewModel.dispose();1996}1997}19981999const enum BooleanEventValue {2000NotSet,2001False,2002True2003}20042005export class BooleanEventEmitter extends Disposable {2006private readonly _onDidChangeToTrue: Emitter<void> = this._register(new Emitter<void>(this._emitterOptions));2007public readonly onDidChangeToTrue: Event<void> = this._onDidChangeToTrue.event;20082009private readonly _onDidChangeToFalse: Emitter<void> = this._register(new Emitter<void>(this._emitterOptions));2010public readonly onDidChangeToFalse: Event<void> = this._onDidChangeToFalse.event;20112012private _value: BooleanEventValue;20132014constructor(2015private readonly _emitterOptions: EmitterOptions2016) {2017super();2018this._value = BooleanEventValue.NotSet;2019}20202021public setValue(_value: boolean) {2022const value = (_value ? BooleanEventValue.True : BooleanEventValue.False);2023if (this._value === value) {2024return;2025}2026this._value = value;2027if (this._value === BooleanEventValue.True) {2028this._onDidChangeToTrue.fire();2029} else if (this._value === BooleanEventValue.False) {2030this._onDidChangeToFalse.fire();2031}2032}2033}20342035/**2036* A regular event emitter that also makes sure contributions are instantiated if necessary2037*/2038class InteractionEmitter<T> extends Emitter<T> {20392040constructor(2041private readonly _contributions: CodeEditorContributions,2042deliveryQueue: EventDeliveryQueue2043) {2044super({ deliveryQueue });2045}20462047override fire(event: T): void {2048this._contributions.onBeforeInteractionEvent();2049super.fire(event);2050}2051}20522053class EditorContextKeysManager extends Disposable {20542055private readonly _editor: CodeEditorWidget;2056private readonly _editorSimpleInput: IContextKey<boolean>;2057private readonly _editorFocus: IContextKey<boolean>;2058private readonly _textInputFocus: IContextKey<boolean>;2059private readonly _editorTextFocus: IContextKey<boolean>;2060private readonly _tabMovesFocus: IContextKey<boolean>;2061private readonly _editorReadonly: IContextKey<boolean>;2062private readonly _inDiffEditor: IContextKey<boolean>;2063private readonly _editorColumnSelection: IContextKey<boolean>;2064private readonly _hasMultipleSelections: IContextKey<boolean>;2065private readonly _hasNonEmptySelection: IContextKey<boolean>;2066private readonly _canUndo: IContextKey<boolean>;2067private readonly _canRedo: IContextKey<boolean>;20682069constructor(2070editor: CodeEditorWidget,2071contextKeyService: IContextKeyService2072) {2073super();20742075this._editor = editor;20762077contextKeyService.createKey('editorId', editor.getId());20782079this._editorSimpleInput = EditorContextKeys.editorSimpleInput.bindTo(contextKeyService);2080this._editorFocus = EditorContextKeys.focus.bindTo(contextKeyService);2081this._textInputFocus = EditorContextKeys.textInputFocus.bindTo(contextKeyService);2082this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService);2083this._tabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService);2084this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService);2085this._inDiffEditor = EditorContextKeys.inDiffEditor.bindTo(contextKeyService);2086this._editorColumnSelection = EditorContextKeys.columnSelection.bindTo(contextKeyService);2087this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);2088this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);2089this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);2090this._canRedo = EditorContextKeys.canRedo.bindTo(contextKeyService);20912092this._register(this._editor.onDidChangeConfiguration(() => this._updateFromConfig()));2093this._register(this._editor.onDidChangeCursorSelection(() => this._updateFromSelection()));2094this._register(this._editor.onDidFocusEditorWidget(() => this._updateFromFocus()));2095this._register(this._editor.onDidBlurEditorWidget(() => this._updateFromFocus()));2096this._register(this._editor.onDidFocusEditorText(() => this._updateFromFocus()));2097this._register(this._editor.onDidBlurEditorText(() => this._updateFromFocus()));2098this._register(this._editor.onDidChangeModel(() => this._updateFromModel()));2099this._register(this._editor.onDidChangeConfiguration(() => this._updateFromModel()));2100this._register(TabFocus.onDidChangeTabFocus((tabFocusMode: boolean) => this._tabMovesFocus.set(tabFocusMode)));21012102this._updateFromConfig();2103this._updateFromSelection();2104this._updateFromFocus();2105this._updateFromModel();21062107this._editorSimpleInput.set(this._editor.isSimpleWidget);2108}21092110private _updateFromConfig(): void {2111const options = this._editor.getOptions();21122113this._tabMovesFocus.set(TabFocus.getTabFocusMode());2114this._editorReadonly.set(options.get(EditorOption.readOnly));2115this._inDiffEditor.set(options.get(EditorOption.inDiffEditor));2116this._editorColumnSelection.set(options.get(EditorOption.columnSelection));2117}21182119private _updateFromSelection(): void {2120const selections = this._editor.getSelections();2121if (!selections) {2122this._hasMultipleSelections.reset();2123this._hasNonEmptySelection.reset();2124} else {2125this._hasMultipleSelections.set(selections.length > 1);2126this._hasNonEmptySelection.set(selections.some(s => !s.isEmpty()));2127}2128}21292130private _updateFromFocus(): void {2131this._editorFocus.set(this._editor.hasWidgetFocus() && !this._editor.isSimpleWidget);2132this._editorTextFocus.set(this._editor.hasTextFocus() && !this._editor.isSimpleWidget);2133this._textInputFocus.set(this._editor.hasTextFocus());2134}21352136private _updateFromModel(): void {2137const model = this._editor.getModel();2138this._canUndo.set(Boolean(model && model.canUndo()));2139this._canRedo.set(Boolean(model && model.canRedo()));2140}2141}21422143export class EditorModeContext extends Disposable {21442145private readonly _langId: IContextKey<string>;2146private readonly _hasCompletionItemProvider: IContextKey<boolean>;2147private readonly _hasCodeActionsProvider: IContextKey<boolean>;2148private readonly _hasCodeLensProvider: IContextKey<boolean>;2149private readonly _hasDefinitionProvider: IContextKey<boolean>;2150private readonly _hasDeclarationProvider: IContextKey<boolean>;2151private readonly _hasImplementationProvider: IContextKey<boolean>;2152private readonly _hasTypeDefinitionProvider: IContextKey<boolean>;2153private readonly _hasHoverProvider: IContextKey<boolean>;2154private readonly _hasDocumentHighlightProvider: IContextKey<boolean>;2155private readonly _hasDocumentSymbolProvider: IContextKey<boolean>;2156private readonly _hasReferenceProvider: IContextKey<boolean>;2157private readonly _hasRenameProvider: IContextKey<boolean>;2158private readonly _hasDocumentFormattingProvider: IContextKey<boolean>;2159private readonly _hasDocumentSelectionFormattingProvider: IContextKey<boolean>;2160private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;2161private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;2162private readonly _hasSignatureHelpProvider: IContextKey<boolean>;2163private readonly _hasInlayHintsProvider: IContextKey<boolean>;2164private readonly _isInEmbeddedEditor: IContextKey<boolean>;21652166constructor(2167private readonly _editor: CodeEditorWidget,2168private readonly _contextKeyService: IContextKeyService,2169private readonly _languageFeaturesService: ILanguageFeaturesService,2170) {2171super();21722173this._langId = EditorContextKeys.languageId.bindTo(_contextKeyService);2174this._hasCompletionItemProvider = EditorContextKeys.hasCompletionItemProvider.bindTo(_contextKeyService);2175this._hasCodeActionsProvider = EditorContextKeys.hasCodeActionsProvider.bindTo(_contextKeyService);2176this._hasCodeLensProvider = EditorContextKeys.hasCodeLensProvider.bindTo(_contextKeyService);2177this._hasDefinitionProvider = EditorContextKeys.hasDefinitionProvider.bindTo(_contextKeyService);2178this._hasDeclarationProvider = EditorContextKeys.hasDeclarationProvider.bindTo(_contextKeyService);2179this._hasImplementationProvider = EditorContextKeys.hasImplementationProvider.bindTo(_contextKeyService);2180this._hasTypeDefinitionProvider = EditorContextKeys.hasTypeDefinitionProvider.bindTo(_contextKeyService);2181this._hasHoverProvider = EditorContextKeys.hasHoverProvider.bindTo(_contextKeyService);2182this._hasDocumentHighlightProvider = EditorContextKeys.hasDocumentHighlightProvider.bindTo(_contextKeyService);2183this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(_contextKeyService);2184this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(_contextKeyService);2185this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(_contextKeyService);2186this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(_contextKeyService);2187this._hasInlayHintsProvider = EditorContextKeys.hasInlayHintsProvider.bindTo(_contextKeyService);2188this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(_contextKeyService);2189this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);2190this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);2191this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);2192this._isInEmbeddedEditor = EditorContextKeys.isInEmbeddedEditor.bindTo(_contextKeyService);21932194const update = () => this._update();21952196// update when model/mode changes2197this._register(_editor.onDidChangeModel(update));2198this._register(_editor.onDidChangeModelLanguage(update));21992200// update when registries change2201this._register(_languageFeaturesService.completionProvider.onDidChange(update));2202this._register(_languageFeaturesService.codeActionProvider.onDidChange(update));2203this._register(_languageFeaturesService.codeLensProvider.onDidChange(update));2204this._register(_languageFeaturesService.definitionProvider.onDidChange(update));2205this._register(_languageFeaturesService.declarationProvider.onDidChange(update));2206this._register(_languageFeaturesService.implementationProvider.onDidChange(update));2207this._register(_languageFeaturesService.typeDefinitionProvider.onDidChange(update));2208this._register(_languageFeaturesService.hoverProvider.onDidChange(update));2209this._register(_languageFeaturesService.documentHighlightProvider.onDidChange(update));2210this._register(_languageFeaturesService.documentSymbolProvider.onDidChange(update));2211this._register(_languageFeaturesService.referenceProvider.onDidChange(update));2212this._register(_languageFeaturesService.renameProvider.onDidChange(update));2213this._register(_languageFeaturesService.documentFormattingEditProvider.onDidChange(update));2214this._register(_languageFeaturesService.documentRangeFormattingEditProvider.onDidChange(update));2215this._register(_languageFeaturesService.signatureHelpProvider.onDidChange(update));2216this._register(_languageFeaturesService.inlayHintsProvider.onDidChange(update));22172218update();2219}22202221override dispose() {2222super.dispose();2223}22242225reset() {2226this._contextKeyService.bufferChangeEvents(() => {2227this._langId.reset();2228this._hasCompletionItemProvider.reset();2229this._hasCodeActionsProvider.reset();2230this._hasCodeLensProvider.reset();2231this._hasDefinitionProvider.reset();2232this._hasDeclarationProvider.reset();2233this._hasImplementationProvider.reset();2234this._hasTypeDefinitionProvider.reset();2235this._hasHoverProvider.reset();2236this._hasDocumentHighlightProvider.reset();2237this._hasDocumentSymbolProvider.reset();2238this._hasReferenceProvider.reset();2239this._hasRenameProvider.reset();2240this._hasDocumentFormattingProvider.reset();2241this._hasDocumentSelectionFormattingProvider.reset();2242this._hasSignatureHelpProvider.reset();2243this._isInEmbeddedEditor.reset();2244});2245}22462247private _update() {2248const model = this._editor.getModel();2249if (!model) {2250this.reset();2251return;2252}2253this._contextKeyService.bufferChangeEvents(() => {2254this._langId.set(model.getLanguageId());2255this._hasCompletionItemProvider.set(this._languageFeaturesService.completionProvider.has(model));2256this._hasCodeActionsProvider.set(this._languageFeaturesService.codeActionProvider.has(model));2257this._hasCodeLensProvider.set(this._languageFeaturesService.codeLensProvider.has(model));2258this._hasDefinitionProvider.set(this._languageFeaturesService.definitionProvider.has(model));2259this._hasDeclarationProvider.set(this._languageFeaturesService.declarationProvider.has(model));2260this._hasImplementationProvider.set(this._languageFeaturesService.implementationProvider.has(model));2261this._hasTypeDefinitionProvider.set(this._languageFeaturesService.typeDefinitionProvider.has(model));2262this._hasHoverProvider.set(this._languageFeaturesService.hoverProvider.has(model));2263this._hasDocumentHighlightProvider.set(this._languageFeaturesService.documentHighlightProvider.has(model));2264this._hasDocumentSymbolProvider.set(this._languageFeaturesService.documentSymbolProvider.has(model));2265this._hasReferenceProvider.set(this._languageFeaturesService.referenceProvider.has(model));2266this._hasRenameProvider.set(this._languageFeaturesService.renameProvider.has(model));2267this._hasSignatureHelpProvider.set(this._languageFeaturesService.signatureHelpProvider.has(model));2268this._hasInlayHintsProvider.set(this._languageFeaturesService.inlayHintsProvider.has(model));2269this._hasDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.has(model) || this._languageFeaturesService.documentRangeFormattingEditProvider.has(model));2270this._hasDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.has(model));2271this._hasMultipleDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.all(model).length + this._languageFeaturesService.documentRangeFormattingEditProvider.all(model).length > 1);2272this._hasMultipleDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.all(model).length > 1);2273this._isInEmbeddedEditor.set(model.uri.scheme === Schemas.walkThroughSnippet || model.uri.scheme === Schemas.vscodeChatCodeBlock);2274});2275}2276}22772278class CodeEditorWidgetFocusTracker extends Disposable {22792280private _hasDomElementFocus: boolean;2281private readonly _domFocusTracker: dom.IFocusTracker;2282private readonly _overflowWidgetsDomNode: dom.IFocusTracker | undefined;22832284private readonly _onChange: Emitter<void> = this._register(new Emitter<void>());2285public readonly onChange: Event<void> = this._onChange.event;22862287private _overflowWidgetsDomNodeHasFocus: boolean;22882289private _hadFocus: boolean | undefined = undefined;22902291constructor(domElement: HTMLElement, overflowWidgetsDomNode: HTMLElement | undefined) {2292super();22932294this._hasDomElementFocus = false;2295this._domFocusTracker = this._register(dom.trackFocus(domElement));22962297this._overflowWidgetsDomNodeHasFocus = false;22982299this._register(this._domFocusTracker.onDidFocus(() => {2300this._hasDomElementFocus = true;2301this._update();2302}));2303this._register(this._domFocusTracker.onDidBlur(() => {2304this._hasDomElementFocus = false;2305this._update();2306}));23072308if (overflowWidgetsDomNode) {2309this._overflowWidgetsDomNode = this._register(dom.trackFocus(overflowWidgetsDomNode));2310this._register(this._overflowWidgetsDomNode.onDidFocus(() => {2311this._overflowWidgetsDomNodeHasFocus = true;2312this._update();2313}));2314this._register(this._overflowWidgetsDomNode.onDidBlur(() => {2315this._overflowWidgetsDomNodeHasFocus = false;2316this._update();2317}));2318}2319}23202321private _update() {2322const focused = this._hasDomElementFocus || this._overflowWidgetsDomNodeHasFocus;2323if (this._hadFocus !== focused) {2324this._hadFocus = focused;2325this._onChange.fire(undefined);2326}2327}23282329public hasFocus(): boolean {2330return this._hadFocus ?? false;2331}23322333public refreshState(): void {2334this._domFocusTracker.refreshState();2335this._overflowWidgetsDomNode?.refreshState?.();2336}2337}23382339class EditorDecorationsCollection implements editorCommon.IEditorDecorationsCollection {23402341private _decorationIds: string[] = [];2342private _isChangingDecorations: boolean = false;23432344public get length(): number {2345return this._decorationIds.length;2346}23472348constructor(2349private readonly _editor: editorBrowser.ICodeEditor,2350decorations: IModelDeltaDecoration[] | undefined2351) {2352if (Array.isArray(decorations) && decorations.length > 0) {2353this.set(decorations);2354}2355}23562357public onDidChange(listener: (e: IModelDecorationsChangedEvent) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable {2358return this._editor.onDidChangeModelDecorations((e) => {2359if (this._isChangingDecorations) {2360return;2361}2362listener.call(thisArgs, e);2363}, disposables);2364}23652366public getRange(index: number): Range | null {2367if (!this._editor.hasModel()) {2368return null;2369}2370if (index >= this._decorationIds.length) {2371return null;2372}2373return this._editor.getModel().getDecorationRange(this._decorationIds[index]);2374}23752376public getRanges(): Range[] {2377if (!this._editor.hasModel()) {2378return [];2379}2380const model = this._editor.getModel();2381const result: Range[] = [];2382for (const decorationId of this._decorationIds) {2383const range = model.getDecorationRange(decorationId);2384if (range) {2385result.push(range);2386}2387}2388return result;2389}23902391public has(decoration: IModelDecoration): boolean {2392return this._decorationIds.includes(decoration.id);2393}23942395public clear(): void {2396if (this._decorationIds.length === 0) {2397// nothing to do2398return;2399}2400this.set([]);2401}24022403public set(newDecorations: readonly IModelDeltaDecoration[]): string[] {2404try {2405this._isChangingDecorations = true;2406this._editor.changeDecorations((accessor) => {2407this._decorationIds = accessor.deltaDecorations(this._decorationIds, newDecorations);2408});2409} finally {2410this._isChangingDecorations = false;2411}2412return this._decorationIds;2413}24142415public append(newDecorations: readonly IModelDeltaDecoration[]): string[] {2416let newDecorationIds: string[] = [];2417try {2418this._isChangingDecorations = true;2419this._editor.changeDecorations((accessor) => {2420newDecorationIds = accessor.deltaDecorations([], newDecorations);2421this._decorationIds = this._decorationIds.concat(newDecorationIds);2422});2423} finally {2424this._isChangingDecorations = false;2425}2426return newDecorationIds;2427}2428}24292430const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' enable-background='new 0 0 6 3' height='3' width='6'><g fill='`);2431const squigglyEnd = encodeURIComponent(`'><polygon points='5.5,0 2.5,3 1.1,3 4.1,0'/><polygon points='4,0 6,2 6,0.6 5.4,0'/><polygon points='0,2 1,3 2.4,3 0,0.6'/></g></svg>`);24322433function getSquigglySVGData(color: Color) {2434return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd;2435}24362437const dotdotdotStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" height="3" width="12"><g fill="`);2438const dotdotdotEnd = encodeURIComponent(`"><circle cx="1" cy="1" r="1"/><circle cx="5" cy="1" r="1"/><circle cx="9" cy="1" r="1"/></g></svg>`);24392440function getDotDotDotSVGData(color: Color) {2441return dotdotdotStart + encodeURIComponent(color.toString()) + dotdotdotEnd;2442}24432444registerThemingParticipant((theme, collector) => {2445const errorForeground = theme.getColor(editorErrorForeground);2446if (errorForeground) {2447collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);2448}2449const warningForeground = theme.getColor(editorWarningForeground);2450if (warningForeground) {2451collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);2452}2453const infoForeground = theme.getColor(editorInfoForeground);2454if (infoForeground) {2455collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);2456}2457const hintForeground = theme.getColor(editorHintForeground);2458if (hintForeground) {2459collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`);2460}2461const unnecessaryForeground = theme.getColor(editorUnnecessaryCodeOpacity);2462if (unnecessaryForeground) {2463collector.addRule(`.monaco-editor.showUnused .${ClassName.EditorUnnecessaryInlineDecoration} { opacity: ${unnecessaryForeground.rgba.a}; }`);2464}2465});246624672468