codeEditorWidget.ts 75.4 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import 'vs/css!./media/editor';
A
Alex Dima 已提交
7 8
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
A
Alex Dima 已提交
9
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
10
import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
A
Alex Dima 已提交
11
import { Color } from 'vs/base/common/color';
J
Johannes Rieken 已提交
12
import { onUnexpectedError } from 'vs/base/common/errors';
A
Alex Dima 已提交
13 14
import { Emitter, Event } from 'vs/base/common/event';
import { hash } from 'vs/base/common/hash';
A
Alex Dima 已提交
15
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
A
Alex Dima 已提交
16
import { Schemas } from 'vs/base/common/network';
J
Johannes Rieken 已提交
17
import { Configuration } from 'vs/editor/browser/config/configuration';
A
Alex Dima 已提交
18 19
import { CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
20
import { EditorExtensionsRegistry, IEditorContributionDescription } from 'vs/editor/browser/editorExtensions';
A
Alex Dima 已提交
21 22 23 24
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICommandDelegate } from 'vs/editor/browser/view/viewController';
import { IContentWidgetData, IOverlayWidgetData, View } from 'vs/editor/browser/view/viewImpl';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
25
import { ConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, IComputedEditorOptions, FindComputedEditorOptionValueById, IEditorConstructionOptions, filterValidationDecorations } from 'vs/editor/common/config/editorOptions';
A
Alex Dima 已提交
26
import { Cursor, CursorStateChangedEvent } from 'vs/editor/common/controller/cursor';
A
Alex Dima 已提交
27
import { CursorColumns, ICursors } from 'vs/editor/common/controller/cursorCommon';
A
Alex Dima 已提交
28
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
A
Alex Dima 已提交
29 30 31 32 33
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { InternalEditorAction } from 'vs/editor/common/editorAction';
import * as editorCommon from 'vs/editor/common/editorCommon';
A
Alex Dima 已提交
34
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
35
import { EndOfLinePreference, IIdentifiedSingleEditOperation, IModelDecoration, IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel, ICursorStateComputer, IWordAtPosition } from 'vs/editor/common/model';
A
Alex Dima 已提交
36
import { ClassName } from 'vs/editor/common/model/intervalTree';
A
Alex Dima 已提交
37
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
A
Alex Dima 已提交
38
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
A
Alex Dima 已提交
39
import * as modes from 'vs/editor/common/modes';
40
import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from 'vs/editor/common/view/editorColorRegistry';
41
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
A
Alex Dima 已提交
42
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
43
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
A
Alex Dima 已提交
44
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
A
Alex Dima 已提交
45
import { ICommandService } from 'vs/platform/commands/common/commands';
A
Alex Dima 已提交
46 47 48 49
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { INotificationService } from 'vs/platform/notification/common/notification';
A
Alex Dima 已提交
50
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
51
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
52
import { withNullAsUndefined } from 'vs/base/common/types';
A
Renames  
Alexandru Dima 已提交
53
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
54
import { DOMLineBreaksComputerFactory } from 'vs/editor/browser/view/domLineBreaksComputer';
55
import { WordOperations } from 'vs/editor/common/controller/cursorWordOperations';
E
Erich Gamma 已提交
56

A
Alex Dima 已提交
57 58
let EDITOR_ID = 0;

59 60 61 62 63 64 65 66 67 68 69
export interface ICodeEditorWidgetOptions {
	/**
	 * Is this a simple widget (not a real code editor) ?
	 * Defaults to false.
	 */
	isSimpleWidget?: boolean;

	/**
	 * Contributions to instantiate.
	 * Defaults to EditorExtensionsRegistry.getEditorContributions().
	 */
70
	contributions?: IEditorContributionDescription[];
71 72 73 74 75 76 77 78

	/**
	 * Telemetry data associated with this CodeEditorWidget.
	 * Defaults to null.
	 */
	telemetryData?: object;
}

A
Alex Dima 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
class ModelData {
	public readonly model: ITextModel;
	public readonly viewModel: ViewModel;
	public readonly cursor: Cursor;
	public readonly view: View;
	public readonly hasRealView: boolean;
	public readonly listenersToRemove: IDisposable[];

	constructor(model: ITextModel, viewModel: ViewModel, cursor: Cursor, view: View, hasRealView: boolean, listenersToRemove: IDisposable[]) {
		this.model = model;
		this.viewModel = viewModel;
		this.cursor = cursor;
		this.view = view;
		this.hasRealView = hasRealView;
		this.listenersToRemove = listenersToRemove;
	}

	public dispose(): void {
		dispose(this.listenersToRemove);
		this.model.onBeforeDetached();
		if (this.hasRealView) {
			this.view.dispose();
		}
		this.cursor.dispose();
		this.viewModel.dispose();
	}
}

A
Alex Dima 已提交
107
export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeEditor {
A
Alex Dima 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

	//#region Eventing
	private readonly _onDidDispose: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidDispose: Event<void> = this._onDidDispose.event;

	private readonly _onDidChangeModelContent: Emitter<IModelContentChangedEvent> = this._register(new Emitter<IModelContentChangedEvent>());
	public readonly onDidChangeModelContent: Event<IModelContentChangedEvent> = this._onDidChangeModelContent.event;

	private readonly _onDidChangeModelLanguage: Emitter<IModelLanguageChangedEvent> = this._register(new Emitter<IModelLanguageChangedEvent>());
	public readonly onDidChangeModelLanguage: Event<IModelLanguageChangedEvent> = this._onDidChangeModelLanguage.event;

	private readonly _onDidChangeModelLanguageConfiguration: Emitter<IModelLanguageConfigurationChangedEvent> = this._register(new Emitter<IModelLanguageConfigurationChangedEvent>());
	public readonly onDidChangeModelLanguageConfiguration: Event<IModelLanguageConfigurationChangedEvent> = this._onDidChangeModelLanguageConfiguration.event;

	private readonly _onDidChangeModelOptions: Emitter<IModelOptionsChangedEvent> = this._register(new Emitter<IModelOptionsChangedEvent>());
	public readonly onDidChangeModelOptions: Event<IModelOptionsChangedEvent> = this._onDidChangeModelOptions.event;

	private readonly _onDidChangeModelDecorations: Emitter<IModelDecorationsChangedEvent> = this._register(new Emitter<IModelDecorationsChangedEvent>());
	public readonly onDidChangeModelDecorations: Event<IModelDecorationsChangedEvent> = this._onDidChangeModelDecorations.event;

128 129
	private readonly _onDidChangeConfiguration: Emitter<ConfigurationChangedEvent> = this._register(new Emitter<ConfigurationChangedEvent>());
	public readonly onDidChangeConfiguration: Event<ConfigurationChangedEvent> = this._onDidChangeConfiguration.event;
A
Alex Dima 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142

	protected readonly _onDidChangeModel: Emitter<editorCommon.IModelChangedEvent> = this._register(new Emitter<editorCommon.IModelChangedEvent>());
	public readonly onDidChangeModel: Event<editorCommon.IModelChangedEvent> = this._onDidChangeModel.event;

	private readonly _onDidChangeCursorPosition: Emitter<ICursorPositionChangedEvent> = this._register(new Emitter<ICursorPositionChangedEvent>());
	public readonly onDidChangeCursorPosition: Event<ICursorPositionChangedEvent> = this._onDidChangeCursorPosition.event;

	private readonly _onDidChangeCursorSelection: Emitter<ICursorSelectionChangedEvent> = this._register(new Emitter<ICursorSelectionChangedEvent>());
	public readonly onDidChangeCursorSelection: Event<ICursorSelectionChangedEvent> = this._onDidChangeCursorSelection.event;

	private readonly _onDidAttemptReadOnlyEdit: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidAttemptReadOnlyEdit: Event<void> = this._onDidAttemptReadOnlyEdit.event;

143 144
	private readonly _onDidLayoutChange: Emitter<EditorLayoutInfo> = this._register(new Emitter<EditorLayoutInfo>());
	public readonly onDidLayoutChange: Event<EditorLayoutInfo> = this._onDidLayoutChange.event;
A
Alex Dima 已提交
145

146
	private readonly _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter());
A
Alex Dima 已提交
147 148 149
	public readonly onDidFocusEditorText: Event<void> = this._editorTextFocus.onDidChangeToTrue;
	public readonly onDidBlurEditorText: Event<void> = this._editorTextFocus.onDidChangeToFalse;

150
	private readonly _editorWidgetFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter());
A
Alex Dima 已提交
151 152
	public readonly onDidFocusEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToTrue;
	public readonly onDidBlurEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToFalse;
A
Alex Dima 已提交
153 154 155 156 157 158 159

	private readonly _onWillType: Emitter<string> = this._register(new Emitter<string>());
	public readonly onWillType = this._onWillType.event;

	private readonly _onDidType: Emitter<string> = this._register(new Emitter<string>());
	public readonly onDidType = this._onDidType.event;

160 161
	private readonly _onDidCompositionStart: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidCompositionStart = this._onDidCompositionStart.event;
J
Johannes Rieken 已提交
162

163 164
	private readonly _onDidCompositionEnd: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidCompositionEnd = this._onDidCompositionEnd.event;
J
Johannes Rieken 已提交
165

166
	private readonly _onDidPaste: Emitter<editorBrowser.IPasteEvent> = this._register(new Emitter<editorBrowser.IPasteEvent>());
A
Alex Dima 已提交
167
	public readonly onDidPaste = this._onDidPaste.event;
E
Erich Gamma 已提交
168

A
Alex Dima 已提交
169 170 171 172 173 174 175 176 177
	private readonly _onMouseUp: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseUp: Event<editorBrowser.IEditorMouseEvent> = this._onMouseUp.event;

	private readonly _onMouseDown: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseDown: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDown.event;

	private readonly _onMouseDrag: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseDrag: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDrag.event;

A
Alex Dima 已提交
178 179
	private readonly _onMouseDrop: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseDrop: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseDrop.event;
A
Alex Dima 已提交
180 181 182 183 184 185 186

	private readonly _onContextMenu: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onContextMenu: Event<editorBrowser.IEditorMouseEvent> = this._onContextMenu.event;

	private readonly _onMouseMove: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseMove: Event<editorBrowser.IEditorMouseEvent> = this._onMouseMove.event;

A
Alex Dima 已提交
187 188
	private readonly _onMouseLeave: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseLeave: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseLeave.event;
A
Alex Dima 已提交
189

190 191 192
	private readonly _onMouseWheel: Emitter<IMouseWheelEvent> = this._register(new Emitter<IMouseWheelEvent>());
	public readonly onMouseWheel: Event<IMouseWheelEvent> = this._onMouseWheel.event;

A
Alex Dima 已提交
193 194 195 196 197 198
	private readonly _onKeyUp: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
	public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;

	private readonly _onKeyDown: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
	public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;

199 200 201
	private readonly _onDidContentSizeChange: Emitter<editorCommon.IContentSizeChangedEvent> = this._register(new Emitter<editorCommon.IContentSizeChangedEvent>());
	public readonly onDidContentSizeChange: Event<editorCommon.IContentSizeChangedEvent> = this._onDidContentSizeChange.event;

