codeEditorWidget.ts 76.1 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';
27
import { CursorColumns } 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';
A
Alex Dima 已提交
56
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
E
Erich Gamma 已提交
57

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

60 61 62 63 64 65 66 67 68 69 70
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().
	 */
71
	contributions?: IEditorContributionDescription[];
72 73 74 75 76 77 78 79

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

A
Alex Dima 已提交
80 81 82 83 84 85 86
class ModelData {
	public readonly model: ITextModel;
	public readonly viewModel: ViewModel;
	public readonly view: View;
	public readonly hasRealView: boolean;
	public readonly listenersToRemove: IDisposable[];

87
	constructor(model: ITextModel, viewModel: ViewModel, view: View, hasRealView: boolean, listenersToRemove: IDisposable[]) {
A
Alex Dima 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
		this.model = model;
		this.viewModel = viewModel;
		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.viewModel.dispose();
	}
}

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

	//#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;

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

	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;

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

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

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

	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;

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

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

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

A
Alex Dima 已提交
167 168 169 170 171 172 173 174 175
	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 已提交
176 177
	private readonly _onMouseDrop: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseDrop: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseDrop.event;
A
Alex Dima 已提交
178 179 180 181 182 183 184

	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 已提交
185 186
	private readonly _onMouseLeave: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseLeave: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseLeave.event;
A
Alex Dima 已提交
187

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

A
Alex Dima 已提交
191 192 193 194 195 196
	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;

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

A
Alex Dima 已提交
200 201 202 203 204
	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 已提交
205
	//#endregion
A
Alex Dima 已提交
206

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

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

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

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

A
Alex Dima 已提交
220 221 222 223 224 225 226
	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 已提交
227
	private readonly _focusTracker: CodeEditorWidgetFocusTracker;
228

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

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

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

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

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

A
Alex Dima 已提交
270
		this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));
A
Alex Dima 已提交
271
		this._notificationService = notificationService;
272
		this._codeEditorService = codeEditorService;
273
		this._commandService = commandService;
274
		this._themeService = themeService;
A
Alex Dima 已提交
275 276 277 278 279
		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 已提交
280
		this._modelData = null;
A
Alex Dima 已提交
281 282 283

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

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

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

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

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

		this._codeEditorService.addCodeEditor(this);
E
Erich Gamma 已提交
325 326
	}

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

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

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

	public dispose(): void {
340 341
		this._codeEditorService.removeCodeEditor(this);

342
		this._focusTracker.dispose();
A
Alex Dima 已提交
343

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

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

		this._onDidDispose.fire();

E
Erich Gamma 已提交
355 356 357
		super.dispose();
	}

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

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

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

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

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

378 379 380 381 382 383 384
	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 已提交
385 386 387
	public getValue(options: { preserveBOM: boolean; lineEnding: string; } | null = null): string {
		if (!this._modelData) {
			return '';
A
Alex Dima 已提交
388
		}
A
Alex Dima 已提交
389

M
Matt Bierner 已提交
390
		const preserveBOM: boolean = (options && options.preserveBOM) ? true : false;
A
Alex Dima 已提交
391 392 393 394 395 396 397
		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 已提交
398 399 400
	}

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

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

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

M
Matt Bierner 已提交
431
		const e: editorCommon.IModelChangedEvent = {
A
Alex Dima 已提交
432 433 434 435 436 437 438 439 440 441 442 443 444
			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 已提交
445
				const subTypes = this._decorationTypeSubtypes[decorationType];
A
Alex Dima 已提交
446 447 448 449 450 451 452 453 454
				for (let subType in subTypes) {
					this._removeDecorationType(decorationType + '-' + subType);
				}
			}
			this._decorationTypeSubtypes = {};
		}
	}

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

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

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

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

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

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

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

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

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

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

515 516 517 518 519 520 521 522 523 524 525
	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 已提交
526 527
	public getPosition(): Position | null {
		if (!this._modelData) {
A
Alex Dima 已提交
528 529
			return null;
		}
530
		return this._modelData.viewModel.getPosition();
A
Alex Dima 已提交
531 532 533
	}

	public setPosition(position: IPosition): void {
A
Alex Dima 已提交
534
		if (!this._modelData) {
A
Alex Dima 已提交
535 536 537 538 539
			return;
		}
		if (!Position.isIPosition(position)) {
			throw new Error('Invalid arguments');
		}
540
		this._modelData.viewModel.setSelections('api', [{
A
Alex Dima 已提交
541 542 543 544 545 546 547 548
			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 已提交
549
		if (!this._modelData) {
A
Alex Dima 已提交
550 551 552 553 554
			return;
		}
		if (!Range.isIRange(modelRange)) {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
555 556
		const validatedModelRange = this._modelData.model.validateRange(modelRange);
		const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);
A
Alex Dima 已提交
557

558
		this._modelData.viewModel.revealRange('api', revealHorizontal, viewRange, verticalType, scrollType);
A
Alex Dima 已提交
559 560 561 562 563 564 565 566 567 568 569 570 571 572
	}

	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);
	}

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

A
Alex Dima 已提交
577 578 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
	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
		);
	}

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

A
Alex Dima 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638
	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 已提交
639 640
	public getSelection(): Selection | null {
		if (!this._modelData) {
A
Alex Dima 已提交
641 642
			return null;
		}
643
		return this._modelData.viewModel.getSelection();
A
Alex Dima 已提交
644 645
	}

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

	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 已提交
