Merge from vscode e6a45f4242ebddb7aa9a229f85555e8a3bd987e2 (#9253)

* Merge from vscode e6a45f4242ebddb7aa9a229f85555e8a3bd987e2

* skip failing tests

* remove github-authentication extensions

* ignore github compile steps

* ignore github compile steps

* check in compiled files
This commit is contained in:
Anthony Dresser
2020-02-21 12:11:51 -08:00
committed by GitHub
parent c74bac3746
commit 1b78a9b1e0
179 changed files with 3200 additions and 1830 deletions

View File

@@ -3,61 +3,72 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Selection } from 'vs/editor/common/core/selection';
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation } from 'vs/editor/common/model';
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel, IValidEditOperations } from 'vs/editor/common/model';
import { TextModel } from 'vs/editor/common/model/textModel';
import { IUndoRedoService, IUndoRedoElement, IUndoRedoContext } from 'vs/platform/undoRedo/common/undoRedo';
import { URI } from 'vs/base/common/uri';
interface IEditOperation {
operations: IValidEditOperation[];
}
class EditStackElement implements IUndoRedoElement {
interface IStackElement {
readonly beforeVersionId: number;
readonly beforeCursorState: Selection[] | null;
readonly afterCursorState: Selection[] | null;
readonly afterVersionId: number;
public readonly label: string;
private _isOpen: boolean;
private readonly _model: TextModel;
private readonly _beforeVersionId: number;
private readonly _beforeCursorState: Selection[];
private _afterVersionId: number;
private _afterCursorState: Selection[] | null;
private _edits: IValidEditOperations[];
undo(model: TextModel): void;
redo(model: TextModel): void;
}
class EditStackElement implements IStackElement {
public readonly beforeVersionId: number;
public readonly beforeCursorState: Selection[];
public afterCursorState: Selection[] | null;
public afterVersionId: number;
public editOperations: IEditOperation[];
constructor(beforeVersionId: number, beforeCursorState: Selection[]) {
this.beforeVersionId = beforeVersionId;
this.beforeCursorState = beforeCursorState;
this.afterCursorState = null;
this.afterVersionId = -1;
this.editOperations = [];
public get resources(): readonly URI[] {
return [this._model.uri];
}
public undo(model: TextModel): void {
// Apply all operations in reverse order
for (let i = this.editOperations.length - 1; i >= 0; i--) {
this.editOperations[i] = {
operations: model.applyEdits(this.editOperations[i].operations)
};
}
constructor(model: TextModel, beforeVersionId: number, beforeCursorState: Selection[], afterVersionId: number, afterCursorState: Selection[] | null, operations: IValidEditOperation[]) {
this.label = nls.localize('edit', "Typing");
this._isOpen = true;
this._model = model;
this._beforeVersionId = beforeVersionId;
this._beforeCursorState = beforeCursorState;
this._afterVersionId = afterVersionId;
this._afterCursorState = afterCursorState;
this._edits = [{ operations: operations }];
}
public redo(model: TextModel): void {
// Apply all operations
for (let i = 0; i < this.editOperations.length; i++) {
this.editOperations[i] = {
operations: model.applyEdits(this.editOperations[i].operations)
};
}
public isOpen(): boolean {
return this._isOpen;
}
public append(operations: IValidEditOperation[], afterVersionId: number, afterCursorState: Selection[] | null): void {
this._edits.push({ operations: operations });
this._afterVersionId = afterVersionId;
this._afterCursorState = afterCursorState;
}
public close(): void {
this._isOpen = false;
}
undo(ctx: IUndoRedoContext): void {
this._isOpen = false;
this._edits.reverse();
this._edits = this._model._applyEdits(this._edits, true, false, this._beforeVersionId, this._beforeCursorState);
}
redo(ctx: IUndoRedoContext): void {
this._isOpen = false;
this._edits.reverse();
this._edits = this._model._applyEdits(this._edits, false, true, this._afterVersionId, this._afterCursorState);
}
invalidate(resource: URI): void {
// nothing to do
}
}
function getModelEOL(model: TextModel): EndOfLineSequence {
function getModelEOL(model: ITextModel): EndOfLineSequence {
const eol = model.getEOL();
if (eol === '\n') {
return EndOfLineSequence.LF;
@@ -66,32 +77,40 @@ function getModelEOL(model: TextModel): EndOfLineSequence {
}
}
class EOLStackElement implements IStackElement {
public readonly beforeVersionId: number;
public readonly beforeCursorState: Selection[] | null;
public readonly afterCursorState: Selection[] | null;
public afterVersionId: number;
class EOLStackElement implements IUndoRedoElement {
public eol: EndOfLineSequence;
public readonly label: string;
private readonly _model: TextModel;
private readonly _beforeVersionId: number;
private readonly _afterVersionId: number;
private _eol: EndOfLineSequence;
constructor(beforeVersionId: number, setEOL: EndOfLineSequence) {
this.beforeVersionId = beforeVersionId;
this.beforeCursorState = null;
this.afterCursorState = null;
this.afterVersionId = -1;
this.eol = setEOL;
public get resources(): readonly URI[] {
return [this._model.uri];
}
public undo(model: TextModel): void {
let redoEOL = getModelEOL(model);
model.setEOL(this.eol);
this.eol = redoEOL;
constructor(model: TextModel, beforeVersionId: number, afterVersionId: number, eol: EndOfLineSequence) {
this.label = nls.localize('eol', "Change End Of Line Sequence");
this._model = model;
this._beforeVersionId = beforeVersionId;
this._afterVersionId = afterVersionId;
this._eol = eol;
}
public redo(model: TextModel): void {
let undoEOL = getModelEOL(model);
model.setEOL(this.eol);
this.eol = undoEOL;
undo(ctx: IUndoRedoContext): void {
const redoEOL = getModelEOL(this._model);
this._model._setEOL(this._eol, true, false, this._beforeVersionId, null);
this._eol = redoEOL;
}
redo(ctx: IUndoRedoContext): void {
const undoEOL = getModelEOL(this._model);
this._model._setEOL(this._eol, false, true, this._afterVersionId, null);
this._eol = undoEOL;
}
invalidate(resource: URI): void {
// nothing to do
}
}
@@ -102,76 +121,52 @@ export interface IUndoRedoResult {
export class EditStack {
private readonly model: TextModel;
private currentOpenStackElement: IStackElement | null;
private past: IStackElement[];
private future: IStackElement[];
private readonly _model: TextModel;
private readonly _undoRedoService: IUndoRedoService;
constructor(model: TextModel) {
this.model = model;
this.currentOpenStackElement = null;
this.past = [];
this.future = [];
constructor(model: TextModel, undoRedoService: IUndoRedoService) {
this._model = model;
this._undoRedoService = undoRedoService;
}
public pushStackElement(): void {
if (this.currentOpenStackElement !== null) {
this.past.push(this.currentOpenStackElement);
this.currentOpenStackElement = null;
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
if (lastElement && lastElement instanceof EditStackElement) {
lastElement.close();
}
}
public clear(): void {
this.currentOpenStackElement = null;
this.past = [];
this.future = [];
this._undoRedoService.removeElements(this._model.uri);
}
public pushEOL(eol: EndOfLineSequence): void {
// No support for parallel universes :(
this.future = [];
const beforeVersionId = this._model.getAlternativeVersionId();
const inverseEOL = getModelEOL(this._model);
this._model.setEOL(eol);
const afterVersionId = this._model.getAlternativeVersionId();
if (this.currentOpenStackElement) {
this.pushStackElement();
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
if (lastElement && lastElement instanceof EditStackElement) {
lastElement.close();
}
const prevEOL = getModelEOL(this.model);
let stackElement = new EOLStackElement(this.model.getAlternativeVersionId(), prevEOL);
this.model.setEOL(eol);
stackElement.afterVersionId = this.model.getVersionId();
this.currentOpenStackElement = stackElement;
this.pushStackElement();
this._undoRedoService.pushElement(new EOLStackElement(this._model, inverseEOL, beforeVersionId, afterVersionId));
}
public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
// No support for parallel universes :(
this.future = [];
const beforeVersionId = this._model.getAlternativeVersionId();
const inverseEditOperations = this._model.applyEdits(editOperations);
const afterVersionId = this._model.getAlternativeVersionId();
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
let stackElement: EditStackElement | null = null;
if (this.currentOpenStackElement) {
if (this.currentOpenStackElement instanceof EditStackElement) {
stackElement = this.currentOpenStackElement;
} else {
this.pushStackElement();
}
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
if (lastElement && lastElement instanceof EditStackElement && lastElement.isOpen()) {
lastElement.append(inverseEditOperations, afterVersionId, afterCursorState);
} else {
this._undoRedoService.pushElement(new EditStackElement(this._model, beforeVersionId, beforeCursorState, afterVersionId, afterCursorState, inverseEditOperations));
}
if (!this.currentOpenStackElement) {
stackElement = new EditStackElement(this.model.getAlternativeVersionId(), beforeCursorState);
this.currentOpenStackElement = stackElement;
}
const inverseEditOperation: IEditOperation = {
operations: this.model.applyEdits(editOperations)
};
stackElement!.editOperations.push(inverseEditOperation);
stackElement!.afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperation.operations);
stackElement!.afterVersionId = this.model.getVersionId();
return stackElement!.afterCursorState;
return afterCursorState;
}
private static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IValidEditOperation[]): Selection[] | null {
@@ -182,62 +177,4 @@ export class EditStack {
return null;
}
}
public undo(): IUndoRedoResult | null {
this.pushStackElement();
if (this.past.length > 0) {
const pastStackElement = this.past.pop()!;
try {
pastStackElement.undo(this.model);
} catch (e) {
onUnexpectedError(e);
this.clear();
return null;
}
this.future.push(pastStackElement);
return {
selections: pastStackElement.beforeCursorState,
recordedVersionId: pastStackElement.beforeVersionId
};
}
return null;
}
public canUndo(): boolean {
return (this.past.length > 0) || this.currentOpenStackElement !== null;
}
public redo(): IUndoRedoResult | null {
if (this.future.length > 0) {
const futureStackElement = this.future.pop()!;
try {
futureStackElement.redo(this.model);
} catch (e) {
onUnexpectedError(e);
this.clear();
return null;
}
this.past.push(futureStackElement);
return {
selections: futureStackElement.afterCursorState,
recordedVersionId: futureStackElement.afterVersionId
};
}
return null;
}
public canRedo(): boolean {
return (this.future.length > 0);
}
}

View File

@@ -36,6 +36,8 @@ import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2
import { Color } from 'vs/base/common/color';
import { Constants } from 'vs/base/common/uint';
import { EditorTheme } from 'vs/editor/common/view/viewContext';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
function createTextBufferBuilder() {
return new PieceTreeTextBufferBuilder();
@@ -188,7 +190,7 @@ export class TextModel extends Disposable implements model.ITextModel {
};
public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel {
return new TextModel(text, options, languageIdentifier, uri);
return new TextModel(text, options, languageIdentifier, uri, new UndoRedoService());
}
public static resolveOptions(textBuffer: model.ITextBuffer, options: model.ITextModelCreationOptions): model.TextModelResolvedOptions {
@@ -253,6 +255,7 @@ export class TextModel extends Disposable implements model.ITextModel {
public readonly id: string;
public readonly isForSimpleWidget: boolean;
private readonly _associatedResource: URI;
private readonly _undoRedoService: IUndoRedoService;
private _attachedEditorCount: number;
private _buffer: model.ITextBuffer;
private _options: model.TextModelResolvedOptions;
@@ -268,7 +271,7 @@ export class TextModel extends Disposable implements model.ITextModel {
private readonly _isTooLargeForTokenization: boolean;
//#region Editing
private _commandManager: EditStack;
private readonly _commandManager: EditStack;
private _isUndoing: boolean;
private _isRedoing: boolean;
private _trimAutoWhitespaceLines: number[] | null;
@@ -293,7 +296,13 @@ export class TextModel extends Disposable implements model.ITextModel {
private readonly _tokenization: TextModelTokenization;
//#endregion
constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier | null, associatedResource: URI | null = null) {
constructor(
source: string | model.ITextBufferFactory,
creationOptions: model.ITextModelCreationOptions,
languageIdentifier: LanguageIdentifier | null,
associatedResource: URI | null = null,
undoRedoService: IUndoRedoService
) {
super();
// Generate a new unique model id
@@ -305,6 +314,7 @@ export class TextModel extends Disposable implements model.ITextModel {
} else {
this._associatedResource = associatedResource;
}
this._undoRedoService = undoRedoService;
this._attachedEditorCount = 0;
this._buffer = createTextBuffer(source, creationOptions.defaultEOL);
@@ -347,7 +357,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this._decorations = Object.create(null);
this._decorationsTree = new DecorationsTrees();
this._commandManager = new EditStack(this);
this._commandManager = new EditStack(this, undoRedoService);
this._isUndoing = false;
this._isRedoing = false;
this._trimAutoWhitespaceLines = null;
@@ -362,6 +372,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this._onWillDispose.fire();
this._languageRegistryListener.dispose();
this._tokenization.dispose();
this._undoRedoService.removeElements(this.uri);
this._isDisposed = true;
super.dispose();
this._isDisposing = false;
@@ -436,7 +447,7 @@ export class TextModel extends Disposable implements model.ITextModel {
this._decorationsTree = new DecorationsTrees();
// Destroy my edit history and settings
this._commandManager = new EditStack(this);
this._commandManager.clear();
this._trimAutoWhitespaceLines = null;
this._emitContentChangedEvent(
@@ -483,6 +494,21 @@ export class TextModel extends Disposable implements model.ITextModel {
);
}
_setEOL(eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
this._isUndoing = isUndoing;
this._isRedoing = isRedoing;
this.setEOL(eol);
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
} finally {
this._isUndoing = false;
this._eventEmitter.endDeferredEmit(resultingSelection);
this._onDidChangeDecorations.endDeferredEmit();
}
}
private _onBeforeEOLChange(): void {
// Ensure all decorations get their `range` set.
const versionId = this.getVersionId();
@@ -1272,18 +1298,37 @@ export class TextModel extends Disposable implements model.ITextModel {
return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);
}
_applyEdits(edits: model.IValidEditOperations[], isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): model.IValidEditOperations[] {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
this._isUndoing = isUndoing;
this._isRedoing = isRedoing;
let reverseEdits: model.IValidEditOperations[] = [];
for (let i = 0, len = edits.length; i < len; i++) {
reverseEdits[i] = { operations: this.applyEdits(edits[i].operations) };
}
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
return reverseEdits;
} finally {
this._isUndoing = false;
this._eventEmitter.endDeferredEmit(resultingSelection);
this._onDidChangeDecorations.endDeferredEmit();
}
}
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IValidEditOperation[] {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
return this._applyEdits(this._validateEditOperations(rawOperations));
return this._doApplyEdits(this._validateEditOperations(rawOperations));
} finally {
this._eventEmitter.endDeferredEmit();
this._onDidChangeDecorations.endDeferredEmit();
}
}
private _applyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] {
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] {
const oldLineCount = this._buffer.getLineCount();
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace);
@@ -1364,62 +1409,20 @@ export class TextModel extends Disposable implements model.ITextModel {
return result.reverseEdits;
}
private _undo(): Selection[] | null {
this._isUndoing = true;
let r = this._commandManager.undo();
this._isUndoing = false;
if (!r) {
return null;
}
this._overwriteAlternativeVersionId(r.recordedVersionId);
return r.selections;
}
public undo(): Selection[] | null {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
return this._undo();
} finally {
this._eventEmitter.endDeferredEmit();
this._onDidChangeDecorations.endDeferredEmit();
}
public undo(): void {
this._undoRedoService.undo(this.uri);
}
public canUndo(): boolean {
return this._commandManager.canUndo();
return this._undoRedoService.canUndo(this.uri);
}
private _redo(): Selection[] | null {
this._isRedoing = true;
let r = this._commandManager.redo();
this._isRedoing = false;
if (!r) {
return null;
}
this._overwriteAlternativeVersionId(r.recordedVersionId);
return r.selections;
}
public redo(): Selection[] | null {
try {
this._onDidChangeDecorations.beginDeferredEmit();
this._eventEmitter.beginDeferredEmit();
return this._redo();
} finally {
this._eventEmitter.endDeferredEmit();
this._onDidChangeDecorations.endDeferredEmit();
}
public redo(): void {
this._undoRedoService.redo(this.uri);
}
public canRedo(): boolean {
return this._commandManager.canRedo();
return this._undoRedoService.canRedo(this.uri);
}
//#endregion
@@ -3191,10 +3194,11 @@ export class DidChangeContentEmitter extends Disposable {
this._deferredCnt++;
}
public endDeferredEmit(): void {
public endDeferredEmit(resultingSelection: Selection[] | null = null): void {
this._deferredCnt--;
if (this._deferredCnt === 0) {
if (this._deferredEvent !== null) {
this._deferredEvent.rawContentChangedEvent.resultingSelection = resultingSelection;
const e = this._deferredEvent;
this._deferredEvent = null;
this._fastEmitter.fire(e);

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IRange } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
/**
* An event describing that the current mode associated with a model has changed.
@@ -225,11 +226,14 @@ export class ModelRawContentChangedEvent {
*/
public readonly isRedoing: boolean;
public resultingSelection: Selection[] | null;
constructor(changes: ModelRawChange[], versionId: number, isUndoing: boolean, isRedoing: boolean) {
this.changes = changes;
this.versionId = versionId;
this.isUndoing = isUndoing;
this.isRedoing = isRedoing;
this.resultingSelection = null;
}
public containsEvent(type: RawContentChangedType): boolean {