A
Alex Dima 已提交
202 203 204 205 206
	private readonly _onDidScrollChange: Emitter<editorCommon.IScrollEvent> = this._register(new Emitter<editorCommon.IScrollEvent>());
	public readonly onDidScrollChange: Event<editorCommon.IScrollEvent> = this._onDidScrollChange.event;

	private readonly _onDidChangeViewZones: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeViewZones: Event<void> = this._onDidChangeViewZones.event;
A
Alex Dima 已提交
207
	//#endregion
A
Alex Dima 已提交
208

A
Alex Dima 已提交
209
	public readonly isSimpleWidget: boolean;
M
Matt Bierner 已提交
210
	private readonly _telemetryData?: object;
211

A
Alex Dima 已提交
212 213
	private readonly _domElement: HTMLElement;
	private readonly _id: number;
A
Alex Dima 已提交
214 215
	private readonly _configuration: editorCommon.IConfiguration;

A
Alex Dima 已提交
216 217
	protected readonly _contributions: { [key: string]: editorCommon.IEditorContribution; };
	protected readonly _actions: { [key: string]: editorCommon.IEditorAction; };
A
Alex Dima 已提交
218 219

	// --- Members logically associated to a model
A
Alex Dima 已提交
220
	protected _modelData: ModelData | null;
E
Erich Gamma 已提交
221

A
Alex Dima 已提交
222 223 224 225 226 227 228
	protected readonly _instantiationService: IInstantiationService;
	protected readonly _contextKeyService: IContextKeyService;
	private readonly _notificationService: INotificationService;
	private readonly _codeEditorService: ICodeEditorService;
	private readonly _commandService: ICommandService;
	private readonly _themeService: IThemeService;

A
Alex Dima 已提交
229
	private readonly _focusTracker: CodeEditorWidgetFocusTracker;
230

A
Alex Dima 已提交
231 232
	private readonly _contentWidgets: { [key: string]: IContentWidgetData; };
	private readonly _overlayWidgets: { [key: string]: IOverlayWidgetData; };
E
Erich Gamma 已提交
233

A
Alex Dima 已提交
234 235 236 237 238
	/**
	 * map from "parent" decoration type to live decoration ids.
	 */
	private _decorationTypeKeysToIds: { [decorationTypeKey: string]: string[] };
	private _decorationTypeSubtypes: { [decorationTypeKey: string]: { [subtype: string]: boolean } };
E
Erich Gamma 已提交
239 240

	constructor(
J
Johannes Rieken 已提交
241
		domElement: HTMLElement,
242
		options: IEditorConstructionOptions,
243
		codeEditorWidgetOptions: ICodeEditorWidgetOptions,
E
Erich Gamma 已提交
244 245
		@IInstantiationService instantiationService: IInstantiationService,
		@ICodeEditorService codeEditorService: ICodeEditorService,
246
		@ICommandService commandService: ICommandService,
247
		@IContextKeyService contextKeyService: IContextKeyService,
248
		@IThemeService themeService: IThemeService,
249 250
		@INotificationService notificationService: INotificationService,
		@IAccessibilityService accessibilityService: IAccessibilityService
E
Erich Gamma 已提交
251
	) {
A
Alex Dima 已提交
252
		super();
A
Alex Dima 已提交
253 254
		this._domElement = domElement;
		this._id = (++EDITOR_ID);
A
Alex Dima 已提交
255 256
		this._decorationTypeKeysToIds = {};
		this._decorationTypeSubtypes = {};
257
		this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false;
M
Matt Bierner 已提交
258
		this._telemetryData = codeEditorWidgetOptions.telemetryData;
A
Alex Dima 已提交
259 260

		options = options || {};
261
		this._configuration = this._register(this._createConfiguration(options, accessibilityService));
A
Alex Dima 已提交
262 263 264
		this._register(this._configuration.onDidChange((e) => {
			this._onDidChangeConfiguration.fire(e);

A
Alex Dima 已提交
265
			const options = this._configuration.options;
A
renames  
Alex Dima 已提交
266 267
			if (e.hasChanged(EditorOption.layoutInfo)) {
				const layoutInfo = options.get(EditorOption.layoutInfo);
A
Alex Dima 已提交
268
				this._onDidLayoutChange.fire(layoutInfo);
A
Alex Dima 已提交
269 270 271
			}
		}));

A
Alex Dima 已提交
272
		this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));
A
Alex Dima 已提交
273
		this._notificationService = notificationService;
274
		this._codeEditorService = codeEditorService;
275
		this._commandService = commandService;
276
		this._themeService = themeService;
A
Alex Dima 已提交
277 278 279 280 281
		this._register(new EditorContextKeysManager(this, this._contextKeyService));
		this._register(new EditorModeContext(this, this._contextKeyService));

		this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));

A
Alex Dima 已提交
282
		this._modelData = null;
A
Alex Dima 已提交
283 284 285

		this._contributions = {};
		this._actions = {};
E
Erich Gamma 已提交
286

287
		this._focusTracker = new CodeEditorWidgetFocusTracker(domElement);
A
Alex Dima 已提交
288
		this._focusTracker.onChange(() => {
A
Alex Dima 已提交
289
			this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());
E
Erich Gamma 已提交
290 291
		});

A
Alex Dima 已提交
292 293
		this._contentWidgets = {};
		this._overlayWidgets = {};
E
Erich Gamma 已提交
294

295
		let contributions: IEditorContributionDescription[];
A
Alex Dima 已提交
296 297 298
		if (Array.isArray(codeEditorWidgetOptions.contributions)) {
			contributions = codeEditorWidgetOptions.contributions;
		} else {
299 300
			contributions = EditorExtensionsRegistry.getEditorContributions();
		}
301
		for (const desc of contributions) {
E
Erich Gamma 已提交
302
			try {
303 304
				const contribution = this._instantiationService.createInstance(desc.ctor, this);
				this._contributions[desc.id] = contribution;
E
Erich Gamma 已提交
305
			} catch (err) {
306
				onUnexpectedError(err);
E
Erich Gamma 已提交
307 308
			}
		}
309

310
		EditorExtensionsRegistry.getEditorActions().forEach((action) => {
311 312 313 314
			const internalAction = new InternalEditorAction(
				action.id,
				action.label,
				action.alias,
315
				withNullAsUndefined(action.precondition),
316
				(): Promise<void> => {
317
					return this._instantiationService.invokeFunction((accessor) => {
318
						return Promise.resolve(action.runEditorCommand(accessor, this, null));
319 320 321 322
					});
				},
				this._contextKeyService
			);
A
Alex Dima 已提交
323
			this._actions[internalAction.id] = internalAction;
324
		});
325 326

		this._codeEditorService.addCodeEditor(this);
E
Erich Gamma 已提交
327 328
	}

329
	protected _createConfiguration(options: IEditorConstructionOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration {
A
Alex Dima 已提交
330
		return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService);
A
Alex Dima 已提交
331 332 333
	}

	public getId(): string {
A
Alex Dima 已提交
334
		return this.getEditorType() + ':' + this._id;
A
Alex Dima 已提交
335 336 337 338
	}

	public getEditorType(): string {
		return editorCommon.EditorType.ICodeEditor;
E
Erich Gamma 已提交
339 340 341
	}

	public dispose(): void {
342 343
		this._codeEditorService.removeCodeEditor(this);

344
		this._focusTracker.dispose();
A
Alex Dima 已提交
345

M
Matt Bierner 已提交
346
		const keys = Object.keys(this._contributions);
A
Alex Dima 已提交
347
		for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
348
			const contributionId = keys[i];
A
Alex Dima 已提交
349 350 351 352 353 354 355 356
			this._contributions[contributionId].dispose();
		}

		this._removeDecorationTypes();
		this._postDetachModelCleanup(this._detachModel());

		this._onDidDispose.fire();

E
Erich Gamma 已提交
357 358 359
		super.dispose();
	}

A
Alex Dima 已提交
360 361 362 363
	public invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T {
		return this._instantiationService.invokeFunction(fn);
	}

364
	public updateOptions(newOptions: IEditorOptions): void {
A
Alex Dima 已提交
365 366 367
		this._configuration.updateOptions(newOptions);
	}

368
	public getOptions(): IComputedEditorOptions {
A
Alex Dima 已提交
369 370 371
		return this._configuration.options;
	}

A
renames  
Alex Dima 已提交
372
	public getOption<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T> {
373
		return this._configuration.options.get(id);
A
Alex Dima 已提交
374 375
	}

376
	public getRawOptions(): IEditorOptions {
A
Alex Dima 已提交
377 378 379
		return this._configuration.getRawOptions();
	}

380 381 382 383 384 385 386
	public getConfiguredWordAtPosition(position: Position): IWordAtPosition | null {
		if (!this._modelData) {
			return null;
		}
		return WordOperations.getWordAtPosition(this._modelData.model, this._configuration.options.get(EditorOption.wordSeparators), position);
	}

A
Alex Dima 已提交
387 388 389
	public getValue(options: { preserveBOM: boolean; lineEnding: string; } | null = null): string {
		if (!this._modelData) {
			return '';
A
Alex Dima 已提交
390
		}
A
Alex Dima 已提交
391

M
Matt Bierner 已提交
392
		const preserveBOM: boolean = (options && options.preserveBOM) ? true : false;
A
Alex Dima 已提交
393 394 395 396 397 398 399
		let eolPreference = EndOfLinePreference.TextDefined;
		if (options && options.lineEnding && options.lineEnding === '\n') {
			eolPreference = EndOfLinePreference.LF;
		} else if (options && options.lineEnding && options.lineEnding === '\r\n') {
			eolPreference = EndOfLinePreference.CRLF;
		}
		return this._modelData.model.getValue(eolPreference, preserveBOM);
A
Alex Dima 已提交
400 401 402
	}

	public setValue(newValue: string): void {
A
Alex Dima 已提交
403 404
		if (!this._modelData) {
			return;
A
Alex Dima 已提交
405
		}
A
Alex Dima 已提交
406
		this._modelData.model.setValue(newValue);
A
Alex Dima 已提交
407 408
	}

A
Alex Dima 已提交
409 410 411 412 413
	public getModel(): ITextModel | null {
		if (!this._modelData) {
			return null;
		}
		return this._modelData.model;
A
Alex Dima 已提交
414 415
	}