658 659
		const isSelection = Selection.isISelection(something);
		const isRange = Range.isIRange(something);
A
Alex Dima 已提交
660 661 662 663 664 665 666 667 668

		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 已提交
669
			const selection: ISelection = {
A
Alex Dima 已提交
670 671 672 673 674 675 676 677 678 679
				selectionStartLineNumber: something.startLineNumber,
				selectionStartColumn: something.startColumn,
				positionLineNumber: something.endLineNumber,
				positionColumn: something.endColumn
			};
			this._setSelectionImpl(selection);
		}
	}

	private _setSelectionImpl(sel: ISelection): void {
A
Alex Dima 已提交
680
		if (!this._modelData) {
A
Alex Dima 已提交
681 682
			return;
		}
M
Matt Bierner 已提交
683
		const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);
684
		this._modelData.viewModel.setSelections('api', [selection]);
A
Alex Dima 已提交
685 686 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
	}

	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
		);
	}

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

A
Alex Dima 已提交
723 724 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
	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
		);
	}

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

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

A
Alex Dima 已提交
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
	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
		);
	}

803
	public setSelections(ranges: readonly ISelection[], source: string = 'api'): void {
A
Alex Dima 已提交
804
		if (!this._modelData) {
A
Alex Dima 已提交
805 806 807 808 809 810 811 812 813 814
			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');
			}
		}
815
		this._modelData.viewModel.setSelections(source, ranges);
A
Alex Dima 已提交
816 817
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

M
Matt Bierner 已提交
955
		const keys = Object.keys(this._actions);
A
Alex Dima 已提交
956
		for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
957
			const id = keys[i];
A
Alex Dima 已提交
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
			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 已提交
976
	public trigger(source: string | null | undefined, handlerId: string, payload: any): void {
A
Alex Dima 已提交
977 978
		payload = payload || {};

979 980 981 982 983 984 985 986 987 988
		switch (handlerId) {
			case editorCommon.Handler.CompositionStart:
				this._startComposition();
				return;
			case editorCommon.Handler.CompositionEnd:
				this._endComposition(source);
				return;
			case editorCommon.Handler.Type: {
				const args = <Partial<editorCommon.TypePayload>>payload;
				this._type(source, args.text || '');
A
Alex Dima 已提交
989 990
				return;
			}
991 992 993
			case editorCommon.Handler.ReplacePreviousChar: {
				const args = <Partial<editorCommon.ReplacePreviousCharPayload>>payload;
				this._replacePreviousChar(source, args.text || '', args.replaceCharCnt || 0);
A
Alex Dima 已提交
994 995
				return;
			}
996 997 998 999
			case editorCommon.Handler.Paste: {
				const args = <Partial<editorCommon.PastePayload>>payload;
				this._paste(source, args.text || '', args.pasteOnNewLine || false, args.multicursorText || null, args.mode || null);
				return;
A
Alex Dima 已提交
1000
			}
1001 1002 1003
			case editorCommon.Handler.Cut:
				this._cut(source);
				return;
A
Alex Dima 已提交
1004 1005 1006 1007
		}

		const action = this.getAction(handlerId);
		if (action) {
R
Rob Lourens 已提交
1008
			Promise.resolve(action.run()).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
1009 1010 1011
			return;
		}

A
Alex Dima 已提交
1012
		if (!this._modelData) {
A
Alex Dima 已提交
1013 1014 1015 1016 1017 1018
			return;
		}

		if (this._triggerEditorCommand(source, handlerId, payload)) {
			return;
		}
1019
	}
A
Alex Dima 已提交
1020

1021 1022 1023 1024
	private _startComposition(): void {
		if (!this._modelData) {
			return;
		}
1025
		this._modelData.viewModel.startComposition();
1026 1027 1028 1029 1030 1031 1032
		this._onDidCompositionStart.fire();
	}

	private _endComposition(source: string | null | undefined): void {
		if (!this._modelData) {
			return;
		}
1033
		this._modelData.viewModel.endComposition(source);
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
		this._onDidCompositionEnd.fire();
	}

	private _type(source: string | null | undefined, text: string): void {
		if (!this._modelData || text.length === 0) {
			return;
		}
		if (source === 'keyboard') {
			this._onWillType.fire(text);
		}
1044
		this._modelData.viewModel.type(text, source);
1045 1046 1047 1048 1049 1050 1051 1052
		if (source === 'keyboard') {
			this._onDidType.fire(text);
		}
	}

	private _replacePreviousChar(source: string | null | undefined, text: string, replaceCharCnt: number): void {
		if (!this._modelData) {
			return;
A
Alex Dima 已提交
1053
		}
1054
		this._modelData.viewModel.replacePreviousChar(text, replaceCharCnt, source);
1055
	}
1056

1057 1058 1059
	private _paste(source: string | null | undefined, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null): void {
		if (!this._modelData || text.length === 0) {
			return;
1060
		}
1061
		const startPosition = this._modelData.viewModel.getSelection().getStartPosition();
1062
		this._modelData.viewModel.paste(text, pasteOnNewLine, multicursorText, source);
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
		const endPosition = this._modelData.viewModel.getSelection().getStartPosition();
		if (source === 'keyboard') {
			this._onDidPaste.fire({
				range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
				mode: mode
			});
		}
	}

	private _cut(source: string | null | undefined): void {
		if (!this._modelData) {
			return;
1075
		}
1076
		this._modelData.viewModel.cut(source);
A
Alex Dima 已提交
1077 1078
	}

