src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts/MergeEditor/constructor
class MergeEditor:	override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
		if (!(input instanceof MergeEditorInput)) {
			throw new BugIndicatingError('ONLY MergeEditorInput is supported');
		}
		await super.setInput(input, options, context, token);

		this._sessionDisposables.clear();
		transaction(tx => {
			this._viewModel.set(undefined, tx);
			this._inputModel.set(undefined, tx);
		});

		const inputModel = await input.resolve();
		const model = inputModel.model;

		const viewModel = this.instantiationService.createInstance(
			MergeEditorViewModel,
			model,
			this.input1View,
			this.input2View,
			this.inputResultView,
			this.baseView,
			this.showNonConflictingChanges,
		);


		model.telemetry.reportMergeEditorOpened({
			combinableConflictCount: model.combinableConflictCount,
			conflictCount: model.conflictCount,

			baseTop: this._layoutModeObs.get().showBaseAtTop,
			baseVisible: this._layoutModeObs.get().showBase,
			isColumnView: this._layoutModeObs.get().kind === 'columns',
		});

		transaction(tx => {
			this._viewModel.set(viewModel, tx);
			this._inputModel.set(inputModel, tx);
		});
		this._sessionDisposables.add(viewModel);

		// Set/unset context keys based on input
		this._ctxResultUri.set(inputModel.resultUri.toString());
		this._ctxBaseUri.set(model.base.uri.toString());
		this._sessionDisposables.add(toDisposable(() => {
			this._ctxBaseUri.reset();
			this._ctxResultUri.reset();
		}));

		// Set the view zones before restoring view state!
		// Otherwise scrolling will be off
		this._sessionDisposables.add(autorunWithStore((reader, store) => {
			const baseView = this.baseView.read(reader);

			this.inputResultView.editor.changeViewZones(resultViewZoneAccessor => {
				const layout = this._layoutModeObs.read(reader);
				const shouldAlignResult = layout.kind === 'columns';
				const shouldAlignBase = layout.kind === 'mixed' && !layout.showBaseAtTop;

				this.input1View.editor.changeViewZones(input1ViewZoneAccessor => {
					this.input2View.editor.changeViewZones(input2ViewZoneAccessor => {
						if (baseView) {
							baseView.editor.changeViewZones(baseViewZoneAccessor => {
								store.add(this.setViewZones(reader,
									viewModel,
									this.input1View.editor,
									input1ViewZoneAccessor,
									this.input2View.editor,
									input2ViewZoneAccessor,
									baseView.editor,
									baseViewZoneAccessor,
									shouldAlignBase,
									this.inputResultView.editor,
									resultViewZoneAccessor,
									shouldAlignResult
								));
							});
						} else {
							store.add(this.setViewZones(reader,
								viewModel,
								this.input1View.editor,
								input1ViewZoneAccessor,
								this.input2View.editor,
								input2ViewZoneAccessor,
								undefined,
								undefined,
								false,
								this.inputResultView.editor,
								resultViewZoneAccessor,
								shouldAlignResult
							));
						}
					});
				});
			});

			this.scrollSynchronizer.updateScrolling();
		}, 'update alignment view zones'));

		const viewState = this.loadEditorViewState(input, context);
		if (viewState) {
			this._applyViewState(viewState);
		} else {
			this._sessionDisposables.add(thenIfNotDisposed(model.onInitialized, () => {
				const firstConflict = model.modifiedBaseRanges.get().find(r => r.isConflicting);
				if (!firstConflict) {
					return;
				}
				this.input1View.editor.revealLineInCenter(firstConflict.input1Range.startLineNumber);
				transaction(tx => {
					/** @description setActiveModifiedBaseRange */
					viewModel.setActiveModifiedBaseRange(firstConflict, tx);
				});
			}));
		}

		// word wrap special case - sync transient state from result model to input[1|2] models
		const mirrorWordWrapTransientState = () => {
			const state = readTransientState(model.resultTextModel, this._codeEditorService);
			writeTransientState(model.input2.textModel, state, this._codeEditorService);
			writeTransientState(model.input1.textModel, state, this._codeEditorService);
		};
		this._sessionDisposables.add(this._codeEditorService.onDidChangeTransientModelProperty(candidate => {
			if (candidate === this.inputResultView.editor.getModel()) {
				mirrorWordWrapTransientState();
			}
		}));
		mirrorWordWrapTransientState();

		// detect when base, input1, and input2 become empty and replace THIS editor with its result editor
		// TODO@jrieken@hediet this needs a better/cleaner solution
		// https://github.com/microsoft/vscode/issues/155940
		const that = this;
		this._sessionDisposables.add(new class {

			private readonly _disposable = new DisposableStore();

			constructor() {
				for (const model of this.baseInput1Input2()) {
					this._disposable.add(model.onDidChangeContent(() => this._checkBaseInput1Input2AllEmpty()));
				}
			}

			dispose() {
				this._disposable.dispose();
			}

			private *baseInput1Input2() {
				yield model.base;
				yield model.input1.textModel;
				yield model.input2.textModel;
			}

			private _checkBaseInput1Input2AllEmpty() {
				for (const model of this.baseInput1Input2()) {
					if (model.getValueLength() > 0) {
						return;
					}
				}
				// all empty -> replace this editor with a normal editor for result
				that.editorService.replaceEditors(
					[{ editor: input, replacement: { resource: input.result, options: { preserveFocus: true } }, forceReplaceDirty: true }],
					that.group ?? that.editorGroupService.activeGroup
				);
			}
		});
	}