A
Alex Dima 已提交
416 417
	public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | null = null): void {
		const model = <ITextModel | null>_model;
A
Alex Dima 已提交
418 419 420 421 422
		if (this._modelData === null && model === null) {
			// Current model is the new model
			return;
		}
		if (this._modelData && this._modelData.model === model) {
A
Alex Dima 已提交
423 424 425
			// Current model is the new model
			return;
		}
A
Alexandru Dima 已提交
426
		const hasTextFocus = this.hasTextFocus();
M
Matt Bierner 已提交
427
		const detachedModel = this._detachModel();
A
Alex Dima 已提交
428
		this._attachModel(model);
A
Alexandru Dima 已提交
429 430 431
		if (hasTextFocus && this.hasModel()) {
			this.focus();
		}
A
Alex Dima 已提交
432

M
Matt Bierner 已提交
433
		const e: editorCommon.IModelChangedEvent = {
A
Alex Dima 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446
			oldModelUrl: detachedModel ? detachedModel.uri : null,
			newModelUrl: model ? model.uri : null
		};

		this._removeDecorationTypes();
		this._onDidChangeModel.fire(e);
		this._postDetachModelCleanup(detachedModel);
	}

	private _removeDecorationTypes(): void {
		this._decorationTypeKeysToIds = {};
		if (this._decorationTypeSubtypes) {
			for (let decorationType in this._decorationTypeSubtypes) {
M
Matt Bierner 已提交
447
				const subTypes = this._decorationTypeSubtypes[decorationType];
A
Alex Dima 已提交
448 449 450 451 452 453 454 455 456
				for (let subType in subTypes) {
					this._removeDecorationType(decorationType + '-' + subType);
				}
			}
			this._decorationTypeSubtypes = {};
		}
	}

	public getVisibleRanges(): Range[] {
A
Alex Dima 已提交
457
		if (!this._modelData) {
A
Alex Dima 已提交
458 459
			return [];
		}
A
Alex Dima 已提交
460
		return this._modelData.viewModel.getVisibleRanges();
A
Alex Dima 已提交
461 462
	}

463 464 465 466 467 468 469
	public getVisibleRangesPlusViewportAboveBelow(): Range[] {
		if (!this._modelData) {
			return [];
		}
		return this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow();
	}

A
Alex Dima 已提交
470
	public getWhitespaces(): IEditorWhitespace[] {
A
Alex Dima 已提交
471
		if (!this._modelData) {
A
Alex Dima 已提交
472 473
			return [];
		}
A
Alex Dima 已提交
474
		return this._modelData.viewModel.viewLayout.getWhitespaces();
A
Alex Dima 已提交
475 476
	}

A
Alex Dima 已提交
477
	private static _getVerticalOffsetForPosition(modelData: ModelData, modelLineNumber: number, modelColumn: number): number {
M
Matt Bierner 已提交
478
		const modelPosition = modelData.model.validatePosition({
A
Alex Dima 已提交
479 480 481
			lineNumber: modelLineNumber,
			column: modelColumn
		});
M
Matt Bierner 已提交
482
		const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
A
Alex Dima 已提交
483
		return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
A
Alex Dima 已提交
484 485 486
	}

	public getTopForLineNumber(lineNumber: number): number {
A
Alex Dima 已提交
487
		if (!this._modelData) {
A
Alex Dima 已提交
488 489
			return -1;
		}
A
Alex Dima 已提交
490
		return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, 1);
A
Alex Dima 已提交
491 492 493
	}

	public getTopForPosition(lineNumber: number, column: number): number {
A
Alex Dima 已提交
494
		if (!this._modelData) {
A
Alex Dima 已提交
495 496
			return -1;
		}
A
Alex Dima 已提交
497
		return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, column);
A
Alex Dima 已提交
498 499 500
	}

	public setHiddenAreas(ranges: IRange[]): void {
A
Alex Dima 已提交
501 502
		if (this._modelData) {
			this._modelData.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)));
A
Alex Dima 已提交
503 504 505 506
		}
	}

	public getVisibleColumnFromPosition(rawPosition: IPosition): number {
A
Alex Dima 已提交
507
		if (!this._modelData) {
A
Alex Dima 已提交
508 509 510
			return rawPosition.column;
		}

M
Matt Bierner 已提交
511 512
		const position = this._modelData.model.validatePosition(rawPosition);
		const tabSize = this._modelData.model.getOptions().tabSize;
A
Alex Dima 已提交
513

A
Alex Dima 已提交
514
		return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1;
A
Alex Dima 已提交
515 516
	}

517 518 519 520 521 522 523 524 525 526 527
	public getStatusbarColumn(rawPosition: IPosition): number {
		if (!this._modelData) {
			return rawPosition.column;
		}

		const position = this._modelData.model.validatePosition(rawPosition);
		const tabSize = this._modelData.model.getOptions().tabSize;

		return CursorColumns.toStatusbarColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize);
	}

A
Alex Dima 已提交
528 529
	public getPosition(): Position | null {
		if (!this._modelData) {
A
Alex Dima 已提交
530 531
			return null;
		}
A
Alex Dima 已提交
532
		return this._modelData.cursor.getPosition();
A
Alex Dima 已提交
533 534 535
	}

	public setPosition(position: IPosition): void {
A
Alex Dima 已提交
536
		if (!this._modelData) {
A
Alex Dima 已提交
537 538 539 540 541
			return;
		}
		if (!Position.isIPosition(position)) {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
542
		this._modelData.cursor.setSelections('api', [{
A
Alex Dima 已提交
543 544 545 546 547 548 549 550
			selectionStartLineNumber: position.lineNumber,
			selectionStartColumn: position.column,
			positionLineNumber: position.lineNumber,
			positionColumn: position.column
		}]);
	}

	private _sendRevealRange(modelRange: Range, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
A
Alex Dima 已提交
551
		if (!this._modelData) {
A
Alex Dima 已提交
552 553 554 555 556
			return;
		}
		if (!Range.isIRange(modelRange)) {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
557 558
		const validatedModelRange = this._modelData.model.validateRange(modelRange);
		const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);
A
Alex Dima 已提交
559

560
		this._modelData.cursor.emitCursorRevealRange('api', viewRange, null, verticalType, revealHorizontal, scrollType);
A
Alex Dima 已提交
561 562 563 564 565 566 567 568 569 570 571 572 573 574
	}

	public revealLine(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.Simple, scrollType);
	}

	public revealLineInCenter(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.Center, scrollType);
	}

	public revealLineInCenterIfOutsideViewport(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.CenterIfOutsideViewport, scrollType);
	}

575 576
	public revealLineNearTop(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.NearTop, scrollType);
577 578
	}

A
Alex Dima 已提交
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
	private _revealLine(lineNumber: number, revealType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {
		if (typeof lineNumber !== 'number') {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(lineNumber, 1, lineNumber, 1),
			revealType,
			false,
			scrollType
		);
	}

	public revealPosition(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.Simple,
			true,
			scrollType
		);
	}

	public revealPositionInCenter(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.Center,
			true,
			scrollType
		);
	}

	public revealPositionInCenterIfOutsideViewport(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.CenterIfOutsideViewport,
			true,
			scrollType
		);
	}

619
	public revealPositionNearTop(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
620 621
		this._revealPosition(
			position,
622
			VerticalRevealType.NearTop,
623 624 625 626 627
			true,
			scrollType
		);
	}

A
Alex Dima 已提交
628 629 630 631 632 633 634 635 636 637 638 639 640
	private _revealPosition(position: IPosition, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
		if (!Position.isIPosition(position)) {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(position.lineNumber, position.column, position.lineNumber, position.column),
			verticalType,
			revealHorizontal,
			scrollType
		);
	}

A
Alex Dima 已提交
641 642
	public getSelection(): Selection | null {
		if (!this._modelData) {
A
Alex Dima 已提交
643 644
			return null;
		}
A
Alex Dima 已提交
645
		return this._modelData.cursor.getSelection();
A
Alex Dima 已提交
646 647
	}

A
Alex Dima 已提交
648 649
	public getSelections(): Selection[] | null {
		if (!this._modelData) {
A
Alex Dima 已提交
650 651
			return null;
		}
A
Alex Dima 已提交
652
		return this._modelData.cursor.getSelections();
A
Alex Dima 已提交
653 654 655 656 657 658 659
	}

	public setSelection(range: IRange): void;
	public setSelection(editorRange: Range): void;
	public setSelection(selection: ISelection): void;
	public setSelection(editorSelection: Selection): void;
	public setSelection(something: any): void {
M
Matt Bierner 已提交
660 661
		const isSelection = Selection.isISelection(something);
		const isRange = Range.isIRange(something);
A
Alex Dima 已提交
662 663 664 665 666 667 668 669 670

		if (!isSelection && !isRange) {
			throw new Error('Invalid arguments');
		}

		if (isSelection) {
			this._setSelectionImpl(<ISelection>something);
		} else if (isRange) {
			// act as if it was an IRange
M
Matt Bierner 已提交
671
			const selection: ISelection = {
A
Alex Dima 已提交
672 673 674 675 676 677 678 679 680 681
				selectionStartLineNumber: something.startLineNumber,
				selectionStartColumn: something.startColumn,
				positionLineNumber: something.endLineNumber,
				positionColumn: something.endColumn
			};
			this._setSelectionImpl(selection);
		}
	}

	private _setSelectionImpl(sel: ISelection): void {
A
Alex Dima 已提交
682
		if (!this._modelData) {
A
Alex Dima 已提交
683 684
			return;
		}
M
Matt Bierner 已提交
685
		const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);
A
Alex Dima 已提交
686
		this._modelData.cursor.setSelections('api', [selection]);
A
Alex Dima 已提交
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
	}

	public revealLines(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.Simple,
			scrollType
		);
	}

	public revealLinesInCenter(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.Center,
			scrollType
		);
	}

	public revealLinesInCenterIfOutsideViewport(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.CenterIfOutsideViewport,
			scrollType
		);
	}

716
	public revealLinesNearTop(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
717 718 719
		this._revealLines(
			startLineNumber,
			endLineNumber,
720
			VerticalRevealType.NearTop,
721 722 723 724
			scrollType
		);
	}

A
Alex Dima 已提交
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
	private _revealLines(startLineNumber: number, endLineNumber: number, verticalType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {
		if (typeof startLineNumber !== 'number' || typeof endLineNumber !== 'number') {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(startLineNumber, 1, endLineNumber, 1),
			verticalType,
			false,
			scrollType
		);
	}

	public revealRange(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth, revealVerticalInCenter: boolean = false, revealHorizontal: boolean = true): void {
		this._revealRange(
			range,
			revealVerticalInCenter ? VerticalRevealType.Center : VerticalRevealType.Simple,
			revealHorizontal,
			scrollType
		);
	}

	public revealRangeInCenter(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.Center,
			true,
			scrollType
		);
	}

	public revealRangeInCenterIfOutsideViewport(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.CenterIfOutsideViewport,
			true,
			scrollType
		);
	}

765
	public revealRangeNearTop(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
766 767
		this._revealRange(
			range,
768
			VerticalRevealType.NearTop,
769 770 771 772 773
			true,
			scrollType
		);
	}

774 775 776 777 778 779 780 781 782
	public revealRangeNearTopIfOutsideViewport(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.NearTopIfOutsideViewport,
			true,
			scrollType
		);
	}

A
Alex Dima 已提交
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
	public revealRangeAtTop(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.Top,
			true,
			scrollType
		);
	}

	private _revealRange(range: IRange, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
		if (!Range.isIRange(range)) {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			Range.lift(range),
			verticalType,
			revealHorizontal,
			scrollType
		);
	}

805
	public setSelections(ranges: readonly ISelection[], source: string = 'api'): void {
A
Alex Dima 已提交
806
		if (!this._modelData) {
A
Alex Dima 已提交
807 808 809 810 811 812 813 814 815 816
			return;
		}
		if (!ranges || ranges.length === 0) {
			throw new Error('Invalid arguments');
		}
		for (let i = 0, len = ranges.length; i < len; i++) {
			if (!Selection.isISelection(ranges[i])) {
				throw new Error('Invalid arguments');
			}
		}
A
Alex Dima 已提交
817
		this._modelData.cursor.setSelections(source, ranges);
A
Alex Dima 已提交
818 819
	}