A
Alex Dima 已提交
1079
	private _triggerEditorCommand(source: string | null | undefined, handlerId: string, payload: any): boolean {
A
Alex Dima 已提交
1080 1081 1082 1083
		const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
		if (command) {
			payload = payload || {};
			payload.source = source;
A
Alex Dima 已提交
1084
			this._instantiationService.invokeFunction((accessor) => {
R
Rob Lourens 已提交
1085
				Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
1086
			});
A
Alex Dima 已提交
1087 1088 1089 1090 1091 1092
			return true;
		}

		return false;
	}

A
Alex Dima 已提交
1093 1094 1095 1096 1097 1098 1099
	public _getViewModel(): IViewModel | null {
		if (!this._modelData) {
			return null;
		}
		return this._modelData.viewModel;
	}

A
Alex Dima 已提交
1100
	public pushUndoStop(): boolean {
A
Alex Dima 已提交
1101
		if (!this._modelData) {
A
Alex Dima 已提交
1102 1103
			return false;
		}
A
renames  
Alex Dima 已提交
1104
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
1105 1106 1107
			// read only editor => sorry!
			return false;
		}
A
Alex Dima 已提交
1108
		this._modelData.model.pushStackElement();
A
Alex Dima 已提交
1109 1110 1111
		return true;
	}

A
Alex Dima 已提交
1112
	public executeEdits(source: string | null | undefined, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean {
A
Alex Dima 已提交
1113
		if (!this._modelData) {
A
Alex Dima 已提交
1114 1115
			return false;
		}
A
renames  
Alex Dima 已提交
1116
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
1117 1118 1119 1120
			// read only editor => sorry!
			return false;
		}

1121 1122 1123 1124 1125 1126 1127
		let cursorStateComputer: ICursorStateComputer;
		if (!endCursorState) {
			cursorStateComputer = () => null;
		} else if (Array.isArray(endCursorState)) {
			cursorStateComputer = () => endCursorState;
		} else {
			cursorStateComputer = endCursorState;
A
Alex Dima 已提交
1128 1129
		}

1130
		this._modelData.viewModel.executeEdits(source, edits, cursorStateComputer);
A
Alex Dima 已提交
1131 1132 1133
		return true;
	}

A
Alex Dima 已提交
1134
	public executeCommand(source: string | null | undefined, command: editorCommon.ICommand): void {
A
Alex Dima 已提交
1135
		if (!this._modelData) {
A
Alex Dima 已提交
1136 1137
			return;
		}
1138
		this._modelData.viewModel.executeCommand(command, source);
A
Alex Dima 已提交
1139 1140
	}

A
Alex Dima 已提交
1141
	public executeCommands(source: string | null | undefined, commands: editorCommon.ICommand[]): void {
A
Alex Dima 已提交
1142
		if (!this._modelData) {
A
Alex Dima 已提交
1143 1144
			return;
		}
1145
		this._modelData.viewModel.executeCommands(commands, source);
A
Alex Dima 已提交
1146 1147 1148
	}

	public changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
A
Alex Dima 已提交
1149
		if (!this._modelData) {
A
Alex Dima 已提交
1150 1151 1152
			// callback will not be called
			return null;
		}
A
Alex Dima 已提交
1153
		return this._modelData.model.changeDecorations(callback, this._id);
A
Alex Dima 已提交
1154 1155
	}

A
Alex Dima 已提交
1156 1157
	public getLineDecorations(lineNumber: number): IModelDecoration[] | null {
		if (!this._modelData) {
A
Alex Dima 已提交
1158 1159
			return null;
		}
1160
		return this._modelData.model.getLineDecorations(lineNumber, this._id, filterValidationDecorations(this._configuration.options));
A
Alex Dima 已提交
1161 1162 1163
	}

	public deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[] {
A
Alex Dima 已提交
1164
		if (!this._modelData) {
A
Alex Dima 已提交
1165 1166 1167 1168 1169 1170 1171
			return [];
		}

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

A
Alex Dima 已提交
1172
		return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);
A
Alex Dima 已提交
1173 1174 1175 1176
	}

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

M
Matt Bierner 已提交
1177 1178
		const newDecorationsSubTypes: { [key: string]: boolean } = {};
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1179 1180
		this._decorationTypeSubtypes[decorationTypeKey] = newDecorationsSubTypes;

M
Matt Bierner 已提交
1181
		const newModelDecorations: IModelDeltaDecoration[] = [];
A
Alex Dima 已提交
1182 1183 1184 1185 1186 1187

		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 已提交
1188
				const subType = hash(decorationOption.renderOptions).toString(16);
A
Alex Dima 已提交
1189 1190 1191 1192 1193 1194 1195 1196 1197
				// 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 已提交
1198
			const opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage);
A
Alex Dima 已提交
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
			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 已提交
1213
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1214 1215 1216 1217 1218 1219
		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 已提交
1220
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1221 1222 1223 1224 1225 1226
		for (let subType in oldDecorationsSubTypes) {
			this._removeDecorationType(decorationTypeKey + '-' + subType);
		}
		this._decorationTypeSubtypes[decorationTypeKey] = {};

		const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false));
M
Matt Bierner 已提交
1227
		const newModelDecorations: IModelDeltaDecoration[] = new Array<IModelDeltaDecoration>(ranges.length);
A
Alex Dima 已提交
1228 1229 1230 1231 1232
		for (let i = 0, len = ranges.length; i < len; i++) {
			newModelDecorations[i] = { range: ranges[i], options: opts };
		}

		// update all decorations
