mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 777931080477e28b7c27e8f7d4b0d69897945946 (#9220)
This commit is contained in:
@@ -86,7 +86,7 @@ class VisualEditorState {
|
||||
|
||||
constructor(
|
||||
private _contextMenuService: IContextMenuService,
|
||||
private _clipboardService: IClipboardService | null
|
||||
private _clipboardService: IClipboardService
|
||||
) {
|
||||
this._zones = [];
|
||||
this.inlineDiffMargins = [];
|
||||
@@ -136,7 +136,7 @@ class VisualEditorState {
|
||||
this._zones.push(zoneId);
|
||||
this._zonesMap[String(zoneId)] = true;
|
||||
|
||||
if (newDecorations.zones[i].diff && viewZone.marginDomNode && this._clipboardService) {
|
||||
if (newDecorations.zones[i].diff && viewZone.marginDomNode) {
|
||||
viewZone.suppressMouseDown = false;
|
||||
this.inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
|
||||
}
|
||||
@@ -223,7 +223,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
constructor(
|
||||
domElement: HTMLElement,
|
||||
options: IDiffEditorOptions,
|
||||
clipboardService: IClipboardService | null,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
@IEditorWorkerService editorWorkerService: IEditorWorkerService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
|
||||
@@ -12,10 +12,10 @@ import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperat
|
||||
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { TypeOperations, TypeWithAutoClosingCommand } from 'vs/editor/common/controller/cursorTypeOperations';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection, SelectionDirection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, ICursorStateComputer } from 'vs/editor/common/model';
|
||||
import { ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { RawContentChangedType } from 'vs/editor/common/model/textModelEvents';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
@@ -903,8 +903,8 @@ class CommandExecutor {
|
||||
if (commandsData.hadTrackedEditOperation && filteredOperations.length > 0) {
|
||||
filteredOperations[0]._isTracked = true;
|
||||
}
|
||||
let selectionsAfter = ctx.model.pushEditOperations(ctx.selectionsBefore, filteredOperations, (inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] => {
|
||||
let groupedInverseEditOperations: IIdentifiedSingleEditOperation[][] = [];
|
||||
let selectionsAfter = ctx.model.pushEditOperations(ctx.selectionsBefore, filteredOperations, (inverseEditOperations: IValidEditOperation[]): Selection[] => {
|
||||
let groupedInverseEditOperations: IValidEditOperation[][] = [];
|
||||
for (let i = 0; i < ctx.selectionsBefore.length; i++) {
|
||||
groupedInverseEditOperations[i] = [];
|
||||
}
|
||||
@@ -915,7 +915,7 @@ class CommandExecutor {
|
||||
}
|
||||
groupedInverseEditOperations[op.identifier.major].push(op);
|
||||
}
|
||||
const minorBasedSorter = (a: IIdentifiedSingleEditOperation, b: IIdentifiedSingleEditOperation) => {
|
||||
const minorBasedSorter = (a: IValidEditOperation, b: IValidEditOperation) => {
|
||||
return a.identifier!.minor - b.identifier!.minor;
|
||||
};
|
||||
let cursorSelections: Selection[] = [];
|
||||
@@ -1000,8 +1000,8 @@ class CommandExecutor {
|
||||
let operations: IIdentifiedSingleEditOperation[] = [];
|
||||
let operationMinor = 0;
|
||||
|
||||
const addEditOperation = (selection: Range, text: string | null, forceMoveMarkers: boolean = false) => {
|
||||
if (selection.isEmpty() && text === '') {
|
||||
const addEditOperation = (range: IRange, text: string | null, forceMoveMarkers: boolean = false) => {
|
||||
if (Range.isEmpty(range) && text === '') {
|
||||
// This command wants to add a no-op => no thank you
|
||||
return;
|
||||
}
|
||||
@@ -1010,7 +1010,7 @@ class CommandExecutor {
|
||||
major: majorIdentifier,
|
||||
minor: operationMinor++
|
||||
},
|
||||
range: selection,
|
||||
range: range,
|
||||
text: text,
|
||||
forceMoveMarkers: forceMoveMarkers,
|
||||
isAutoWhitespaceEdit: command.insertsAutoWhitespace
|
||||
@@ -1018,12 +1018,13 @@ class CommandExecutor {
|
||||
};
|
||||
|
||||
let hadTrackedEditOperation = false;
|
||||
const addTrackedEditOperation = (selection: Range, text: string | null, forceMoveMarkers?: boolean) => {
|
||||
const addTrackedEditOperation = (selection: IRange, text: string | null, forceMoveMarkers?: boolean) => {
|
||||
hadTrackedEditOperation = true;
|
||||
addEditOperation(selection, text, forceMoveMarkers);
|
||||
};
|
||||
|
||||
const trackSelection = (selection: Selection, trackPreviousOnEmpty?: boolean) => {
|
||||
const trackSelection = (_selection: ISelection, trackPreviousOnEmpty?: boolean) => {
|
||||
const selection = Selection.liftSelection(_selection);
|
||||
let stickiness: TrackedRangeStickiness;
|
||||
if (selection.isEmpty()) {
|
||||
if (typeof trackPreviousOnEmpty === 'boolean') {
|
||||
@@ -1093,7 +1094,7 @@ class CommandExecutor {
|
||||
const previousOp = operations[i - 1];
|
||||
const currentOp = operations[i];
|
||||
|
||||
if (previousOp.range.getStartPosition().isBefore(currentOp.range.getEndPosition())) {
|
||||
if (Range.getStartPosition(previousOp.range).isBefore(Range.getEndPosition(currentOp.range))) {
|
||||
|
||||
let loserMajor: number;
|
||||
|
||||
|
||||
@@ -264,14 +264,28 @@ export class Range {
|
||||
* Return the end position (which will be after or equal to the start position)
|
||||
*/
|
||||
public getEndPosition(): Position {
|
||||
return new Position(this.endLineNumber, this.endColumn);
|
||||
return Range.getEndPosition(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the end position (which will be after or equal to the start position)
|
||||
*/
|
||||
public static getEndPosition(range: IRange): Position {
|
||||
return new Position(range.endLineNumber, range.endColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start position (which will be before or equal to the end position)
|
||||
*/
|
||||
public getStartPosition(): Position {
|
||||
return new Position(this.startLineNumber, this.startColumn);
|
||||
return Range.getStartPosition(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start position (which will be before or equal to the end position)
|
||||
*/
|
||||
public static getStartPosition(range: IRange): Position {
|
||||
return new Position(range.startLineNumber, range.startColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ConfigurationChangedEvent, IComputedEditorOptions, IEditorOptions } fro
|
||||
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 { IIdentifiedSingleEditOperation, IModelDecorationsChangeAccessor, ITextModel, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import { IModelDecorationsChangeAccessor, ITextModel, OverviewRulerLane, TrackedRangeStickiness, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
/**
|
||||
@@ -22,7 +22,7 @@ export interface IEditOperationBuilder {
|
||||
* @param range The range to replace (delete). May be empty to represent a simple insert.
|
||||
* @param text The text to replace with. May be null to represent a simple delete.
|
||||
*/
|
||||
addEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
|
||||
addEditOperation(range: IRange, text: string | null, forceMoveMarkers?: boolean): void;
|
||||
|
||||
/**
|
||||
* Add a new edit operation (a replace operation).
|
||||
@@ -30,7 +30,7 @@ export interface IEditOperationBuilder {
|
||||
* @param range The range to replace (delete). May be empty to represent a simple insert.
|
||||
* @param text The text to replace with. May be null to represent a simple delete.
|
||||
*/
|
||||
addTrackedEditOperation(range: Range, text: string | null, forceMoveMarkers?: boolean): void;
|
||||
addTrackedEditOperation(range: IRange, text: string | null, forceMoveMarkers?: boolean): void;
|
||||
|
||||
/**
|
||||
* Track `selection` when applying edit operations.
|
||||
@@ -51,7 +51,7 @@ export interface ICursorStateComputerData {
|
||||
/**
|
||||
* Get the inverse edit operations of the added edit operations.
|
||||
*/
|
||||
getInverseEditOperations(): IIdentifiedSingleEditOperation[];
|
||||
getInverseEditOperations(): IValidEditOperation[];
|
||||
/**
|
||||
* Get a previously tracked selection.
|
||||
* @param id The unique identifier returned by `trackSelection`.
|
||||
|
||||
@@ -335,7 +335,7 @@ export interface IIdentifiedSingleEditOperation {
|
||||
/**
|
||||
* The range to replace. This can be empty to emulate a simple insert.
|
||||
*/
|
||||
range: Range;
|
||||
range: IRange;
|
||||
/**
|
||||
* The text to replace with. This can be null to emulate a simple delete.
|
||||
*/
|
||||
@@ -358,6 +358,27 @@ export interface IIdentifiedSingleEditOperation {
|
||||
_isTracked?: boolean;
|
||||
}
|
||||
|
||||
export interface IValidEditOperation {
|
||||
/**
|
||||
* An identifier associated with this single edit operation.
|
||||
* @internal
|
||||
*/
|
||||
identifier: ISingleEditOperationIdentifier | null;
|
||||
/**
|
||||
* The range to replace. This can be empty to emulate a simple insert.
|
||||
*/
|
||||
range: Range;
|
||||
/**
|
||||
* The text to replace with. This can be null to emulate a simple delete.
|
||||
*/
|
||||
text: string | null;
|
||||
/**
|
||||
* This indicates that this operation has "insert" semantics.
|
||||
* i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved.
|
||||
*/
|
||||
forceMoveMarkers: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback that can compute the cursor state after applying a series of edit operations.
|
||||
*/
|
||||
@@ -365,7 +386,7 @@ export interface ICursorStateComputer {
|
||||
/**
|
||||
* A callback that can compute the resulting cursors state after some edit operations have been executed.
|
||||
*/
|
||||
(inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] | null;
|
||||
(inverseEditOperations: IValidEditOperation[]): Selection[] | null;
|
||||
}
|
||||
|
||||
export class TextModelResolvedOptions {
|
||||
@@ -1063,7 +1084,7 @@ export interface ITextModel {
|
||||
* @param operations The edit operations.
|
||||
* @return The inverse edit operations, that, when applied, will bring the model back to the previous state.
|
||||
*/
|
||||
applyEdits(operations: IIdentifiedSingleEditOperation[]): IIdentifiedSingleEditOperation[];
|
||||
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
|
||||
|
||||
/**
|
||||
* Change the end of line sequence without recording in the undo stack.
|
||||
@@ -1206,6 +1227,20 @@ export const enum ModelConstants {
|
||||
FIRST_LINE_DETECTION_LENGTH_LIMIT = 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class ValidAnnotatedEditOperation implements IIdentifiedSingleEditOperation {
|
||||
constructor(
|
||||
public readonly identifier: ISingleEditOperationIdentifier | null,
|
||||
public readonly range: Range,
|
||||
public readonly text: string | null,
|
||||
public readonly forceMoveMarkers: boolean,
|
||||
public readonly isAutoWhitespaceEdit: boolean,
|
||||
public readonly _isTracked: boolean,
|
||||
) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -1234,7 +1269,7 @@ export interface ITextBuffer {
|
||||
getLineLastNonWhitespaceColumn(lineNumber: number): number;
|
||||
|
||||
setEOL(newEOL: '\r\n' | '\n'): void;
|
||||
applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult;
|
||||
applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult;
|
||||
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
|
||||
}
|
||||
|
||||
@@ -1244,7 +1279,7 @@ export interface ITextBuffer {
|
||||
export class ApplyEditsResult {
|
||||
|
||||
constructor(
|
||||
public readonly reverseEdits: IIdentifiedSingleEditOperation[],
|
||||
public readonly reverseEdits: IValidEditOperation[],
|
||||
public readonly changes: IInternalModelContentChange[],
|
||||
public readonly trimAutoWhitespaceLineNumbers: number[] | null
|
||||
) { }
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
|
||||
interface IEditOperation {
|
||||
operations: IIdentifiedSingleEditOperation[];
|
||||
operations: IValidEditOperation[];
|
||||
}
|
||||
|
||||
interface IStackElement {
|
||||
@@ -174,7 +174,7 @@ export class EditStack {
|
||||
return stackElement!.afterCursorState;
|
||||
}
|
||||
|
||||
private static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] | null {
|
||||
private static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IValidEditOperation[]): Selection[] | null {
|
||||
try {
|
||||
return cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null;
|
||||
} catch (e) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ApplyEditsResult, EndOfLinePreference, FindMatch, IIdentifiedSingleEditOperation, IInternalModelContentChange, ISingleEditOperationIdentifier, ITextBuffer, ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { ApplyEditsResult, EndOfLinePreference, FindMatch, IInternalModelContentChange, ISingleEditOperationIdentifier, ITextBuffer, ITextSnapshot, ValidAnnotatedEditOperation, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase';
|
||||
import { SearchData } from 'vs/editor/common/model/textModelSearch';
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface IValidatedEditOperation {
|
||||
isAutoWhitespaceEdit: boolean;
|
||||
}
|
||||
|
||||
export interface IReverseSingleEditOperation extends IIdentifiedSingleEditOperation {
|
||||
export interface IReverseSingleEditOperation extends IValidEditOperation {
|
||||
sortIndex: number;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ export class PieceTreeTextBuffer implements ITextBuffer {
|
||||
this._pieceTree.setEOL(newEOL);
|
||||
}
|
||||
|
||||
public applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult {
|
||||
public applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult {
|
||||
let mightContainRTL = this._mightContainRTL;
|
||||
let mightContainNonBasicASCII = this._mightContainNonBasicASCII;
|
||||
let canReduceOperations = true;
|
||||
|
||||
@@ -1154,18 +1154,40 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
private _validateEditOperation(rawOperation: model.IIdentifiedSingleEditOperation): model.ValidAnnotatedEditOperation {
|
||||
if (rawOperation instanceof model.ValidAnnotatedEditOperation) {
|
||||
return rawOperation;
|
||||
}
|
||||
return new model.ValidAnnotatedEditOperation(
|
||||
rawOperation.identifier || null,
|
||||
this.validateRange(rawOperation.range),
|
||||
rawOperation.text,
|
||||
rawOperation.forceMoveMarkers || false,
|
||||
rawOperation.isAutoWhitespaceEdit || false,
|
||||
rawOperation._isTracked || false
|
||||
);
|
||||
}
|
||||
|
||||
private _validateEditOperations(rawOperations: model.IIdentifiedSingleEditOperation[]): model.ValidAnnotatedEditOperation[] {
|
||||
const result: model.ValidAnnotatedEditOperation[] = [];
|
||||
for (let i = 0, len = rawOperations.length; i < len; i++) {
|
||||
result[i] = this._validateEditOperation(rawOperations[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
return this._pushEditOperations(beforeCursorState, editOperations, cursorStateComputer);
|
||||
return this._pushEditOperations(beforeCursorState, this._validateEditOperations(editOperations), cursorStateComputer);
|
||||
} finally {
|
||||
this._eventEmitter.endDeferredEmit();
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.ValidAnnotatedEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
|
||||
// Go through each saved line number and insert a trim whitespace edit
|
||||
// if it is safe to do so (no conflicts with other edits).
|
||||
@@ -1238,10 +1260,8 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
if (allowTrimLine) {
|
||||
editOperations.push({
|
||||
range: new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn),
|
||||
text: null
|
||||
});
|
||||
const trimRange = new Range(trimLineNumber, 1, trimLineNumber, maxLineColumn);
|
||||
editOperations.push(new model.ValidAnnotatedEditOperation(null, trimRange, null, false, false, false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1252,21 +1272,18 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);
|
||||
}
|
||||
|
||||
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IIdentifiedSingleEditOperation[] {
|
||||
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IValidEditOperation[] {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
return this._applyEdits(rawOperations);
|
||||
return this._applyEdits(this._validateEditOperations(rawOperations));
|
||||
} finally {
|
||||
this._eventEmitter.endDeferredEmit();
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
private _applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IIdentifiedSingleEditOperation[] {
|
||||
for (let i = 0, len = rawOperations.length; i < len; i++) {
|
||||
rawOperations[i].range = this.validateRange(rawOperations[i].range);
|
||||
}
|
||||
private _applyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] {
|
||||
|
||||
const oldLineCount = this._buffer.getLineCount();
|
||||
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace);
|
||||
|
||||
@@ -1324,7 +1324,7 @@ export interface WorkspaceEditMetadata {
|
||||
needsConfirmation: boolean;
|
||||
label: string;
|
||||
description?: string;
|
||||
iconPath?: { id: string } | { light: URI, dark: URI };
|
||||
iconPath?: { id: string } | URI | { light: URI, dark: URI };
|
||||
}
|
||||
|
||||
export interface WorkspaceFileEditOptions {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';
|
||||
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
|
||||
import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { LanguageIdentifier, DocumentSemanticTokensProviderRegistry, DocumentSemanticTokensProvider, SemanticTokensLegend, SemanticTokens, SemanticTokensEdits, TokenMetadata, FontStyle, MetadataConsts } from 'vs/editor/common/modes';
|
||||
@@ -305,7 +305,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
model.pushEditOperations(
|
||||
[],
|
||||
ModelServiceImpl._computeEdits(model, textBuffer),
|
||||
(inverseEditOperations: IIdentifiedSingleEditOperation[]) => []
|
||||
(inverseEditOperations: IValidEditOperation[]) => []
|
||||
);
|
||||
model.pushStackElement();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ICommand, IEditOperationBuilder, ICursorStateComputerData } from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';
|
||||
import { ITextModel, IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
|
||||
export class BlockCommentCommand implements ICommand {
|
||||
|
||||
@@ -205,7 +205,7 @@ export class LineCommentCommand implements ICommand {
|
||||
|
||||
for (let i = 0, len = ops.length; i < len; i++) {
|
||||
builder.addEditOperation(ops[i].range, ops[i].text);
|
||||
if (ops[i].range.isEmpty() && ops[i].range.getStartPosition().equals(cursorPosition)) {
|
||||
if (Range.isEmpty(ops[i].range) && Range.getStartPosition(ops[i].range).equals(cursorPosition)) {
|
||||
const lineContent = model.getLineContent(cursorPosition.lineNumber);
|
||||
if (lineContent.length + 1 === cursorPosition.column) {
|
||||
this._deltaColumn = (ops[i].text || '').length;
|
||||
|
||||
@@ -25,6 +25,10 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
|
||||
function getHoverMessage(link: Link, useMetaKey: boolean): MarkdownString {
|
||||
const executeCmd = link.url && /^command:/i.test(link.url.toString());
|
||||
@@ -291,7 +295,29 @@ class LinkDetector implements IEditorContribution {
|
||||
const { link } = occurrence;
|
||||
|
||||
link.resolve(CancellationToken.None).then(uri => {
|
||||
// open the uri
|
||||
|
||||
// Support for relative file URIs of the shape file://./relativeFile.txt or file:///./relativeFile.txt
|
||||
if (typeof uri === 'string' && this.editor.hasModel()) {
|
||||
const modelUri = this.editor.getModel().uri;
|
||||
if (modelUri.scheme === Schemas.file && strings.startsWith(uri, 'file:')) {
|
||||
const parsedUri = URI.parse(uri);
|
||||
if (parsedUri.scheme === Schemas.file) {
|
||||
const fsPath = resources.originalFSPath(parsedUri);
|
||||
|
||||
let relativePath: string | null = null;
|
||||
if (strings.startsWith(fsPath, '/./')) {
|
||||
relativePath = `.${fsPath.substr(1)}`;
|
||||
} else if (strings.startsWith(fsPath, '//./')) {
|
||||
relativePath = `.${fsPath.substr(2)}`;
|
||||
}
|
||||
|
||||
if (relativePath) {
|
||||
uri = resources.joinPath(modelUri, relativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.openerService.open(uri, { openToSide, fromUserGesture });
|
||||
|
||||
}, err => {
|
||||
|
||||
@@ -26,7 +26,7 @@ import { IResolvedTextEditorModel, ITextModelContentProvider, ITextModelService
|
||||
import { ITextResourceConfigurationService, ITextResourcePropertiesService, ITextResourceConfigurationChangeEvent } from 'vs/editor/common/services/textResourceConfigurationService';
|
||||
import { CommandsRegistry, ICommand, ICommandEvent, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService, IConfigurationModel, IConfigurationValue, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { Configuration, ConfigurationModel, DefaultConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfirmation, IConfirmationResult, IDialogOptions, IDialogService, IShowResult } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -448,10 +448,6 @@ export class SimpleConfigurationService implements IConfigurationService {
|
||||
this._configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel());
|
||||
}
|
||||
|
||||
private configuration(): Configuration {
|
||||
return this._configuration;
|
||||
}
|
||||
|
||||
getValue<T>(): T;
|
||||
getValue<T>(section: string): T;
|
||||
getValue<T>(overrides: IConfigurationOverrides): T;
|
||||
@@ -459,20 +455,43 @@ export class SimpleConfigurationService implements IConfigurationService {
|
||||
getValue(arg1?: any, arg2?: any): any {
|
||||
const section = typeof arg1 === 'string' ? arg1 : undefined;
|
||||
const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {};
|
||||
return this.configuration().getValue(section, overrides, undefined);
|
||||
return this._configuration.getValue(section, overrides, undefined);
|
||||
}
|
||||
|
||||
public updateValue(key: string, value: any, arg3?: any, arg4?: any): Promise<void> {
|
||||
this.configuration().updateValue(key, value);
|
||||
public updateValues(values: [string, any][]): Promise<void> {
|
||||
const previous = { data: this._configuration.toData() };
|
||||
|
||||
let changedKeys: string[] = [];
|
||||
|
||||
for (const entry of values) {
|
||||
const [key, value] = entry;
|
||||
if (this.getValue(key) === value) {
|
||||
continue;
|
||||
}
|
||||
this._configuration.updateValue(key, value);
|
||||
changedKeys.push(key);
|
||||
}
|
||||
|
||||
if (changedKeys.length > 0) {
|
||||
const configurationChangeEvent = new ConfigurationChangeEvent({ keys: changedKeys, overrides: [] }, previous, this._configuration);
|
||||
configurationChangeEvent.source = ConfigurationTarget.MEMORY;
|
||||
configurationChangeEvent.sourceConfig = null;
|
||||
this._onDidChangeConfiguration.fire(configurationChangeEvent);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public updateValue(key: string, value: any, arg3?: any, arg4?: any): Promise<void> {
|
||||
return this.updateValues([[key, value]]);
|
||||
}
|
||||
|
||||
public inspect<C>(key: string, options: IConfigurationOverrides = {}): IConfigurationValue<C> {
|
||||
return this.configuration().inspect<C>(key, options, undefined);
|
||||
return this._configuration.inspect<C>(key, options, undefined);
|
||||
}
|
||||
|
||||
public keys() {
|
||||
return this.configuration().keys(undefined);
|
||||
return this._configuration.keys(undefined);
|
||||
}
|
||||
|
||||
public reloadConfiguration(): Promise<void> {
|
||||
@@ -622,14 +641,18 @@ export function applyConfigurationValues(configurationService: IConfigurationSer
|
||||
if (!(configurationService instanceof SimpleConfigurationService)) {
|
||||
return;
|
||||
}
|
||||
let toUpdate: [string, any][] = [];
|
||||
Object.keys(source).forEach((key) => {
|
||||
if (isEditorConfigurationKey(key)) {
|
||||
configurationService.updateValue(`editor.${key}`, source[key]);
|
||||
toUpdate.push([`editor.${key}`, source[key]]);
|
||||
}
|
||||
if (isDiffEditor && isDiffEditorConfigurationKey(key)) {
|
||||
configurationService.updateValue(`diffEditor.${key}`, source[key]);
|
||||
toUpdate.push([`diffEditor.${key}`, source[key]]);
|
||||
}
|
||||
});
|
||||
if (toUpdate.length > 0) {
|
||||
configurationService.updateValues(toUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleBulkEditService implements IBulkEditService {
|
||||
|
||||
@@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
|
||||
import { IInstantiationService, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -114,6 +114,11 @@ export interface IGlobalEditorOptions {
|
||||
* Defaults to true.
|
||||
*/
|
||||
wordBasedSuggestions?: boolean;
|
||||
/**
|
||||
* Controls whether the semanticHighlighting is shown for the languages that support it.
|
||||
* Defaults to true.
|
||||
*/
|
||||
'semanticHighlighting.enabled'?: boolean;
|
||||
/**
|
||||
* Keep peek editors open even when double clicking their content or when hitting `Escape`.
|
||||
* Defaults to false.
|
||||
@@ -443,7 +448,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IEditorProgressService editorProgressService: IEditorProgressService,
|
||||
@optional(IClipboardService) clipboardService: IClipboardService | null,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
) {
|
||||
applyConfigurationValues(configurationService, options, true);
|
||||
const themeDomRegistration = (<StandaloneThemeServiceImpl>themeService).registerEditorContainer(domElement);
|
||||
|
||||
@@ -39,6 +39,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { clearAllFontInfos } from 'vs/editor/browser/config/configuration';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
||||
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
@@ -122,7 +123,7 @@ export function createDiffEditor(domElement: HTMLElement, options?: IDiffEditorC
|
||||
services.get(IConfigurationService),
|
||||
services.get(IContextMenuService),
|
||||
services.get(IEditorProgressService),
|
||||
null
|
||||
services.get(IClipboardService)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions';
|
||||
import { AccessibilityService } from 'vs/platform/accessibility/common/accessibilityService';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { BrowserClipboardService } from 'vs/platform/clipboard/browser/clipboardService';
|
||||
|
||||
export interface IEditorOverrideServices {
|
||||
[index: string]: any;
|
||||
@@ -204,6 +206,8 @@ export class DynamicStandaloneServices extends Disposable {
|
||||
|
||||
let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(layoutService)));
|
||||
|
||||
ensure(IClipboardService, () => new BrowserClipboardService());
|
||||
|
||||
ensure(IContextMenuService, () => {
|
||||
const contextMenuService = new ContextMenuService(telemetryService, notificationService, contextViewService, keybindingService, themeService);
|
||||
contextMenuService.configure({ blockMouse: false }); // we do not want that in the standalone editor
|
||||
|
||||
@@ -2880,6 +2880,33 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #90973: Undo brings back model alternative version', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
''
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: false,
|
||||
}
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
const beforeVersion = model.getVersionId();
|
||||
const beforeAltVersion = model.getAlternativeVersionId();
|
||||
cursorCommand(cursor, H.Type, { text: 'Hello' }, 'keyboard');
|
||||
cursorCommand(cursor, H.Undo, {});
|
||||
const afterVersion = model.getVersionId();
|
||||
const afterAltVersion = model.getAlternativeVersionId();
|
||||
|
||||
assert.notEqual(beforeVersion, afterVersion);
|
||||
assert.equal(beforeAltVersion, afterAltVersion);
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
suite('Editor Controller - Indentation Rules', () => {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { Selection, ISelection } from 'vs/editor/common/core/selection';
|
||||
import { ICommand, Handler, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
@@ -50,7 +50,7 @@ export function testCommand(
|
||||
export function getEditOperation(model: ITextModel, command: ICommand): IIdentifiedSingleEditOperation[] {
|
||||
let operations: IIdentifiedSingleEditOperation[] = [];
|
||||
let editOperationBuilder: IEditOperationBuilder = {
|
||||
addEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
|
||||
addEditOperation: (range: IRange, text: string, forceMoveMarkers: boolean = false) => {
|
||||
operations.push({
|
||||
range: range,
|
||||
text: text,
|
||||
@@ -58,7 +58,7 @@ export function getEditOperation(model: ITextModel, command: ICommand): IIdentif
|
||||
});
|
||||
},
|
||||
|
||||
addTrackedEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
|
||||
addTrackedEditOperation: (range: IRange, text: string, forceMoveMarkers: boolean = false) => {
|
||||
operations.push({
|
||||
range: range,
|
||||
text: text,
|
||||
@@ -67,7 +67,7 @@ export function getEditOperation(model: ITextModel, command: ICommand): IIdentif
|
||||
},
|
||||
|
||||
|
||||
trackSelection: (selection: Selection) => {
|
||||
trackSelection: (selection: ISelection) => {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { DefaultEndOfLine, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferBuilder } from 'vs/editor/common/model';
|
||||
import { DefaultEndOfLine, ITextBuffer, ITextBufferBuilder, ValidAnnotatedEditOperation } from 'vs/editor/common/model';
|
||||
|
||||
export function getRandomInt(min: number, max: number): number {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
@@ -31,7 +31,7 @@ export function getRandomString(minLength: number, maxLength: number): string {
|
||||
return r;
|
||||
}
|
||||
|
||||
export function generateRandomEdits(chunks: string[], editCnt: number): IIdentifiedSingleEditOperation[] {
|
||||
export function generateRandomEdits(chunks: string[], editCnt: number): ValidAnnotatedEditOperation[] {
|
||||
let lines: string[] = [];
|
||||
for (const chunk of chunks) {
|
||||
let newLines = chunk.split(/\r\n|\r|\n/);
|
||||
@@ -43,7 +43,7 @@ export function generateRandomEdits(chunks: string[], editCnt: number): IIdentif
|
||||
}
|
||||
}
|
||||
|
||||
let ops: IIdentifiedSingleEditOperation[] = [];
|
||||
let ops: ValidAnnotatedEditOperation[] = [];
|
||||
|
||||
for (let i = 0; i < editCnt; i++) {
|
||||
let line = getRandomInt(1, lines.length);
|
||||
@@ -54,17 +54,14 @@ export function generateRandomEdits(chunks: string[], editCnt: number): IIdentif
|
||||
text = getRandomString(5, 10);
|
||||
}
|
||||
|
||||
ops.push({
|
||||
text: text,
|
||||
range: new Range(line, startColumn, line, endColumn)
|
||||
});
|
||||
ops.push(new ValidAnnotatedEditOperation(null, new Range(line, startColumn, line, endColumn), text, false, false, false));
|
||||
lines[line - 1] = lines[line - 1].substring(0, startColumn - 1) + text + lines[line - 1].substring(endColumn - 1);
|
||||
}
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
export function generateSequentialInserts(chunks: string[], editCnt: number): IIdentifiedSingleEditOperation[] {
|
||||
export function generateSequentialInserts(chunks: string[], editCnt: number): ValidAnnotatedEditOperation[] {
|
||||
let lines: string[] = [];
|
||||
for (const chunk of chunks) {
|
||||
let newLines = chunk.split(/\r\n|\r|\n/);
|
||||
@@ -76,7 +73,7 @@ export function generateSequentialInserts(chunks: string[], editCnt: number): II
|
||||
}
|
||||
}
|
||||
|
||||
let ops: IIdentifiedSingleEditOperation[] = [];
|
||||
let ops: ValidAnnotatedEditOperation[] = [];
|
||||
|
||||
for (let i = 0; i < editCnt; i++) {
|
||||
let line = lines.length;
|
||||
@@ -90,16 +87,13 @@ export function generateSequentialInserts(chunks: string[], editCnt: number): II
|
||||
lines[line - 1] += text;
|
||||
}
|
||||
|
||||
ops.push({
|
||||
text: text,
|
||||
range: new Range(line, column, line, column)
|
||||
});
|
||||
ops.push(new ValidAnnotatedEditOperation(null, new Range(line, column, line, column), text, false, false, false));
|
||||
}
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
export function generateRandomReplaces(chunks: string[], editCnt: number, searchStringLen: number, replaceStringLen: number): IIdentifiedSingleEditOperation[] {
|
||||
export function generateRandomReplaces(chunks: string[], editCnt: number, searchStringLen: number, replaceStringLen: number): ValidAnnotatedEditOperation[] {
|
||||
let lines: string[] = [];
|
||||
for (const chunk of chunks) {
|
||||
let newLines = chunk.split(/\r\n|\r|\n/);
|
||||
@@ -111,7 +105,7 @@ export function generateRandomReplaces(chunks: string[], editCnt: number, search
|
||||
}
|
||||
}
|
||||
|
||||
let ops: IIdentifiedSingleEditOperation[] = [];
|
||||
let ops: ValidAnnotatedEditOperation[] = [];
|
||||
let chunkSize = Math.max(1, Math.floor(lines.length / editCnt));
|
||||
let chunkCnt = Math.floor(lines.length / chunkSize);
|
||||
let replaceString = getRandomString(replaceStringLen, replaceStringLen);
|
||||
@@ -125,10 +119,7 @@ export function generateRandomReplaces(chunks: string[], editCnt: number, search
|
||||
let startColumn = getRandomInt(1, maxColumn);
|
||||
let endColumn = Math.min(maxColumn, startColumn + searchStringLen);
|
||||
|
||||
ops.push({
|
||||
text: replaceString,
|
||||
range: new Range(line, startColumn, line, endColumn)
|
||||
});
|
||||
ops.push(new ValidAnnotatedEditOperation(null, new Range(line, startColumn, line, endColumn), replaceString, false, false, false));
|
||||
previousChunksLength = endLine;
|
||||
}
|
||||
|
||||
@@ -166,4 +157,4 @@ export function generateRandomChunkWithLF(minLength: number, maxLength: number):
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user