820 821 822 823 824 825 826
	public getContentWidth(): number {
		if (!this._modelData) {
			return -1;
		}
		return this._modelData.viewModel.viewLayout.getContentWidth();
	}

A
Alex Dima 已提交
827
	public getScrollWidth(): number {
A
Alex Dima 已提交
828
		if (!this._modelData) {
A
Alex Dima 已提交
829 830
			return -1;
		}
A
Alex Dima 已提交
831
		return this._modelData.viewModel.viewLayout.getScrollWidth();
A
Alex Dima 已提交
832 833
	}
	public getScrollLeft(): number {
A
Alex Dima 已提交
834
		if (!this._modelData) {
A
Alex Dima 已提交
835 836
			return -1;
		}
A
Alex Dima 已提交
837
		return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();
A
Alex Dima 已提交
838 839
	}

840 841 842 843 844 845 846
	public getContentHeight(): number {
		if (!this._modelData) {
			return -1;
		}
		return this._modelData.viewModel.viewLayout.getContentHeight();
	}

A
Alex Dima 已提交
847
	public getScrollHeight(): number {
A
Alex Dima 已提交
848
		if (!this._modelData) {
A
Alex Dima 已提交
849 850
			return -1;
		}
A
Alex Dima 已提交
851
		return this._modelData.viewModel.viewLayout.getScrollHeight();
A
Alex Dima 已提交
852 853
	}
	public getScrollTop(): number {
A
Alex Dima 已提交
854
		if (!this._modelData) {
A
Alex Dima 已提交
855 856
			return -1;
		}
A
Alex Dima 已提交
857
		return this._modelData.viewModel.viewLayout.getCurrentScrollTop();
A
Alex Dima 已提交
858 859
	}

860
	public setScrollLeft(newScrollLeft: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {
A
Alex Dima 已提交
861
		if (!this._modelData) {
A
Alex Dima 已提交
862 863 864 865 866
			return;
		}
		if (typeof newScrollLeft !== 'number') {
			throw new Error('Invalid arguments');
		}
867
		this._modelData.viewModel.viewLayout.setScrollPosition({
A
Alex Dima 已提交
868
			scrollLeft: newScrollLeft
869
		}, scrollType);
A
Alex Dima 已提交
870
	}
871
	public setScrollTop(newScrollTop: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {
A
Alex Dima 已提交
872
		if (!this._modelData) {
A
Alex Dima 已提交
873 874 875 876 877
			return;
		}
		if (typeof newScrollTop !== 'number') {
			throw new Error('Invalid arguments');
		}
878
		this._modelData.viewModel.viewLayout.setScrollPosition({
A
Alex Dima 已提交
879
			scrollTop: newScrollTop
880
		}, scrollType);
A
Alex Dima 已提交
881
	}
882
	public setScrollPosition(position: editorCommon.INewScrollPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Immediate): void {
A
Alex Dima 已提交
883
		if (!this._modelData) {
A
Alex Dima 已提交
884 885
			return;
		}
886
		this._modelData.viewModel.viewLayout.setScrollPosition(position, scrollType);
A
Alex Dima 已提交
887 888
	}

A
Alex Dima 已提交
889 890
	public saveViewState(): editorCommon.ICodeEditorViewState | null {
		if (!this._modelData) {
A
Alex Dima 已提交
891 892 893 894 895
			return null;
		}
		const contributionsState: { [key: string]: any } = {};

		const keys = Object.keys(this._contributions);
896
		for (const id of keys) {
A
Alex Dima 已提交
897 898 899 900 901 902
			const contribution = this._contributions[id];
			if (typeof contribution.saveViewState === 'function') {
				contributionsState[id] = contribution.saveViewState();
			}
		}

A
Alex Dima 已提交
903 904
		const cursorState = this._modelData.cursor.saveState();
		const viewState = this._modelData.viewModel.saveState();
A
Alex Dima 已提交
905 906 907 908 909 910 911
		return {
			cursorState: cursorState,
			viewState: viewState,
			contributionsState: contributionsState
		};
	}

M
Matt Bierner 已提交
912
	public restoreViewState(s: editorCommon.IEditorViewState | null): void {
A
Alex Dima 已提交
913
		if (!this._modelData || !this._modelData.hasRealView) {
A
Alex Dima 已提交
914 915
			return;
		}
M
Matt Bierner 已提交
916 917
		const codeEditorState = s as editorCommon.ICodeEditorViewState | null;
		if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) {
M
Matt Bierner 已提交
918
			const cursorState = <any>codeEditorState.cursorState;
A
Alex Dima 已提交
919
			if (Array.isArray(cursorState)) {
A
Alex Dima 已提交
920
				this._modelData.cursor.restoreState(<editorCommon.ICursorState[]>cursorState);
A
Alex Dima 已提交
921 922
			} else {
				// Backwards compatibility
A
Alex Dima 已提交
923
				this._modelData.cursor.restoreState([<editorCommon.ICursorState>cursorState]);
A
Alex Dima 已提交
924 925
			}

M
Matt Bierner 已提交
926 927
			const contributionsState = codeEditorState.contributionsState || {};
			const keys = Object.keys(this._contributions);
A
Alex Dima 已提交
928
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
929 930
				const id = keys[i];
				const contribution = this._contributions[id];
A
Alex Dima 已提交
931 932 933 934 935
				if (typeof contribution.restoreViewState === 'function') {
					contribution.restoreViewState(contributionsState[id]);
				}
			}

M
Matt Bierner 已提交
936
			const reducedState = this._modelData.viewModel.reduceRestoreState(codeEditorState.viewState);
A
Alex Dima 已提交
937
			this._modelData.view.restoreState(reducedState);
A
Alex Dima 已提交
938 939 940 941
		}
	}

	public onVisible(): void {
942
		this._modelData?.view.refreshFocusState();
A
Alex Dima 已提交
943 944 945
	}

	public onHide(): void {
946
		this._modelData?.view.refreshFocusState();
947
		this._focusTracker.refreshState();
A
Alex Dima 已提交
948 949 950 951 952 953 954
	}

	public getContribution<T extends editorCommon.IEditorContribution>(id: string): T {
		return <T>(this._contributions[id] || null);
	}

	public getActions(): editorCommon.IEditorAction[] {
M
Matt Bierner 已提交
955
		const result: editorCommon.IEditorAction[] = [];
A
Alex Dima 已提交
956

M
Matt Bierner 已提交
957
		const keys = Object.keys(this._actions);
A
Alex Dima 已提交
958
		for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
959
			const id = keys[i];
A
Alex Dima 已提交
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
			result.push(this._actions[id]);
		}

		return result;
	}

	public getSupportedActions(): editorCommon.IEditorAction[] {
		let result = this.getActions();

		result = result.filter(action => action.isSupported());

		return result;
	}

	public getAction(id: string): editorCommon.IEditorAction {
		return this._actions[id] || null;
	}

A
Alex Dima 已提交
978
	public trigger(source: string | null | undefined, handlerId: string, payload: any): void {
A
Alex Dima 已提交
979 980 981 982
		payload = payload || {};

		// Special case for typing
		if (handlerId === editorCommon.Handler.Type) {
A
Alex Dima 已提交
983
			if (!this._modelData || typeof payload.text !== 'string' || payload.text.length === 0) {
A
Alex Dima 已提交
984 985 986 987 988 989
				// nothing to do
				return;
			}
			if (source === 'keyboard') {
				this._onWillType.fire(payload.text);
			}
A
Alex Dima 已提交
990
			this._modelData.cursor.trigger(source, handlerId, payload);
A
Alex Dima 已提交
991 992 993 994 995 996 997 998
			if (source === 'keyboard') {
				this._onDidType.fire(payload.text);
			}
			return;
		}

		// Special case for pasting
		if (handlerId === editorCommon.Handler.Paste) {
A
Alex Dima 已提交
999
			if (!this._modelData || typeof payload.text !== 'string' || payload.text.length === 0) {
A
Alex Dima 已提交
1000 1001 1002
				// nothing to do
				return;
			}
A
Alex Dima 已提交
1003 1004 1005
			const startPosition = this._modelData.cursor.getSelection().getStartPosition();
			this._modelData.cursor.trigger(source, handlerId, payload);
			const endPosition = this._modelData.cursor.getSelection().getStartPosition();
A
Alex Dima 已提交
1006 1007
			if (source === 'keyboard') {
				this._onDidPaste.fire(
1008 1009 1010 1011
					{
						range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
						mode: payload.mode
					}
A
Alex Dima 已提交
1012 1013 1014 1015 1016 1017 1018
				);
			}
			return;
		}

		const action = this.getAction(handlerId);
		if (action) {
R
Rob Lourens 已提交
1019
			Promise.resolve(action.run()).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
1020 1021 1022
			return;
		}

A
Alex Dima 已提交
1023
		if (!this._modelData) {
A
Alex Dima 已提交
1024 1025 1026 1027 1028 1029 1030
			return;
		}

		if (this._triggerEditorCommand(source, handlerId, payload)) {
			return;
		}

A
Alex Dima 已提交
1031
		this._modelData.cursor.trigger(source, handlerId, payload);
1032 1033 1034 1035 1036 1037 1038

		if (handlerId === editorCommon.Handler.CompositionStart) {
			this._onDidCompositionStart.fire();
		}
		if (handlerId === editorCommon.Handler.CompositionEnd) {
			this._onDidCompositionEnd.fire();
		}
A
Alex Dima 已提交
1039 1040
	}

A
Alex Dima 已提交
1041
	private _triggerEditorCommand(source: string | null | undefined, handlerId: string, payload: any): boolean {
A
Alex Dima 已提交
1042 1043 1044 1045
		const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
		if (command) {
			payload = payload || {};
			payload.source = source;
A
Alex Dima 已提交
1046
			this._instantiationService.invokeFunction((accessor) => {
R
Rob Lourens 已提交
1047
				Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
1048
			});
A
Alex Dima 已提交
1049 1050 1051 1052 1053 1054
			return true;
		}

		return false;
	}

A
Alex Dima 已提交
1055 1056 1057 1058 1059
	public _getCursors(): ICursors | null {
		if (!this._modelData) {
			return null;
		}
		return this._modelData.cursor;
A
Alex Dima 已提交
1060 1061 1062
	}

	public pushUndoStop(): boolean {
A
Alex Dima 已提交
1063
		if (!this._modelData) {
A
Alex Dima 已提交
1064 1065
			return false;
		}
A
renames  
Alex Dima 已提交
1066
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
1067 1068 1069
			// read only editor => sorry!
			return false;
		}
A
Alex Dima 已提交
1070
		this._modelData.model.pushStackElement();
A
Alex Dima 已提交
1071 1072 1073
		return true;
	}