M
Matt Bierner 已提交
1233
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1234 1235 1236 1237 1238
		this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations);
	}

	public removeDecorations(decorationTypeKey: string): void {
		// remove decorations for type and sub type
M
Matt Bierner 已提交
1239
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];
A
Alex Dima 已提交
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
		if (oldDecorationsIds) {
			this.deltaDecorations(oldDecorationsIds, []);
		}
		if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeKeysToIds[decorationTypeKey];
		}
		if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeSubtypes[decorationTypeKey];
		}
	}

1251
	public getLayoutInfo(): EditorLayoutInfo {
A
Alex Dima 已提交
1252
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1253
		const layoutInfo = options.get(EditorOption.layoutInfo);
A
Alex Dima 已提交
1254
		return layoutInfo;
A
Alex Dima 已提交
1255 1256
	}

A
Alex Dima 已提交
1257 1258 1259 1260 1261
	public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler | null {
		if (!this._modelData || !this._modelData.hasRealView) {
			return null;
		}
		return this._modelData.view.createOverviewRuler(cssClassName);
E
Erich Gamma 已提交
1262 1263
	}

1264 1265 1266 1267
	public getContainerDomNode(): HTMLElement {
		return this._domElement;
	}

A
Alex Dima 已提交
1268 1269
	public getDomNode(): HTMLElement | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1270 1271
			return null;
		}
A
Alex Dima 已提交
1272
		return this._modelData.view.domNode.domNode;
E
Erich Gamma 已提交
1273 1274
	}

1275
	public delegateVerticalScrollbarMouseDown(browserEvent: IMouseEvent): void {
A
Alex Dima 已提交
1276
		if (!this._modelData || !this._modelData.hasRealView) {
1277
			return;
E
Erich Gamma 已提交
1278
		}
A
Alex Dima 已提交
1279
		this._modelData.view.delegateVerticalScrollbarMouseDown(browserEvent);
E
Erich Gamma 已提交
1280 1281
	}

J
Johannes Rieken 已提交
1282
	public layout(dimension?: editorCommon.IDimension): void {
E
Erich Gamma 已提交
1283
		this._configuration.observeReferenceElement(dimension);
1284
		this.render();
E
Erich Gamma 已提交
1285 1286 1287
	}

	public focus(): void {
A
Alex Dima 已提交
1288
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1289 1290
			return;
		}
A
Alex Dima 已提交
1291
		this._modelData.view.focus();
E
Erich Gamma 已提交
1292 1293
	}

A
Alex Dima 已提交
1294
	public hasTextFocus(): boolean {
A
Alex Dima 已提交
1295 1296 1297 1298
		if (!this._modelData || !this._modelData.hasRealView) {
			return false;
		}
		return this._modelData.view.isFocused();
E
Erich Gamma 已提交
1299 1300
	}

1301
	public hasWidgetFocus(): boolean {
1302
		return this._focusTracker && this._focusTracker.hasFocus();
1303 1304
	}

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

A
Alex Dima 已提交
1311
		if (this._contentWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1312 1313 1314
			console.warn('Overwriting a content widget with the same id.');
		}

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

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

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

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

A
Alex Dima 已提交
1344
	public addOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1345
		const widgetData: IOverlayWidgetData = {
E
Erich Gamma 已提交
1346 1347 1348 1349
			widget: widget,
			position: widget.getPosition()
		};

A
Alex Dima 已提交
1350
		if (this._overlayWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1351 1352 1353
			console.warn('Overwriting an overlay widget with the same id.');
		}

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

A
Alex Dima 已提交
1356 1357
		if (this._modelData && this._modelData.hasRealView) {
			this._modelData.view.addOverlayWidget(widgetData);
E
Erich Gamma 已提交
1358 1359 1360
		}
	}

A
Alex Dima 已提交
1361
	public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1362
		const widgetId = widget.getId();
A
Alex Dima 已提交
1363
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1364
			const widgetData = this._overlayWidgets[widgetId];
E
Erich Gamma 已提交
1365
			widgetData.position = widget.getPosition();
A
Alex Dima 已提交
1366 1367
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.layoutOverlayWidget(widgetData);
E
Erich Gamma 已提交
1368 1369 1370 1371
			}
		}
	}

A
Alex Dima 已提交
1372
	public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1373
		const widgetId = widget.getId();
A
Alex Dima 已提交
1374
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1375
			const widgetData = this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1376
			delete this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1377 1378
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.removeOverlayWidget(widgetData);
E
Erich Gamma 已提交
1379 1380 1381 1382
			}
		}
	}

J
Johannes Rieken 已提交
1383
	public changeViewZones(callback: (accessor: editorBrowser.IViewZoneChangeAccessor) => void): void {
A
Alex Dima 已提交
1384
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1385 1386
			return;
		}
M
Matt Bierner 已提交
1387
		const hasChanges = this._modelData.view.change(callback);
E
Erich Gamma 已提交
1388
		if (hasChanges) {
A
Alex Dima 已提交
1389
			this._onDidChangeViewZones.fire();
E
Erich Gamma 已提交
1390 1391 1392
		}
	}

A
Alex Dima 已提交
1393 1394
	public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
		if (!this._modelData || !this._modelData.hasRealView) {
1395 1396
			return null;
		}
A
Alex Dima 已提交
1397
		return this._modelData.view.getTargetAtClientPoint(clientX, clientY);
1398 1399
	}