A
Alex Dima 已提交
1074
	public executeEdits(source: string | null | undefined, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean {
A
Alex Dima 已提交
1075
		if (!this._modelData) {
A
Alex Dima 已提交
1076 1077
			return false;
		}
A
renames  
Alex Dima 已提交
1078
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
1079 1080 1081 1082
			// read only editor => sorry!
			return false;
		}

1083 1084 1085 1086 1087 1088 1089
		let cursorStateComputer: ICursorStateComputer;
		if (!endCursorState) {
			cursorStateComputer = () => null;
		} else if (Array.isArray(endCursorState)) {
			cursorStateComputer = () => endCursorState;
		} else {
			cursorStateComputer = endCursorState;
A
Alex Dima 已提交
1090 1091
		}

1092
		this._modelData.cursor.executeEdits(source, edits, cursorStateComputer);
A
Alex Dima 已提交
1093 1094 1095
		return true;
	}

A
Alex Dima 已提交
1096
	public executeCommand(source: string | null | undefined, command: editorCommon.ICommand): void {
A
Alex Dima 已提交
1097
		if (!this._modelData) {
A
Alex Dima 已提交
1098 1099
			return;
		}
A
Alex Dima 已提交
1100
		this._modelData.cursor.trigger(source, editorCommon.Handler.ExecuteCommand, command);
A
Alex Dima 已提交
1101 1102
	}

A
Alex Dima 已提交
1103
	public executeCommands(source: string | null | undefined, commands: editorCommon.ICommand[]): void {
A
Alex Dima 已提交
1104
		if (!this._modelData) {
A
Alex Dima 已提交
1105 1106
			return;
		}
A
Alex Dima 已提交
1107
		this._modelData.cursor.trigger(source, editorCommon.Handler.ExecuteCommands, commands);
A
Alex Dima 已提交
1108 1109 1110
	}

	public changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
A
Alex Dima 已提交
1111
		if (!this._modelData) {
A
Alex Dima 已提交
1112 1113 1114
			// callback will not be called
			return null;
		}
A
Alex Dima 已提交
1115
		return this._modelData.model.changeDecorations(callback, this._id);
A
Alex Dima 已提交
1116 1117
	}

A
Alex Dima 已提交
1118 1119
	public getLineDecorations(lineNumber: number): IModelDecoration[] | null {
		if (!this._modelData) {
A
Alex Dima 已提交
1120 1121
			return null;
		}
1122
		return this._modelData.model.getLineDecorations(lineNumber, this._id, filterValidationDecorations(this._configuration.options));
A
Alex Dima 已提交
1123 1124 1125
	}

	public deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[] {
A
Alex Dima 已提交
1126
		if (!this._modelData) {
A
Alex Dima 已提交
1127 1128 1129 1130 1131 1132 1133
			return [];
		}

		if (oldDecorations.length === 0 && newDecorations.length === 0) {
			return oldDecorations;
		}

A
Alex Dima 已提交
1134
		return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);
A
Alex Dima 已提交
1135 1136 1137 1138
	}

	public setDecorations(decorationTypeKey: string, decorationOptions: editorCommon.IDecorationOptions[]): void {

M
Matt Bierner 已提交
1139 1140
		const newDecorationsSubTypes: { [key: string]: boolean } = {};
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1141 1142
		this._decorationTypeSubtypes[decorationTypeKey] = newDecorationsSubTypes;

M
Matt Bierner 已提交
1143
		const newModelDecorations: IModelDeltaDecoration[] = [];
A
Alex Dima 已提交
1144 1145 1146 1147 1148 1149

		for (let decorationOption of decorationOptions) {
			let typeKey = decorationTypeKey;
			if (decorationOption.renderOptions) {
				// identify custom reder options by a hash code over all keys and values
				// For custom render options register a decoration type if necessary
M
Matt Bierner 已提交
1150
				const subType = hash(decorationOption.renderOptions).toString(16);
A
Alex Dima 已提交
1151 1152 1153 1154 1155 1156 1157 1158 1159
				// The fact that `decorationTypeKey` appears in the typeKey has no influence
				// it is just a mechanism to get predictable and unique keys (repeatable for the same options and unique across clients)
				typeKey = decorationTypeKey + '-' + subType;
				if (!oldDecorationsSubTypes[subType] && !newDecorationsSubTypes[subType]) {
					// decoration type did not exist before, register new one
					this._registerDecorationType(typeKey, decorationOption.renderOptions, decorationTypeKey);
				}
				newDecorationsSubTypes[subType] = true;
			}
M
Matt Bierner 已提交
1160
			const opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage);
A
Alex Dima 已提交
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
			if (decorationOption.hoverMessage) {
				opts.hoverMessage = decorationOption.hoverMessage;
			}
			newModelDecorations.push({ range: decorationOption.range, options: opts });
		}

		// remove decoration sub types that are no longer used, deregister decoration type if necessary
		for (let subType in oldDecorationsSubTypes) {
			if (!newDecorationsSubTypes[subType]) {
				this._removeDecorationType(decorationTypeKey + '-' + subType);
			}
		}

		// update all decorations
M
Matt Bierner 已提交
1175
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1176 1177 1178 1179 1180 1181
		this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations);
	}

	public setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void {

		// remove decoration sub types that are no longer used, deregister decoration type if necessary
M
Matt Bierner 已提交
1182
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1183 1184 1185 1186 1187 1188
		for (let subType in oldDecorationsSubTypes) {
			this._removeDecorationType(decorationTypeKey + '-' + subType);
		}
		this._decorationTypeSubtypes[decorationTypeKey] = {};

		const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false));
M
Matt Bierner 已提交
1189
		const newModelDecorations: IModelDeltaDecoration[] = new Array<IModelDeltaDecoration>(ranges.length);
A
Alex Dima 已提交
1190 1191 1192 1193 1194
		for (let i = 0, len = ranges.length; i < len; i++) {
			newModelDecorations[i] = { range: ranges[i], options: opts };
		}

		// update all decorations
M
Matt Bierner 已提交
1195
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1196 1197 1198 1199 1200
		this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations);
	}

	public removeDecorations(decorationTypeKey: string): void {
		// remove decorations for type and sub type
M
Matt Bierner 已提交
1201
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];
A
Alex Dima 已提交
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
		if (oldDecorationsIds) {
			this.deltaDecorations(oldDecorationsIds, []);
		}
		if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeKeysToIds[decorationTypeKey];
		}
		if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeSubtypes[decorationTypeKey];
		}
	}

1213
	public getLayoutInfo(): EditorLayoutInfo {
A
Alex Dima 已提交
1214
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1215
		const layoutInfo = options.get(EditorOption.layoutInfo);
A
Alex Dima 已提交
1216
		return layoutInfo;
A
Alex Dima 已提交
1217 1218
	}

A
Alex Dima 已提交
1219 1220 1221 1222 1223
	public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler | null {
		if (!this._modelData || !this._modelData.hasRealView) {
			return null;
		}
		return this._modelData.view.createOverviewRuler(cssClassName);
E
Erich Gamma 已提交
1224 1225
	}

1226 1227 1228 1229
	public getContainerDomNode(): HTMLElement {
		return this._domElement;
	}

A
Alex Dima 已提交
1230 1231
	public getDomNode(): HTMLElement | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1232 1233
			return null;
		}
A
Alex Dima 已提交
1234
		return this._modelData.view.domNode.domNode;
E
Erich Gamma 已提交
1235 1236
	}

1237
	public delegateVerticalScrollbarMouseDown(browserEvent: IMouseEvent): void {
A
Alex Dima 已提交
1238
		if (!this._modelData || !this._modelData.hasRealView) {
1239
			return;
E
Erich Gamma 已提交
1240
		}
A
Alex Dima 已提交
1241
		this._modelData.view.delegateVerticalScrollbarMouseDown(browserEvent);
E
Erich Gamma 已提交
1242 1243
	}

J
Johannes Rieken 已提交
1244
	public layout(dimension?: editorCommon.IDimension): void {
E
Erich Gamma 已提交
1245
		this._configuration.observeReferenceElement(dimension);
1246
		this.render();
E
Erich Gamma 已提交
1247 1248 1249
	}

	public focus(): void {
A
Alex Dima 已提交
1250
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1251 1252
			return;
		}
A
Alex Dima 已提交
1253
		this._modelData.view.focus();
E
Erich Gamma 已提交
1254 1255
	}

A
Alex Dima 已提交
1256
	public hasTextFocus(): boolean {
A
Alex Dima 已提交
1257 1258 1259 1260
		if (!this._modelData || !this._modelData.hasRealView) {
			return false;
		}
		return this._modelData.view.isFocused();
E
Erich Gamma 已提交
1261 1262
	}

1263
	public hasWidgetFocus(): boolean {
1264
		return this._focusTracker && this._focusTracker.hasFocus();
1265 1266
	}

A
Alex Dima 已提交
1267
	public addContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1268
		const widgetData: IContentWidgetData = {
E
Erich Gamma 已提交
1269 1270 1271 1272
			widget: widget,
			position: widget.getPosition()
		};

A
Alex Dima 已提交
1273
		if (this._contentWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1274 1275 1276
			console.warn('Overwriting a content widget with the same id.');
		}

A
Alex Dima 已提交
1277
		this._contentWidgets[widget.getId()] = widgetData;
E
Erich Gamma 已提交
1278

A
Alex Dima 已提交
1279 1280
		if (this._modelData && this._modelData.hasRealView) {
			this._modelData.view.addContentWidget(widgetData);
E
Erich Gamma 已提交
1281 1282 1283
		}
	}

A
Alex Dima 已提交
1284
	public layoutContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1285
		const widgetId = widget.getId();
A
Alex Dima 已提交
1286
		if (this._contentWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1287
			const widgetData = this._contentWidgets[widgetId];
E
Erich Gamma 已提交
1288
			widgetData.position = widget.getPosition();
A
Alex Dima 已提交
1289 1290
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.layoutContentWidget(widgetData);
E
Erich Gamma 已提交
1291 1292 1293 1294
			}
		}
	}

A
Alex Dima 已提交
1295
	public removeContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1296
		const widgetId = widget.getId();
A
Alex Dima 已提交
1297
		if (this._contentWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1298
			const widgetData = this._contentWidgets[widgetId];
A
Alex Dima 已提交
1299
			delete this._contentWidgets[widgetId];
A
Alex Dima 已提交
1300 1301
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.removeContentWidget(widgetData);
E
Erich Gamma 已提交
1302 1303 1304 1305
			}
		}
	}

A
Alex Dima 已提交
1306
	public addOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1307
		const widgetData: IOverlayWidgetData = {
E
Erich Gamma 已提交
1308 1309 1310 1311
			widget: widget,
			position: widget.getPosition()
		};

A
Alex Dima 已提交
1312
		if (this._overlayWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1313 1314 1315
			console.warn('Overwriting an overlay widget with the same id.');
		}

A
Alex Dima 已提交
1316
		this._overlayWidgets[widget.getId()] = widgetData;
E
Erich Gamma 已提交
1317

A
Alex Dima 已提交
1318 1319
		if (this._modelData && this._modelData.hasRealView) {
			this._modelData.view.addOverlayWidget(widgetData);
E
Erich Gamma 已提交
1320 1321 1322
		}
	}

A
Alex Dima 已提交
1323
	public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1324
		const widgetId = widget.getId();
A
Alex Dima 已提交
1325
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1326
			const widgetData = this._overlayWidgets[widgetId];
E
Erich Gamma 已提交
1327
			widgetData.position = widget.getPosition();
A
Alex Dima 已提交
1328 1329
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.layoutOverlayWidget(widgetData);
E
Erich Gamma 已提交
1330 1331 1332 1333
			}
		}
	}

A
Alex Dima 已提交
1334
	public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1335
		const widgetId = widget.getId();
A
Alex Dima 已提交
1336
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1337
			const widgetData = this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1338
			delete this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1339 1340
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.removeOverlayWidget(widgetData);
E
Erich Gamma 已提交
1341 1342 1343 1344
			}
		}
	}

J
Johannes Rieken 已提交
1345
	public changeViewZones(callback: (accessor: editorBrowser.IViewZoneChangeAccessor) => void): void {
A
Alex Dima 已提交
1346
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1347 1348
			return;
		}
M
Matt Bierner 已提交
1349
		const hasChanges = this._modelData.view.change(callback);
E
Erich Gamma 已提交
1350
		if (hasChanges) {
A
Alex Dima 已提交
1351
			this._onDidChangeViewZones.fire();
E
Erich Gamma 已提交
1352 1353 1354
		}
	}

A
Alex Dima 已提交
1355 1356
	public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
		if (!this._modelData || !this._modelData.hasRealView) {
1357 1358
			return null;
		}
A
Alex Dima 已提交
1359
		return this._modelData.view.getTargetAtClientPoint(clientX, clientY);
1360 1361
	}

A
Alex Dima 已提交
1362 1363
	public getScrolledVisiblePosition(rawPosition: IPosition): { top: number; left: number; height: number; } | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1364 1365 1366
			return null;
		}

M
Matt Bierner 已提交
1367
		const position = this._modelData.model.validatePosition(rawPosition);
A
Alex Dima 已提交
1368
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1369
		const layoutInfo = options.get(EditorOption.layoutInfo);
E
Erich Gamma 已提交
1370

M
Matt Bierner 已提交
1371 1372
		const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop();
		const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft();
E
Erich Gamma 已提交
1373 1374 1375 1376

		return {
			top: top,
			left: left,
A
Alex Dima 已提交
1377
			height: options.get(EditorOption.lineHeight)
E
Erich Gamma 已提交
1378 1379 1380
		};
	}

J
Johannes Rieken 已提交
1381
	public getOffsetForColumn(lineNumber: number, column: number): number {
A
Alex Dima 已提交
1382
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1383 1384
			return -1;
		}
A
Alex Dima 已提交
1385
		return this._modelData.view.getOffsetForColumn(lineNumber, column);
E
Erich Gamma 已提交
1386 1387
	}

1388
	public render(forceRedraw: boolean = false): void {
A
Alex Dima 已提交
1389
		if (!this._modelData || !this._modelData.hasRealView) {
1390 1391
			return;
		}
1392
		this._modelData.view.render(true, forceRedraw);
1393 1394
	}

I
isidor 已提交
1395
	public setAriaOptions(options: editorBrowser.IEditorAriaOptions): void {
I
isidor 已提交
1396 1397 1398
		if (!this._modelData || !this._modelData.hasRealView) {
			return;
		}
I
isidor 已提交
1399
		this._modelData.view.setAriaOptions(options);
I
isidor 已提交
1400 1401
	}

J
Johannes Rieken 已提交
1402
	public applyFontInfo(target: HTMLElement): void {
1403
		Configuration.applyFontInfoSlow(target, this._configuration.options.get(EditorOption.fontInfo));
1404 1405
	}

A
Alex Dima 已提交
1406 1407 1408 1409 1410
	protected _attachModel(model: ITextModel | null): void {
		if (!model) {
			this._modelData = null;
			return;
		}
E
Erich Gamma 已提交
1411

A
Alex Dima 已提交
1412
		const listenersToRemove: IDisposable[] = [];
A
Alex Dima 已提交
1413

A
Alex Dima 已提交
1414
		this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1415 1416
		this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());
		this._configuration.setMaxLineNumber(model.getLineCount());
A
Alex Dima 已提交
1417

A
Alex Dima 已提交
1418
		model.onBeforeAttached();
A
Alex Dima 已提交
1419

1420 1421 1422 1423
		const viewModel = new ViewModel(
			this._id,
			this._configuration,
			model,
1424
			DOMLineBreaksComputerFactory.create(),
1425
			MonospaceLineBreaksComputerFactory.create(this._configuration.options),
1426 1427
			(callback) => dom.scheduleAtNextAnimationFrame(callback)
		);
A
Alex Dima 已提交
1428

A
Alex Dima 已提交
1429 1430
		listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
		listenersToRemove.push(model.onDidChangeLanguage((e) => {
A
Alex Dima 已提交
1431
			this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1432 1433 1434 1435 1436 1437 1438
			this._onDidChangeModelLanguage.fire(e);
		}));
		listenersToRemove.push(model.onDidChangeLanguageConfiguration((e) => this._onDidChangeModelLanguageConfiguration.fire(e)));
		listenersToRemove.push(model.onDidChangeContent((e) => this._onDidChangeModelContent.fire(e)));
		listenersToRemove.push(model.onDidChangeOptions((e) => this._onDidChangeModelOptions.fire(e)));
		// Someone might destroy the model from under the editor, so prevent any exceptions by setting a null model
		listenersToRemove.push(model.onWillDispose(() => this.setModel(null)));
A
Alex Dima 已提交
1439

A
Alex Dima 已提交
1440
		const cursor = new Cursor(this._configuration, model, viewModel);
A
Alex Dima 已提交
1441

A
Alex Dima 已提交
1442 1443 1444
		listenersToRemove.push(cursor.onDidReachMaxCursorCount(() => {
			this._notificationService.warn(nls.localize('cursors.maximum', "The number of cursors has been limited to {0}.", Cursor.MAX_CURSOR_COUNT));
		}));
A
Alex Dima 已提交
1445

A
Alex Dima 已提交
1446
		listenersToRemove.push(cursor.onDidAttemptReadOnlyEdit(() => {
R
Rob Lourens 已提交
1447
			this._onDidAttemptReadOnlyEdit.fire(undefined);
A
Alex Dima 已提交
1448
		}));
A
Alex Dima 已提交
1449

A
Alex Dima 已提交
1450
		listenersToRemove.push(cursor.onDidChange((e: CursorStateChangedEvent) => {
M
Matt Bierner 已提交
1451
			const positions: Position[] = [];
A
Alex Dima 已提交
1452 1453 1454
			for (let i = 0, len = e.selections.length; i < len; i++) {
				positions[i] = e.selections[i].getPosition();
			}
A
Alex Dima 已提交
1455

A
Alex Dima 已提交
1456 1457 1458 1459 1460 1461 1462
			const e1: ICursorPositionChangedEvent = {
				position: positions[0],
				secondaryPositions: positions.slice(1),
				reason: e.reason,
				source: e.source
			};
			this._onDidChangeCursorPosition.fire(e1);
A
Alex Dima 已提交
1463

A
Alex Dima 已提交
1464 1465 1466
			const e2: ICursorSelectionChangedEvent = {
				selection: e.selections[0],
				secondarySelections: e.selections.slice(1),
1467 1468 1469
				modelVersionId: e.modelVersionId,
				oldSelections: e.oldSelections,
				oldModelVersionId: e.oldModelVersionId,
A
Alex Dima 已提交
1470 1471 1472 1473 1474
				source: e.source,
				reason: e.reason
			};
			this._onDidChangeCursorSelection.fire(e2);
		}));
E
Erich Gamma 已提交
1475

A
Alex Dima 已提交
1476 1477
		const [view, hasRealView] = this._createView(viewModel, cursor);
		if (hasRealView) {
A
Alex Dima 已提交
1478
			this._domElement.appendChild(view.domNode.domNode);
E
Erich Gamma 已提交
1479

A
Alex Dima 已提交
1480
			let keys = Object.keys(this._contentWidgets);
A
Alex Dima 已提交
1481
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1482
				const widgetId = keys[i];
A
Alex Dima 已提交
1483
				view.addContentWidget(this._contentWidgets[widgetId]);
A
Alex Dima 已提交
1484
			}
E
Erich Gamma 已提交
1485

A
Alex Dima 已提交
1486
			keys = Object.keys(this._overlayWidgets);
A
Alex Dima 已提交
1487
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1488
				const widgetId = keys[i];
A
Alex Dima 已提交
1489
				view.addOverlayWidget(this._overlayWidgets[widgetId]);
A
Alex Dima 已提交
1490
			}
E
Erich Gamma 已提交
1491

A
Alex Dima 已提交
1492 1493
			view.render(false, true);
			view.domNode.domNode.setAttribute('data-uri', model.uri.toString());
E
Erich Gamma 已提交
1494
		}
A
Alex Dima 已提交
1495 1496

		this._modelData = new ModelData(model, viewModel, cursor, view, hasRealView, listenersToRemove);
E
Erich Gamma 已提交
1497 1498
	}

A
Alex Dima 已提交
1499
	protected _createView(viewModel: ViewModel, cursor: Cursor): [View, boolean] {
1500 1501 1502
		let commandDelegate: ICommandDelegate;
		if (this.isSimpleWidget) {
			commandDelegate = {
A
Alex Dima 已提交
1503 1504 1505
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
					editorCommand.runCoreEditorCommand(cursor, args);
				},
A
Alex Dima 已提交
1506 1507
				paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {
					this.trigger('keyboard', editorCommon.Handler.Paste, { text, pasteOnNewLine, multicursorText, mode });
1508
				},
A
Alex Dima 已提交
1509 1510
				type: (text: string) => {
					this.trigger('keyboard', editorCommon.Handler.Type, { text });
1511
				},
A
Alex Dima 已提交
1512 1513
				replacePreviousChar: (text: string, replaceCharCnt: number) => {
					this.trigger('keyboard', editorCommon.Handler.ReplacePreviousChar, { text, replaceCharCnt });
1514
				},
A
Alex Dima 已提交
1515 1516
				compositionStart: () => {
					this.trigger('keyboard', editorCommon.Handler.CompositionStart, undefined);
1517
				},
A
Alex Dima 已提交
1518 1519
				compositionEnd: () => {
					this.trigger('keyboard', editorCommon.Handler.CompositionEnd, undefined);
1520
				},
A
Alex Dima 已提交
1521 1522
				cut: () => {
					this.trigger('keyboard', editorCommon.Handler.Cut, undefined);
1523 1524 1525 1526
				}
			};
		} else {
			commandDelegate = {
A
Alex Dima 已提交
1527 1528 1529
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
					editorCommand.runCoreEditorCommand(cursor, args);
				},
A
Alex Dima 已提交
1530
				paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {
1531 1532 1533
					this._commandService.executeCommand(editorCommon.Handler.Paste, {
						text: text,
						pasteOnNewLine: pasteOnNewLine,
1534 1535
						multicursorText: multicursorText,
						mode
1536 1537
					});
				},
A
Alex Dima 已提交
1538
				type: (text: string) => {
1539 1540 1541 1542
					this._commandService.executeCommand(editorCommon.Handler.Type, {
						text: text
					});
				},
A
Alex Dima 已提交
1543
				replacePreviousChar: (text: string, replaceCharCnt: number) => {
1544 1545 1546 1547 1548
					this._commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, {
						text: text,
						replaceCharCnt: replaceCharCnt
					});
				},