A
Alex Dima 已提交
1400 1401
	public getScrolledVisiblePosition(rawPosition: IPosition): { top: number; left: number; height: number; } | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1402 1403 1404
			return null;
		}

M
Matt Bierner 已提交
1405
		const position = this._modelData.model.validatePosition(rawPosition);
A
Alex Dima 已提交
1406
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1407
		const layoutInfo = options.get(EditorOption.layoutInfo);
E
Erich Gamma 已提交
1408

M
Matt Bierner 已提交
1409 1410
		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 已提交
1411 1412 1413 1414

		return {
			top: top,
			left: left,
A
Alex Dima 已提交
1415
			height: options.get(EditorOption.lineHeight)
E
Erich Gamma 已提交
1416 1417 1418
		};
	}

J
Johannes Rieken 已提交
1419
	public getOffsetForColumn(lineNumber: number, column: number): number {
A
Alex Dima 已提交
1420
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1421 1422
			return -1;
		}
A
Alex Dima 已提交
1423
		return this._modelData.view.getOffsetForColumn(lineNumber, column);
E
Erich Gamma 已提交
1424 1425
	}

1426
	public render(forceRedraw: boolean = false): void {
A
Alex Dima 已提交
1427
		if (!this._modelData || !this._modelData.hasRealView) {
1428 1429
			return;
		}
1430
		this._modelData.view.render(true, forceRedraw);
1431 1432
	}

I
isidor 已提交
1433
	public setAriaOptions(options: editorBrowser.IEditorAriaOptions): void {
I
isidor 已提交
1434 1435 1436
		if (!this._modelData || !this._modelData.hasRealView) {
			return;
		}
I
isidor 已提交
1437
		this._modelData.view.setAriaOptions(options);
I
isidor 已提交
1438 1439
	}

J
Johannes Rieken 已提交
1440
	public applyFontInfo(target: HTMLElement): void {
1441
		Configuration.applyFontInfoSlow(target, this._configuration.options.get(EditorOption.fontInfo));
1442 1443
	}

A
Alex Dima 已提交
1444 1445 1446 1447 1448
	protected _attachModel(model: ITextModel | null): void {
		if (!model) {
			this._modelData = null;
			return;
		}
E
Erich Gamma 已提交
1449

A
Alex Dima 已提交
1450
		const listenersToRemove: IDisposable[] = [];
A
Alex Dima 已提交
1451

A
Alex Dima 已提交
1452
		this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1453 1454
		this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());
		this._configuration.setMaxLineNumber(model.getLineCount());
A
Alex Dima 已提交
1455

A
Alex Dima 已提交
1456
		model.onBeforeAttached();
A
Alex Dima 已提交
1457

1458 1459 1460 1461
		const viewModel = new ViewModel(
			this._id,
			this._configuration,
			model,
1462
			DOMLineBreaksComputerFactory.create(),
1463
			MonospaceLineBreaksComputerFactory.create(this._configuration.options),
1464 1465
			(callback) => dom.scheduleAtNextAnimationFrame(callback)
		);
A
Alex Dima 已提交
1466

A
Alex Dima 已提交
1467 1468
		listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
		listenersToRemove.push(model.onDidChangeLanguage((e) => {
A
Alex Dima 已提交
1469
			this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1470 1471 1472 1473 1474 1475 1476
			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 已提交
1477

1478
		listenersToRemove.push(viewModel.cursor.onDidAttemptReadOnlyEdit(() => {
R
Rob Lourens 已提交
1479
			this._onDidAttemptReadOnlyEdit.fire(undefined);
A
Alex Dima 已提交
1480
		}));
A
Alex Dima 已提交
1481

1482
		listenersToRemove.push(viewModel.cursor.onDidChange((e: CursorStateChangedEvent) => {
A
Alex Dima 已提交
1483 1484 1485 1486
			if (e.reachedMaxCursorCount) {
				this._notificationService.warn(nls.localize('cursors.maximum', "The number of cursors has been limited to {0}.", Cursor.MAX_CURSOR_COUNT));
			}

M
Matt Bierner 已提交
1487
			const positions: Position[] = [];
A
Alex Dima 已提交
1488 1489 1490
			for (let i = 0, len = e.selections.length; i < len; i++) {
				positions[i] = e.selections[i].getPosition();
			}
A
Alex Dima 已提交
1491

A
Alex Dima 已提交
1492 1493 1494 1495 1496 1497 1498
			const e1: ICursorPositionChangedEvent = {
				position: positions[0],
				secondaryPositions: positions.slice(1),
				reason: e.reason,
				source: e.source
			};
			this._onDidChangeCursorPosition.fire(e1);
A
Alex Dima 已提交
1499

A
Alex Dima 已提交
1500 1501 1502
			const e2: ICursorSelectionChangedEvent = {
				selection: e.selections[0],
				secondarySelections: e.selections.slice(1),
1503 1504 1505
				modelVersionId: e.modelVersionId,
				oldSelections: e.oldSelections,
				oldModelVersionId: e.oldModelVersionId,
A
Alex Dima 已提交
1506 1507 1508 1509 1510
				source: e.source,
				reason: e.reason
			};
			this._onDidChangeCursorSelection.fire(e2);
		}));
E
Erich Gamma 已提交
1511

1512
		const [view, hasRealView] = this._createView(viewModel);
A
Alex Dima 已提交
1513
		if (hasRealView) {
A
Alex Dima 已提交
1514
			this._domElement.appendChild(view.domNode.domNode);
E
Erich Gamma 已提交
1515

A
Alex Dima 已提交
1516
			let keys = Object.keys(this._contentWidgets);
A
Alex Dima 已提交
1517
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1518
				const widgetId = keys[i];
A
Alex Dima 已提交
1519
				view.addContentWidget(this._contentWidgets[widgetId]);
A
Alex Dima 已提交
1520
			}
E
Erich Gamma 已提交
1521

A
Alex Dima 已提交
1522
			keys = Object.keys(this._overlayWidgets);
A
Alex Dima 已提交
1523
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1524
				const widgetId = keys[i];
A
Alex Dima 已提交
1525
				view.addOverlayWidget(this._overlayWidgets[widgetId]);
A
Alex Dima 已提交
1526
			}
E
Erich Gamma 已提交
1527

A
Alex Dima 已提交
1528 1529
			view.render(false, true);
			view.domNode.domNode.setAttribute('data-uri', model.uri.toString());
E
Erich Gamma 已提交
1530
		}
A
Alex Dima 已提交
1531

1532
		this._modelData = new ModelData(model, viewModel, view, hasRealView, listenersToRemove);
E
Erich Gamma 已提交
1533 1534
	}