A
Alex Dima 已提交
1549
				compositionStart: () => {
1550 1551
					this._commandService.executeCommand(editorCommon.Handler.CompositionStart, {});
				},
A
Alex Dima 已提交
1552
				compositionEnd: () => {
1553 1554
					this._commandService.executeCommand(editorCommon.Handler.CompositionEnd, {});
				},
A
Alex Dima 已提交
1555
				cut: () => {
1556 1557 1558 1559 1560
					this._commandService.executeCommand(editorCommon.Handler.Cut, {});
				}
			};
		}

1561 1562 1563 1564 1565 1566 1567
		const onDidChangeTextFocus = (textFocus: boolean) => {
			if (this._modelData) {
				this._modelData.cursor.setHasFocus(textFocus);
			}
			this._editorTextFocus.setValue(textFocus);
		};

A
Alex Dima 已提交
1568
		const viewOutgoingEvents = new ViewOutgoingEvents(viewModel);
1569
		viewOutgoingEvents.onDidContentSizeChange = (e) => this._onDidContentSizeChange.fire(e);
A
Alex Dima 已提交
1570
		viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
1571 1572
		viewOutgoingEvents.onDidGainFocus = () => onDidChangeTextFocus(true);
		viewOutgoingEvents.onDidLoseFocus = () => onDidChangeTextFocus(false);
A
Alex Dima 已提交
1573 1574 1575 1576 1577 1578 1579 1580
		viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e);
		viewOutgoingEvents.onMouseDown = (e) => this._onMouseDown.fire(e);
		viewOutgoingEvents.onMouseUp = (e) => this._onMouseUp.fire(e);
		viewOutgoingEvents.onMouseDrag = (e) => this._onMouseDrag.fire(e);
		viewOutgoingEvents.onMouseDrop = (e) => this._onMouseDrop.fire(e);
		viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e);
		viewOutgoingEvents.onMouseMove = (e) => this._onMouseMove.fire(e);
		viewOutgoingEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);
1581
		viewOutgoingEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);
A
Alex Dima 已提交
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
		viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e);

		const view = new View(
			commandDelegate,
			this._configuration,
			this._themeService,
			viewModel,
			cursor,
			viewOutgoingEvents
		);
A
Alex Dima 已提交
1592

A
Alex Dima 已提交
1593
		return [view, true];
1594
	}
E
Erich Gamma 已提交
1595

A
Alex Dima 已提交
1596
	protected _postDetachModelCleanup(detachedModel: ITextModel | null): void {
A
Alex Dima 已提交
1597
		if (detachedModel) {
A
Alex Dima 已提交
1598
			detachedModel.removeAllDecorationsWithOwnerId(this._id);
1599 1600 1601
		}
	}

A
Alex Dima 已提交
1602 1603 1604
	private _detachModel(): ITextModel | null {
		if (!this._modelData) {
			return null;
A
Alex Dima 已提交
1605
		}
A
Alex Dima 已提交
1606 1607
		const model = this._modelData.model;
		const removeDomNode = this._modelData.hasRealView ? this._modelData.view.domNode.domNode : null;
A
Alex Dima 已提交
1608

A
Alex Dima 已提交
1609 1610
		this._modelData.dispose();
		this._modelData = null;
A
Alex Dima 已提交
1611

A
Alex Dima 已提交
1612
		this._domElement.removeAttribute('data-mode-id');
1613
		if (removeDomNode && this._domElement.contains(removeDomNode)) {
A
Alex Dima 已提交
1614
			this._domElement.removeChild(removeDomNode);
E
Erich Gamma 已提交
1615 1616
		}

A
Alex Dima 已提交
1617
		return model;
E
Erich Gamma 已提交
1618
	}
1619

A
Alex Dima 已提交
1620
	private _registerDecorationType(key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void {
1621
		this._codeEditorService.registerDecorationType(key, options, parentTypeKey, this);
1622 1623
	}

A
Alex Dima 已提交
1624
	private _removeDecorationType(key: string): void {
1625 1626 1627
		this._codeEditorService.removeDecorationType(key);
	}

A
Alex Dima 已提交
1628
	private _resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions {
1629 1630 1631
		return this._codeEditorService.resolveDecorationOptions(typeKey, writable);
	}

M
Matt Bierner 已提交
1632
	public getTelemetryData(): { [key: string]: any; } | undefined {
1633
		return this._telemetryData;
A
Alex Dima 已提交
1634
	}
A
Alex Dima 已提交
1635 1636 1637 1638

	public hasModel(): this is editorBrowser.IActiveCodeEditor {
		return (this._modelData !== null);
	}
A
Alex Dima 已提交
1639
}
1640

A
Alex Dima 已提交
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
const enum BooleanEventValue {
	NotSet,
	False,
	True
}

export class BooleanEventEmitter extends Disposable {
	private readonly _onDidChangeToTrue: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeToTrue: Event<void> = this._onDidChangeToTrue.event;

	private readonly _onDidChangeToFalse: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeToFalse: Event<void> = this._onDidChangeToFalse.event;

	private _value: BooleanEventValue;

	constructor() {
		super();
		this._value = BooleanEventValue.NotSet;
	}

	public setValue(_value: boolean) {
M
Matt Bierner 已提交
1662
		const value = (_value ? BooleanEventValue.True : BooleanEventValue.False);
A
Alex Dima 已提交
1663 1664
		if (this._value === value) {
			return;
1665
		}
A
Alex Dima 已提交
1666 1667 1668 1669 1670 1671 1672 1673
		this._value = value;
		if (this._value === BooleanEventValue.True) {
			this._onDidChangeToTrue.fire();
		} else if (this._value === BooleanEventValue.False) {
			this._onDidChangeToFalse.fire();
		}
	}
}
1674

A
Alex Dima 已提交
1675 1676
class EditorContextKeysManager extends Disposable {

1677
	private readonly _editor: CodeEditorWidget;
1678
	private readonly _editorSimpleInput: IContextKey<boolean>;
1679 1680 1681 1682 1683
	private readonly _editorFocus: IContextKey<boolean>;
	private readonly _textInputFocus: IContextKey<boolean>;
	private readonly _editorTextFocus: IContextKey<boolean>;
	private readonly _editorTabMovesFocus: IContextKey<boolean>;
	private readonly _editorReadonly: IContextKey<boolean>;
1684
	private readonly _editorColumnSelection: IContextKey<boolean>;
1685 1686 1687 1688
	private readonly _hasMultipleSelections: IContextKey<boolean>;
	private readonly _hasNonEmptySelection: IContextKey<boolean>;
	private readonly _canUndo: IContextKey<boolean>;
	private readonly _canRedo: IContextKey<boolean>;
A
Alex Dima 已提交
1689 1690 1691 1692 1693 1694 1695 1696 1697 1698

	constructor(
		editor: CodeEditorWidget,
		contextKeyService: IContextKeyService
	) {
		super();

		this._editor = editor;

		contextKeyService.createKey('editorId', editor.getId());
1699 1700

		this._editorSimpleInput = EditorContextKeys.editorSimpleInput.bindTo(contextKeyService);
A
Alex Dima 已提交
1701 1702 1703 1704 1705
		this._editorFocus = EditorContextKeys.focus.bindTo(contextKeyService);
		this._textInputFocus = EditorContextKeys.textInputFocus.bindTo(contextKeyService);
		this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService);
		this._editorTabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService);
		this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService);
1706
		this._editorColumnSelection = EditorContextKeys.columnSelection.bindTo(contextKeyService);
A
Alex Dima 已提交
1707 1708
		this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);
		this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);
A
Alex Dima 已提交
1709 1710
		this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);
		this._canRedo = EditorContextKeys.canRedo.bindTo(contextKeyService);
A
Alex Dima 已提交
1711 1712 1713

		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromConfig()));
		this._register(this._editor.onDidChangeCursorSelection(() => this._updateFromSelection()));
A
Alex Dima 已提交
1714 1715
		this._register(this._editor.onDidFocusEditorWidget(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorWidget(() => this._updateFromFocus()));
A
Alex Dima 已提交
1716 1717
		this._register(this._editor.onDidFocusEditorText(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorText(() => this._updateFromFocus()));
A
Alex Dima 已提交
1718 1719
		this._register(this._editor.onDidChangeModel(() => this._updateFromModel()));
		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromModel()));
A
Alex Dima 已提交
1720 1721 1722 1723

		this._updateFromConfig();
		this._updateFromSelection();
		this._updateFromFocus();
A
Alex Dima 已提交
1724
		this._updateFromModel();
1725 1726

		this._editorSimpleInput.set(this._editor.isSimpleWidget);
A
Alex Dima 已提交
1727 1728 1729
	}

	private _updateFromConfig(): void {
1730
		const options = this._editor.getOptions();
A
Alex Dima 已提交
1731

A
renames  
Alex Dima 已提交
1732 1733
		this._editorTabMovesFocus.set(options.get(EditorOption.tabFocusMode));
		this._editorReadonly.set(options.get(EditorOption.readOnly));
1734
		this._editorColumnSelection.set(options.get(EditorOption.columnSelection));
A
Alex Dima 已提交
1735 1736 1737
	}

	private _updateFromSelection(): void {
M
Matt Bierner 已提交
1738
		const selections = this._editor.getSelections();
A
Alex Dima 已提交
1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
		if (!selections) {
			this._hasMultipleSelections.reset();
			this._hasNonEmptySelection.reset();
		} else {
			this._hasMultipleSelections.set(selections.length > 1);
			this._hasNonEmptySelection.set(selections.some(s => !s.isEmpty()));
		}
	}

	private _updateFromFocus(): void {
		this._editorFocus.set(this._editor.hasWidgetFocus() && !this._editor.isSimpleWidget);
A
Alex Dima 已提交
1750 1751
		this._editorTextFocus.set(this._editor.hasTextFocus() && !this._editor.isSimpleWidget);
		this._textInputFocus.set(this._editor.hasTextFocus());
A
Alex Dima 已提交
1752
	}
A
Alex Dima 已提交
1753 1754 1755

	private _updateFromModel(): void {
		const model = this._editor.getModel();
A
Alex Dima 已提交
1756 1757
		this._canUndo.set(Boolean(model && model.canUndo()));
		this._canRedo.set(Boolean(model && model.canRedo()));
A
Alex Dima 已提交
1758
	}
A
Alex Dima 已提交
1759 1760 1761 1762
}