1535
	protected _createView(viewModel: ViewModel): [View, boolean] {
1536 1537 1538
		let commandDelegate: ICommandDelegate;
		if (this.isSimpleWidget) {
			commandDelegate = {
A
Alex Dima 已提交
1539
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
1540
					editorCommand.runCoreEditorCommand(viewModel, args);
A
Alex Dima 已提交
1541
				},
A
Alex Dima 已提交
1542
				paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {
1543
					this._paste('keyboard', text, pasteOnNewLine, multicursorText, mode);
1544
				},
A
Alex Dima 已提交
1545
				type: (text: string) => {
1546
					this._type('keyboard', text);
1547
				},
A
Alex Dima 已提交
1548
				replacePreviousChar: (text: string, replaceCharCnt: number) => {
1549
					this._replacePreviousChar('keyboard', text, replaceCharCnt);
1550
				},
1551 1552
				startComposition: () => {
					this._startComposition();
1553
				},
1554 1555
				endComposition: () => {
					this._endComposition('keyboard');
1556
				},
A
Alex Dima 已提交
1557
				cut: () => {
1558
					this._cut('keyboard');
1559 1560 1561 1562
				}
			};
		} else {
			commandDelegate = {
A
Alex Dima 已提交
1563
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
1564
					editorCommand.runCoreEditorCommand(viewModel, args);
A
Alex Dima 已提交
1565
				},
A
Alex Dima 已提交
1566
				paste: (text: string, pasteOnNewLine: boolean, multicursorText: string[] | null, mode: string | null) => {
1567 1568
					const payload: editorCommon.PastePayload = { text, pasteOnNewLine, multicursorText, mode };
					this._commandService.executeCommand(editorCommon.Handler.Paste, payload);
1569
				},
A
Alex Dima 已提交
1570
				type: (text: string) => {
1571 1572
					const payload: editorCommon.TypePayload = { text };
					this._commandService.executeCommand(editorCommon.Handler.Type, payload);
1573
				},
A
Alex Dima 已提交
1574
				replacePreviousChar: (text: string, replaceCharCnt: number) => {
1575 1576
					const payload: editorCommon.ReplacePreviousCharPayload = { text, replaceCharCnt };
					this._commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, payload);
1577
				},
1578
				startComposition: () => {
1579 1580
					this._commandService.executeCommand(editorCommon.Handler.CompositionStart, {});
				},
1581
				endComposition: () => {
1582 1583
					this._commandService.executeCommand(editorCommon.Handler.CompositionEnd, {});
				},
A
Alex Dima 已提交
1584
				cut: () => {
1585 1586 1587 1588 1589
					this._commandService.executeCommand(editorCommon.Handler.Cut, {});
				}
			};
		}

1590 1591 1592 1593
		const onDidChangeTextFocus = (textFocus: boolean) => {
			this._editorTextFocus.setValue(textFocus);
		};

A
Alex Dima 已提交
1594
		const viewOutgoingEvents = new ViewOutgoingEvents(viewModel);
1595
		viewOutgoingEvents.onDidContentSizeChange = (e) => this._onDidContentSizeChange.fire(e);
A
Alex Dima 已提交
1596
		viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
1597 1598
		viewOutgoingEvents.onDidGainFocus = () => onDidChangeTextFocus(true);
		viewOutgoingEvents.onDidLoseFocus = () => onDidChangeTextFocus(false);
1599 1600
		viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e);
		viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e);
A
Alex Dima 已提交
1601
		viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e);
1602 1603
		viewOutgoingEvents.onMouseMove = (e) => this._onMouseMove.fire(e);
		viewOutgoingEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);
A
Alex Dima 已提交
1604 1605 1606 1607
		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);
1608
		viewOutgoingEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);
A
Alex Dima 已提交
1609 1610 1611 1612 1613 1614 1615 1616

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

A
Alex Dima 已提交
1618
		return [view, true];
1619
	}
E
Erich Gamma 已提交
1620

A
Alex Dima 已提交
1621
	protected _postDetachModelCleanup(detachedModel: ITextModel | null): void {
A
Alex Dima 已提交
1622
		if (detachedModel) {
A
Alex Dima 已提交
1623
			detachedModel.removeAllDecorationsWithOwnerId(this._id);
1624 1625 1626
		}
	}

A
Alex Dima 已提交
1627 1628 1629
	private _detachModel(): ITextModel | null {
		if (!this._modelData) {
			return null;
A
Alex Dima 已提交
1630
		}
A
Alex Dima 已提交
1631 1632
		const model = this._modelData.model;
		const removeDomNode = this._modelData.hasRealView ? this._modelData.view.domNode.domNode : null;
A
Alex Dima 已提交
1633

A
Alex Dima 已提交
1634 1635
		this._modelData.dispose();
		this._modelData = null;
A
Alex Dima 已提交
1636

A
Alex Dima 已提交
1637
		this._domElement.removeAttribute('data-mode-id');
1638
		if (removeDomNode && this._domElement.contains(removeDomNode)) {
A
Alex Dima 已提交
1639
			this._domElement.removeChild(removeDomNode);
E
Erich Gamma 已提交
1640 1641
		}

A
Alex Dima 已提交
1642
		return model;
E
Erich Gamma 已提交
1643
	}
1644

A
Alex Dima 已提交
1645
	private _registerDecorationType(key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void {
1646
		this._codeEditorService.registerDecorationType(key, options, parentTypeKey, this);
1647 1648
	}

A
Alex Dima 已提交
1649
	private _removeDecorationType(key: string): void {
1650 1651 1652
		this._codeEditorService.removeDecorationType(key);
	}

A
Alex Dima 已提交
1653
	private _resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions {
1654 1655 1656
		return this._codeEditorService.resolveDecorationOptions(typeKey, writable);
	}

M
Matt Bierner 已提交
1657
	public getTelemetryData(): { [key: string]: any; } | undefined {
1658
		return this._telemetryData;
A
Alex Dima 已提交
1659
	}
A
Alex Dima 已提交
1660 1661 1662 1663

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

A
Alex Dima 已提交
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686
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 已提交
1687
		const value = (_value ? BooleanEventValue.True : BooleanEventValue.False);
A
Alex Dima 已提交
1688 1689
		if (this._value === value) {
			return;
1690
		}
A
Alex Dima 已提交
1691 1692 1693 1694 1695 1696 1697 1698
		this._value = value;
		if (this._value === BooleanEventValue.True) {
			this._onDidChangeToTrue.fire();
		} else if (this._value === BooleanEventValue.False) {
			this._onDidChangeToFalse.fire();
		}
	}
}
1699

A
Alex Dima 已提交
1700 1701
class EditorContextKeysManager extends Disposable {

1702
	private readonly _editor: CodeEditorWidget;
1703
	private readonly _editorSimpleInput: IContextKey<boolean>;
1704 1705 1706 1707 1708
	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>;
1709
	private readonly _editorColumnSelection: IContextKey<boolean>;
1710 1711 1712 1713
	private readonly _hasMultipleSelections: IContextKey<boolean>;
	private readonly _hasNonEmptySelection: IContextKey<boolean>;
	private readonly _canUndo: IContextKey<boolean>;
	private readonly _canRedo: IContextKey<boolean>;
A
Alex Dima 已提交
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723

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

		this._editor = editor;

		contextKeyService.createKey('editorId', editor.getId());
1724 1725

		this._editorSimpleInput = EditorContextKeys.editorSimpleInput.bindTo(contextKeyService);
A
Alex Dima 已提交
1726 1727 1728 1729 1730
		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);
1731
		this._editorColumnSelection = EditorContextKeys.columnSelection.bindTo(contextKeyService);
A
Alex Dima 已提交
1732 1733
		this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);
		this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);
A
Alex Dima 已提交
1734 1735
		this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);
		this._canRedo = EditorContextKeys.canRedo.bindTo(contextKeyService);
A
Alex Dima 已提交
1736 1737 1738

		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromConfig()));
		this._register(this._editor.onDidChangeCursorSelection(() => this._updateFromSelection()));
A
Alex Dima 已提交
1739 1740
		this._register(this._editor.onDidFocusEditorWidget(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorWidget(() => this._updateFromFocus()));
A
Alex Dima 已提交
1741 1742
		this._register(this._editor.onDidFocusEditorText(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorText(() => this._updateFromFocus()));
A
Alex Dima 已提交
1743 1744
		this._register(this._editor.onDidChangeModel(() => this._updateFromModel()));
		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromModel()));
A
Alex Dima 已提交
1745 1746 1747 1748

		this._updateFromConfig();
		this._updateFromSelection();
		this._updateFromFocus();
A
Alex Dima 已提交
1749
		this._updateFromModel();
1750 1751

		this._editorSimpleInput.set(this._editor.isSimpleWidget);
A
Alex Dima 已提交
1752 1753 1754
	}

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

A
renames  
Alex Dima 已提交
1757 1758
		this._editorTabMovesFocus.set(options.get(EditorOption.tabFocusMode));
		this._editorReadonly.set(options.get(EditorOption.readOnly));
1759
		this._editorColumnSelection.set(options.get(EditorOption.columnSelection));
A
Alex Dima 已提交
1760 1761 1762
	}

	private _updateFromSelection(): void {
M
Matt Bierner 已提交
1763
		const selections = this._editor.getSelections();
A
Alex Dima 已提交
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
		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 已提交
1775 1776
		this._editorTextFocus.set(this._editor.hasTextFocus() && !this._editor.isSimpleWidget);
		this._textInputFocus.set(this._editor.hasTextFocus());
A
Alex Dima 已提交
1777
	}