export class EditorModeContext extends Disposable {

1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
	private readonly _langId: IContextKey<string>;
	private readonly _hasCompletionItemProvider: IContextKey<boolean>;
	private readonly _hasCodeActionsProvider: IContextKey<boolean>;
	private readonly _hasCodeLensProvider: IContextKey<boolean>;
	private readonly _hasDefinitionProvider: IContextKey<boolean>;
	private readonly _hasDeclarationProvider: IContextKey<boolean>;
	private readonly _hasImplementationProvider: IContextKey<boolean>;
	private readonly _hasTypeDefinitionProvider: IContextKey<boolean>;
	private readonly _hasHoverProvider: IContextKey<boolean>;
	private readonly _hasDocumentHighlightProvider: IContextKey<boolean>;
	private readonly _hasDocumentSymbolProvider: IContextKey<boolean>;
	private readonly _hasReferenceProvider: IContextKey<boolean>;
	private readonly _hasRenameProvider: IContextKey<boolean>;
	private readonly _hasDocumentFormattingProvider: IContextKey<boolean>;
	private readonly _hasDocumentSelectionFormattingProvider: IContextKey<boolean>;
1778 1779
	private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;
	private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;
1780 1781
	private readonly _hasSignatureHelpProvider: IContextKey<boolean>;
	private readonly _isInWalkThrough: IContextKey<boolean>;
A
Alex Dima 已提交
1782 1783

	constructor(
1784 1785
		private readonly _editor: CodeEditorWidget,
		private readonly _contextKeyService: IContextKeyService
A
Alex Dima 已提交
1786 1787 1788
	) {
		super();

1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
		this._langId = EditorContextKeys.languageId.bindTo(_contextKeyService);
		this._hasCompletionItemProvider = EditorContextKeys.hasCompletionItemProvider.bindTo(_contextKeyService);
		this._hasCodeActionsProvider = EditorContextKeys.hasCodeActionsProvider.bindTo(_contextKeyService);
		this._hasCodeLensProvider = EditorContextKeys.hasCodeLensProvider.bindTo(_contextKeyService);
		this._hasDefinitionProvider = EditorContextKeys.hasDefinitionProvider.bindTo(_contextKeyService);
		this._hasDeclarationProvider = EditorContextKeys.hasDeclarationProvider.bindTo(_contextKeyService);
		this._hasImplementationProvider = EditorContextKeys.hasImplementationProvider.bindTo(_contextKeyService);
		this._hasTypeDefinitionProvider = EditorContextKeys.hasTypeDefinitionProvider.bindTo(_contextKeyService);
		this._hasHoverProvider = EditorContextKeys.hasHoverProvider.bindTo(_contextKeyService);
		this._hasDocumentHighlightProvider = EditorContextKeys.hasDocumentHighlightProvider.bindTo(_contextKeyService);
		this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(_contextKeyService);
		this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(_contextKeyService);
		this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(_contextKeyService);
		this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(_contextKeyService);
		this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(_contextKeyService);
		this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
		this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);
		this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
1807
		this._isInWalkThrough = EditorContextKeys.isInWalkThroughSnippet.bindTo(_contextKeyService);
A
Alex Dima 已提交
1808 1809 1810 1811

		const update = () => this._update();

		// update when model/mode changes
1812 1813
		this._register(_editor.onDidChangeModel(update));
		this._register(_editor.onDidChangeModelLanguage(update));
A
Alex Dima 已提交
1814 1815

		// update when registries change
1816
		this._register(modes.CompletionProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1817 1818 1819
		this._register(modes.CodeActionProviderRegistry.onDidChange(update));
		this._register(modes.CodeLensProviderRegistry.onDidChange(update));
		this._register(modes.DefinitionProviderRegistry.onDidChange(update));
1820
		this._register(modes.DeclarationProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
		this._register(modes.ImplementationProviderRegistry.onDidChange(update));
		this._register(modes.TypeDefinitionProviderRegistry.onDidChange(update));
		this._register(modes.HoverProviderRegistry.onDidChange(update));
		this._register(modes.DocumentHighlightProviderRegistry.onDidChange(update));
		this._register(modes.DocumentSymbolProviderRegistry.onDidChange(update));
		this._register(modes.ReferenceProviderRegistry.onDidChange(update));
		this._register(modes.RenameProviderRegistry.onDidChange(update));
		this._register(modes.DocumentFormattingEditProviderRegistry.onDidChange(update));
		this._register(modes.DocumentRangeFormattingEditProviderRegistry.onDidChange(update));
		this._register(modes.SignatureHelpProviderRegistry.onDidChange(update));

		update();
	}

	dispose() {
		super.dispose();
	}

	reset() {
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858
		this._contextKeyService.bufferChangeEvents(() => {
			this._langId.reset();
			this._hasCompletionItemProvider.reset();
			this._hasCodeActionsProvider.reset();
			this._hasCodeLensProvider.reset();
			this._hasDefinitionProvider.reset();
			this._hasDeclarationProvider.reset();
			this._hasImplementationProvider.reset();
			this._hasTypeDefinitionProvider.reset();
			this._hasHoverProvider.reset();
			this._hasDocumentHighlightProvider.reset();
			this._hasDocumentSymbolProvider.reset();
			this._hasReferenceProvider.reset();
			this._hasRenameProvider.reset();
			this._hasDocumentFormattingProvider.reset();
			this._hasDocumentSelectionFormattingProvider.reset();
			this._hasSignatureHelpProvider.reset();
			this._isInWalkThrough.reset();
		});
A
Alex Dima 已提交
1859 1860 1861 1862 1863 1864 1865 1866
	}

	private _update() {
		const model = this._editor.getModel();
		if (!model) {
			this.reset();
			return;
		}
1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
		this._contextKeyService.bufferChangeEvents(() => {
			this._langId.set(model.getLanguageIdentifier().language);
			this._hasCompletionItemProvider.set(modes.CompletionProviderRegistry.has(model));
			this._hasCodeActionsProvider.set(modes.CodeActionProviderRegistry.has(model));
			this._hasCodeLensProvider.set(modes.CodeLensProviderRegistry.has(model));
			this._hasDefinitionProvider.set(modes.DefinitionProviderRegistry.has(model));
			this._hasDeclarationProvider.set(modes.DeclarationProviderRegistry.has(model));
			this._hasImplementationProvider.set(modes.ImplementationProviderRegistry.has(model));
			this._hasTypeDefinitionProvider.set(modes.TypeDefinitionProviderRegistry.has(model));
			this._hasHoverProvider.set(modes.HoverProviderRegistry.has(model));
			this._hasDocumentHighlightProvider.set(modes.DocumentHighlightProviderRegistry.has(model));
			this._hasDocumentSymbolProvider.set(modes.DocumentSymbolProviderRegistry.has(model));
			this._hasReferenceProvider.set(modes.ReferenceProviderRegistry.has(model));
			this._hasRenameProvider.set(modes.RenameProviderRegistry.has(model));
			this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model));
			this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model));
			this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model));
J
Johannes Rieken 已提交
1884
			this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length + modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
1885 1886 1887
			this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
			this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
		});
1888
	}
E
Erich Gamma 已提交
1889 1890
}

1891 1892
class CodeEditorWidgetFocusTracker extends Disposable {

1893
	private _hasFocus: boolean;
1894
	private readonly _domFocusTracker: dom.IFocusTracker;
1895

M
Matt Bierner 已提交
1896
	private readonly _onChange: Emitter<void> = this._register(new Emitter<void>());
1897
	public readonly onChange: Event<void> = this._onChange.event;
1898

J
Johannes Rieken 已提交
1899
	constructor(domElement: HTMLElement) {
1900 1901
		super();

1902 1903
		this._hasFocus = false;
		this._domFocusTracker = this._register(dom.trackFocus(domElement));
1904

1905
		this._register(this._domFocusTracker.onDidFocus(() => {
1906
			this._hasFocus = true;
R
Rob Lourens 已提交
1907
			this._onChange.fire(undefined);
1908 1909
		}));
		this._register(this._domFocusTracker.onDidBlur(() => {
1910
			this._hasFocus = false;
R
Rob Lourens 已提交
1911
			this._onChange.fire(undefined);
1912
		}));
1913 1914 1915
	}

	public hasFocus(): boolean {
1916
		return this._hasFocus;
1917
	}
1918 1919 1920 1921 1922 1923

	public refreshState(): void {
		if (this._domFocusTracker.refreshState) {
			this._domFocusTracker.refreshState();
		}
	}
1924
}
1925

1926
const 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='`);
1927
const 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>`);
1928

1929 1930 1931
function getSquigglySVGData(color: Color) {
	return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd;
}
1932

1933 1934 1935 1936 1937 1938 1939
const dotdotdotStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" height="3" width="12"><g fill="`);
const 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>`);

function getDotDotDotSVGData(color: Color) {
	return dotdotdotStart + encodeURIComponent(color.toString()) + dotdotdotEnd;
}

1940
registerThemingParticipant((theme, collector) => {
M
Matt Bierner 已提交
1941
	const errorBorderColor = theme.getColor(editorErrorBorder);
1942
	if (errorBorderColor) {
1943
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { border-bottom: 4px double ${errorBorderColor}; }`);
1944
	}
M
Matt Bierner 已提交
1945
	const errorForeground = theme.getColor(editorErrorForeground);
1946
	if (errorForeground) {
1947
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);
1948 1949
	}

M
Matt Bierner 已提交
1950
	const warningBorderColor = theme.getColor(editorWarningBorder);
1951
	if (warningBorderColor) {
1952
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { border-bottom: 4px double ${warningBorderColor}; }`);
1953
	}
M
Matt Bierner 已提交
1954
	const warningForeground = theme.getColor(editorWarningForeground);
1955
	if (warningForeground) {
1956
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);
1957 1958
	}

M
Matt Bierner 已提交
1959
	const infoBorderColor = theme.getColor(editorInfoBorder);
1960 1961
	if (infoBorderColor) {
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { border-bottom: 4px double ${infoBorderColor}; }`);
1962
	}
M
Matt Bierner 已提交
1963
	const infoForeground = theme.getColor(editorInfoForeground);
1964
	if (infoForeground) {
1965
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);
1966
	}
1967

M
Matt Bierner 已提交
1968
	const hintBorderColor = theme.getColor(editorHintBorder);
1969
	if (hintBorderColor) {
1970
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { border-bottom: 2px dotted ${hintBorderColor}; }`);
1971
	}
M
Matt Bierner 已提交
1972
	const hintForeground = theme.getColor(editorHintForeground);
1973
	if (hintForeground) {
1974
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`);
1975
	}
1976

1977
	const unnecessaryForeground = theme.getColor(editorUnnecessaryCodeOpacity);
1978
	if (unnecessaryForeground) {
1979
		collector.addRule(`.monaco-editor.showUnused .${ClassName.EditorUnnecessaryInlineDecoration} { opacity: ${unnecessaryForeground.rgba.a}; }`);
1980 1981 1982 1983
	}

	const unnecessaryBorder = theme.getColor(editorUnnecessaryCodeBorder);
	if (unnecessaryBorder) {
1984
		collector.addRule(`.monaco-editor.showUnused .${ClassName.EditorUnnecessaryDecoration} { border-bottom: 2px dashed ${unnecessaryBorder}; }`);
1985
	}
K
Kamran Ayub 已提交
1986

1987 1988
	const deprecatedForeground = theme.getColor(editorForeground) || 'inherit';
	collector.addRule(`.monaco-editor .${ClassName.EditorDeprecatedInlineDecoration} { text-decoration: line-through; text-decoration-color: ${deprecatedForeground}}`);
1989
});