A
Alex Dima 已提交
1778 1779 1780

	private _updateFromModel(): void {
		const model = this._editor.getModel();
A
Alex Dima 已提交
1781 1782
		this._canUndo.set(Boolean(model && model.canUndo()));
		this._canRedo.set(Boolean(model && model.canRedo()));
A
Alex Dima 已提交
1783
	}
A
Alex Dima 已提交
1784 1785 1786 1787
}

export class EditorModeContext extends Disposable {

1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802
	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>;
1803 1804
	private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;
	private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;
1805 1806
	private readonly _hasSignatureHelpProvider: IContextKey<boolean>;
	private readonly _isInWalkThrough: IContextKey<boolean>;
A
Alex Dima 已提交
1807 1808

	constructor(
1809 1810
		private readonly _editor: CodeEditorWidget,
		private readonly _contextKeyService: IContextKeyService
A
Alex Dima 已提交
1811 1812 1813
	) {
		super();

1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831
		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);
1832
		this._isInWalkThrough = EditorContextKeys.isInWalkThroughSnippet.bindTo(_contextKeyService);
A
Alex Dima 已提交
1833 1834 1835 1836

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

		// update when model/mode changes
1837 1838
		this._register(_editor.onDidChangeModel(update));
		this._register(_editor.onDidChangeModelLanguage(update));
A
Alex Dima 已提交
1839 1840

		// update when registries change
1841
		this._register(modes.CompletionProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1842 1843 1844
		this._register(modes.CodeActionProviderRegistry.onDidChange(update));
		this._register(modes.CodeLensProviderRegistry.onDidChange(update));
		this._register(modes.DefinitionProviderRegistry.onDidChange(update));
1845
		this._register(modes.DeclarationProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864
		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() {
1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
		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 已提交
1884 1885 1886 1887 1888 1889 1890 1891
	}

	private _update() {
		const model = this._editor.getModel();
		if (!model) {
			this.reset();
			return;
		}
1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
		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 已提交
1909
			this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length + modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
1910 1911 1912
			this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
			this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
		});
1913
	}
E
Erich Gamma 已提交
1914 1915
}

1916 1917
class CodeEditorWidgetFocusTracker extends Disposable {

1918
	private _hasFocus: boolean;
1919
	private readonly _domFocusTracker: dom.IFocusTracker;
1920

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

J
Johannes Rieken 已提交
1924
	constructor(domElement: HTMLElement) {
1925 1926
		super();

1927 1928
		this._hasFocus = false;
		this._domFocusTracker = this._register(dom.trackFocus(domElement));
1929

1930
		this._register(this._domFocusTracker.onDidFocus(() => {
1931
			this._hasFocus = true;
R
Rob Lourens 已提交
1932
			this._onChange.fire(undefined);
1933 1934
		}));
		this._register(this._domFocusTracker.onDidBlur(() => {
1935
			this._hasFocus = false;
R
Rob Lourens 已提交
1936
			this._onChange.fire(undefined);
1937
		}));
1938 1939 1940
	}

	public hasFocus(): boolean {
1941
		return this._hasFocus;
1942
	}
1943 1944 1945 1946 1947 1948

	public refreshState(): void {
		if (this._domFocusTracker.refreshState) {
			this._domFocusTracker.refreshState();
		}
	}
1949
}
1950

1951
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='`);
1952
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>`);
1953

1954 1955 1956
function getSquigglySVGData(color: Color) {
	return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd;
}
1957

1958 1959 1960 1961 1962 1963 1964
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;
}

1965
registerThemingParticipant((theme, collector) => {
M
Matt Bierner 已提交
1966
	const errorBorderColor = theme.getColor(editorErrorBorder);
1967
	if (errorBorderColor) {
1968
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { border-bottom: 4px double ${errorBorderColor}; }`);
1969
	}
M
Matt Bierner 已提交
1970
	const errorForeground = theme.getColor(editorErrorForeground);
1971
	if (errorForeground) {
1972
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);
1973 1974
	}

M
Matt Bierner 已提交
1975
	const warningBorderColor = theme.getColor(editorWarningBorder);
1976
	if (warningBorderColor) {
1977
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { border-bottom: 4px double ${warningBorderColor}; }`);
1978
	}
M
Matt Bierner 已提交
1979
	const warningForeground = theme.getColor(editorWarningForeground);
1980
	if (warningForeground) {
1981
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);
1982 1983
	}

M
Matt Bierner 已提交
1984
	const infoBorderColor = theme.getColor(editorInfoBorder);
1985 1986
	if (infoBorderColor) {
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { border-bottom: 4px double ${infoBorderColor}; }`);
1987
	}
M
Matt Bierner 已提交
1988
	const infoForeground = theme.getColor(editorInfoForeground);
1989
	if (infoForeground) {
1990
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);
1991
	}
1992

M
Matt Bierner 已提交
1993
	const hintBorderColor = theme.getColor(editorHintBorder);
1994
	if (hintBorderColor) {
1995
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { border-bottom: 2px dotted ${hintBorderColor}; }`);
1996
	}
M
Matt Bierner 已提交
1997
	const hintForeground = theme.getColor(editorHintForeground);
1998
	if (hintForeground) {
1999
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`);
2000
	}
2001

2002
	const unnecessaryForeground = theme.getColor(editorUnnecessaryCodeOpacity);
2003
	if (unnecessaryForeground) {
2004
		collector.addRule(`.monaco-editor.showUnused .${ClassName.EditorUnnecessaryInlineDecoration} { opacity: ${unnecessaryForeground.rgba.a}; }`);
2005 2006 2007 2008
	}

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

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