mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 (#8911)
* Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 * update distro * fix layering * update distro * fix tests
This commit is contained in:
@@ -22,7 +22,8 @@ import { EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions'
|
||||
export function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
|
||||
return {
|
||||
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
|
||||
text: text
|
||||
text: text,
|
||||
forceMoveMarkers: false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
|
||||
function testCommand(lines: string[], selections: Selection[], edits: IIdentifiedSingleEditOperation[], expectedLines: string[], expectedSelections: Selection[]): void {
|
||||
withTestCodeEditor(lines, {}, (editor, cursor) => {
|
||||
@@ -200,7 +201,8 @@ suite('SideEditing', () => {
|
||||
function _runTest(selection: Selection, editRange: Range, editText: string, editForceMoveMarkers: boolean, expected: Selection, msg: string): void {
|
||||
const model = TextModel.createFromString(LINES.join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(config.options);
|
||||
const viewModel = new ViewModel(0, config, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
cursor.setSelections('tests', [selection]);
|
||||
|
||||
@@ -28,7 +28,8 @@ function createInsertDeleteSingleEditOp(text: string | null, positionLineNumber:
|
||||
export function createSingleEditOp(text: string | null, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
|
||||
return {
|
||||
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
|
||||
text: text
|
||||
text: text,
|
||||
forceMoveMarkers: false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,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 { TokenizationResult2 } from 'vs/editor/common/core/token';
|
||||
import { Handler, ICommand, ICursorStateComputerData, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
|
||||
import { Handler, ICommand, ICursorStateComputerData, IEditOperationBuilder, IConfiguration } from 'vs/editor/common/editorCommon';
|
||||
import { EndOfLinePreference, EndOfLineSequence, ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IState, ITokenizationSupport, LanguageIdentifier, TokenizationRegistry } from 'vs/editor/common/modes';
|
||||
@@ -25,6 +25,7 @@ import { IRelaxedTextModelCreationOptions, createTextModel } from 'vs/editor/tes
|
||||
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
|
||||
const H = Handler;
|
||||
|
||||
@@ -130,6 +131,11 @@ function assertCursor(cursor: Cursor, what: Position | Selection | Selection[]):
|
||||
assert.deepEqual(actual, expected);
|
||||
}
|
||||
|
||||
function createViewModel(configuration: IConfiguration, model: ITextModel): ViewModel {
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(configuration.options);
|
||||
return new ViewModel(0, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
}
|
||||
|
||||
suite('Editor Controller - Cursor', () => {
|
||||
const LINE1 = ' \tMy First Line\t ';
|
||||
const LINE2 = '\tMy Second Line';
|
||||
@@ -152,7 +158,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
|
||||
thisModel = createTextModel(text);
|
||||
thisConfiguration = new TestConfiguration({});
|
||||
thisViewModel = new ViewModel(0, thisConfiguration, thisModel, null!);
|
||||
thisViewModel = createViewModel(thisConfiguration, thisModel);
|
||||
|
||||
thisCursor = new Cursor(thisConfiguration, thisModel, thisViewModel);
|
||||
});
|
||||
@@ -776,7 +782,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'var newer = require("gulp-newer");',
|
||||
].join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const viewModel = createViewModel(config, model);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
moveTo(cursor, 1, 4, false);
|
||||
@@ -816,7 +822,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'<property id="SomeThing" key="SomeKey" value="00X"/>',
|
||||
].join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const viewModel = createViewModel(config, model);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
moveTo(cursor, 10, 10, false);
|
||||
@@ -880,7 +886,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'<property id="SomeThing" key="SomeKey" value="00X"/>',
|
||||
].join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const viewModel = createViewModel(config, model);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
moveTo(cursor, 10, 10, false);
|
||||
@@ -929,7 +935,7 @@ suite('Editor Controller - Cursor', () => {
|
||||
'var newer = require("gulp-newer");',
|
||||
].join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const viewModel = createViewModel(config, model);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
moveTo(cursor, 1, 4, false);
|
||||
@@ -2074,7 +2080,7 @@ suite('Editor Controller - Regression tests', () => {
|
||||
wordWrap: 'wordWrapColumn',
|
||||
wordWrapColumn: 100
|
||||
});
|
||||
const viewModel = new ViewModel(0, config, model, null!);
|
||||
const viewModel = createViewModel(config, model);
|
||||
const cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
moveTo(cursor, 1, 43, false);
|
||||
@@ -2273,6 +2279,64 @@ suite('Editor Controller - Regression tests', () => {
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #85712: Paste line moves cursor to start of current line rather than start of next line', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
'abc123',
|
||||
''
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
editor.setSelections([
|
||||
new Selection(2, 1, 2, 1)
|
||||
]);
|
||||
cursorCommand(cursor, H.Paste, { text: 'something\n', pasteOnNewLine: true });
|
||||
assert.equal(model.getValue(), [
|
||||
'abc123',
|
||||
'something',
|
||||
''
|
||||
].join('\n'));
|
||||
assertCursor(cursor, new Position(3, 1));
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #84897: Left delete behavior in some languages is changed', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
'สวัสดี'
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
editor.setSelections([
|
||||
new Selection(1, 7, 1, 7)
|
||||
]);
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'สวัสด');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'สวัส');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'สวั');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'สว');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), 'ส');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(EndOfLinePreference.LF), '');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
suite('Editor Controller - Cursor Configuration', () => {
|
||||
@@ -2630,7 +2694,7 @@ suite('Editor Controller - Cursor Configuration', () => {
|
||||
'',
|
||||
' }',
|
||||
].join('\n'));
|
||||
assertCursor(cursor, new Position(4, 1));
|
||||
assertCursor(cursor, new Position(5, 1));
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
@@ -3834,7 +3898,7 @@ function usingCursor(opts: ICursorOpts, callback: (model: TextModel, cursor: Cur
|
||||
let model = createTextModel(opts.text.join('\n'), opts.modelOpts, opts.languageIdentifier);
|
||||
model.forceTokenization(model.getLineCount());
|
||||
let config = new TestConfiguration(opts.editorOpts || {});
|
||||
let viewModel = new ViewModel(0, config, model, null!);
|
||||
let viewModel = createViewModel(config, model);
|
||||
let cursor = new Cursor(config, model, viewModel);
|
||||
|
||||
callback(model, cursor);
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
|
||||
suite('Cursor move command test', () => {
|
||||
|
||||
@@ -32,7 +33,8 @@ suite('Cursor move command test', () => {
|
||||
|
||||
thisModel = TextModel.createFromString(text);
|
||||
thisConfiguration = new TestConfiguration({});
|
||||
thisViewModel = new ViewModel(0, thisConfiguration, thisModel, null!);
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(thisConfiguration.options);
|
||||
thisViewModel = new ViewModel(0, thisConfiguration, thisModel, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
thisCursor = new Cursor(thisConfiguration, thisModel, thisViewModel);
|
||||
});
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { View } from 'vs/editor/browser/view/viewImpl';
|
||||
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import * as editorOptions from 'vs/editor/common/config/editorOptions';
|
||||
import { Cursor } from 'vs/editor/common/controller/cursor';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IConfiguration, IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
@@ -26,10 +26,10 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
|
||||
export class TestCodeEditor extends CodeEditorWidget implements editorBrowser.ICodeEditor {
|
||||
export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor {
|
||||
|
||||
//#region testing overrides
|
||||
protected _createConfiguration(options: editorOptions.IEditorConstructionOptions): editorCommon.IConfiguration {
|
||||
protected _createConfiguration(options: editorOptions.IEditorConstructionOptions): IConfiguration {
|
||||
return new TestConfiguration(options);
|
||||
}
|
||||
protected _createView(viewModel: ViewModel, cursor: Cursor): [View, boolean] {
|
||||
@@ -42,7 +42,7 @@ export class TestCodeEditor extends CodeEditorWidget implements editorBrowser.IC
|
||||
public getCursor(): Cursor | undefined {
|
||||
return this._modelData ? this._modelData.cursor : undefined;
|
||||
}
|
||||
public registerAndInstantiateContribution<T extends editorCommon.IEditorContribution>(id: string, ctor: any): T {
|
||||
public registerAndInstantiateContribution<T extends IEditorContribution>(id: string, ctor: any): T {
|
||||
let r = <T>this._instantiationService.createInstance(ctor, this);
|
||||
this._contributions[id] = r;
|
||||
return r;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
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';
|
||||
import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
@@ -16,7 +16,7 @@ export function testCommand(
|
||||
lines: string[],
|
||||
languageIdentifier: LanguageIdentifier | null,
|
||||
selection: Selection,
|
||||
commandFactory: (selection: Selection) => editorCommon.ICommand,
|
||||
commandFactory: (selection: Selection) => ICommand,
|
||||
expectedLines: string[],
|
||||
expectedSelection: Selection,
|
||||
forceTokenization?: boolean
|
||||
@@ -33,7 +33,7 @@ export function testCommand(
|
||||
|
||||
cursor.setSelections('tests', [selection]);
|
||||
|
||||
cursor.trigger('tests', editorCommon.Handler.ExecuteCommand, commandFactory(cursor.getSelection()));
|
||||
cursor.trigger('tests', Handler.ExecuteCommand, commandFactory(cursor.getSelection()));
|
||||
|
||||
assert.deepEqual(model.getLinesContent(), expectedLines);
|
||||
|
||||
@@ -47,20 +47,22 @@ export function testCommand(
|
||||
/**
|
||||
* Extract edit operations if command `command` were to execute on model `model`
|
||||
*/
|
||||
export function getEditOperation(model: ITextModel, command: editorCommon.ICommand): IIdentifiedSingleEditOperation[] {
|
||||
export function getEditOperation(model: ITextModel, command: ICommand): IIdentifiedSingleEditOperation[] {
|
||||
let operations: IIdentifiedSingleEditOperation[] = [];
|
||||
let editOperationBuilder: editorCommon.IEditOperationBuilder = {
|
||||
addEditOperation: (range: Range, text: string) => {
|
||||
let editOperationBuilder: IEditOperationBuilder = {
|
||||
addEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
|
||||
operations.push({
|
||||
range: range,
|
||||
text: text
|
||||
text: text,
|
||||
forceMoveMarkers: forceMoveMarkers
|
||||
});
|
||||
},
|
||||
|
||||
addTrackedEditOperation: (range: Range, text: string) => {
|
||||
addTrackedEditOperation: (range: Range, text: string, forceMoveMarkers: boolean = false) => {
|
||||
operations.push({
|
||||
range: range,
|
||||
text: text
|
||||
text: text,
|
||||
forceMoveMarkers: forceMoveMarkers
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -743,87 +743,6 @@ suite('Editor Model - TextModel', () => {
|
||||
assert.deepEqual(m.validatePosition(new Position(2, 1.5)), new Position(2, 1), 'h');
|
||||
});
|
||||
|
||||
function assertValidatePosition(m: TextModel, lineNumber: number, column: number, expectedColumn: number): void {
|
||||
const input = new Position(lineNumber, column);
|
||||
const actual = m.validatePosition(input);
|
||||
const expected = new Position(lineNumber, expectedColumn);
|
||||
assert.deepEqual(actual, expected, `validatePosition for ${input}, got ${actual}, expected ${expected}`);
|
||||
}
|
||||
|
||||
function assertValidateRange(m: TextModel, input: Range, expected: Range): void {
|
||||
const actual = m.validateRange(input);
|
||||
assert.deepEqual(actual, expected, `validateRange for ${input}, got ${actual}, expected ${expected}`);
|
||||
}
|
||||
|
||||
test('grapheme breaking', () => {
|
||||
const m = TextModel.createFromString([
|
||||
'abcabc',
|
||||
'ãããããã',
|
||||
'辻󠄀辻󠄀辻󠄀',
|
||||
'புபுபு',
|
||||
].join('\n'));
|
||||
|
||||
assertValidatePosition(m, 2, 1, 1);
|
||||
assertValidatePosition(m, 2, 2, 1);
|
||||
assertValidatePosition(m, 2, 3, 3);
|
||||
assertValidatePosition(m, 2, 4, 3);
|
||||
assertValidatePosition(m, 2, 5, 5);
|
||||
assertValidatePosition(m, 2, 6, 5);
|
||||
assertValidatePosition(m, 2, 7, 7);
|
||||
assertValidatePosition(m, 2, 8, 7);
|
||||
assertValidatePosition(m, 2, 9, 9);
|
||||
assertValidatePosition(m, 2, 10, 9);
|
||||
assertValidatePosition(m, 2, 11, 11);
|
||||
assertValidatePosition(m, 2, 12, 11);
|
||||
assertValidatePosition(m, 2, 13, 13);
|
||||
assertValidatePosition(m, 2, 14, 13);
|
||||
|
||||
assertValidatePosition(m, 3, 1, 1);
|
||||
assertValidatePosition(m, 3, 2, 1);
|
||||
assertValidatePosition(m, 3, 3, 1);
|
||||
assertValidatePosition(m, 3, 4, 4);
|
||||
assertValidatePosition(m, 3, 5, 4);
|
||||
assertValidatePosition(m, 3, 6, 4);
|
||||
assertValidatePosition(m, 3, 7, 7);
|
||||
assertValidatePosition(m, 3, 8, 7);
|
||||
assertValidatePosition(m, 3, 9, 7);
|
||||
assertValidatePosition(m, 3, 10, 10);
|
||||
|
||||
assertValidatePosition(m, 4, 1, 1);
|
||||
assertValidatePosition(m, 4, 2, 1);
|
||||
assertValidatePosition(m, 4, 3, 3);
|
||||
assertValidatePosition(m, 4, 4, 3);
|
||||
assertValidatePosition(m, 4, 5, 5);
|
||||
assertValidatePosition(m, 4, 6, 5);
|
||||
assertValidatePosition(m, 4, 7, 7);
|
||||
|
||||
assertValidateRange(m, new Range(2, 1, 2, 1), new Range(2, 1, 2, 1));
|
||||
assertValidateRange(m, new Range(2, 1, 2, 2), new Range(2, 1, 2, 3));
|
||||
assertValidateRange(m, new Range(2, 1, 2, 3), new Range(2, 1, 2, 3));
|
||||
assertValidateRange(m, new Range(2, 1, 2, 4), new Range(2, 1, 2, 5));
|
||||
assertValidateRange(m, new Range(2, 1, 2, 5), new Range(2, 1, 2, 5));
|
||||
assertValidateRange(m, new Range(2, 2, 2, 2), new Range(2, 1, 2, 1));
|
||||
assertValidateRange(m, new Range(2, 2, 2, 3), new Range(2, 1, 2, 3));
|
||||
assertValidateRange(m, new Range(2, 2, 2, 4), new Range(2, 1, 2, 5));
|
||||
assertValidateRange(m, new Range(2, 2, 2, 5), new Range(2, 1, 2, 5));
|
||||
|
||||
assertValidateRange(m, new Range(3, 1, 3, 1), new Range(3, 1, 3, 1));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 2), new Range(3, 1, 3, 4));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 3), new Range(3, 1, 3, 4));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 4), new Range(3, 1, 3, 4));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 5), new Range(3, 1, 3, 7));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 6), new Range(3, 1, 3, 7));
|
||||
assertValidateRange(m, new Range(3, 1, 3, 7), new Range(3, 1, 3, 7));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 2), new Range(3, 1, 3, 1));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 3), new Range(3, 1, 3, 4));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 4), new Range(3, 1, 3, 4));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 5), new Range(3, 1, 3, 7));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 6), new Range(3, 1, 3, 7));
|
||||
assertValidateRange(m, new Range(3, 2, 3, 7), new Range(3, 1, 3, 7));
|
||||
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
test('issue #71480: validateRange handle floats', () => {
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
|
||||
|
||||
@@ -112,19 +112,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -170,19 +166,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -228,19 +220,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -286,19 +274,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -344,19 +328,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -402,19 +382,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 50,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 50,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -460,19 +436,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 50,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 50,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -518,19 +490,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 60,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 60,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 70,
|
||||
contentWidth: 830,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -576,19 +544,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 30,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 30,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -634,19 +598,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 900,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 30,
|
||||
lineNumbersHeight: 900,
|
||||
|
||||
decorationsLeft: 30,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 900,
|
||||
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
contentHeight: 900,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
@@ -692,19 +652,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
@@ -750,19 +706,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
@@ -808,19 +760,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 0,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 0,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
@@ -866,19 +814,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 55,
|
||||
glyphMarginWidth: 0,
|
||||
glyphMarginHeight: 800,
|
||||
|
||||
lineNumbersLeft: 55,
|
||||
lineNumbersWidth: 0,
|
||||
lineNumbersHeight: 800,
|
||||
|
||||
decorationsLeft: 55,
|
||||
decorationsWidth: 10,
|
||||
decorationsHeight: 800,
|
||||
|
||||
contentLeft: 65,
|
||||
contentWidth: 935,
|
||||
contentHeight: 800,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 0,
|
||||
@@ -924,19 +868,15 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
|
||||
glyphMarginLeft: 0,
|
||||
glyphMarginWidth: 30,
|
||||
glyphMarginHeight: 422,
|
||||
|
||||
lineNumbersLeft: 30,
|
||||
lineNumbersWidth: 36,
|
||||
lineNumbersHeight: 422,
|
||||
|
||||
decorationsLeft: 66,
|
||||
decorationsWidth: 26,
|
||||
decorationsHeight: 422,
|
||||
|
||||
contentLeft: 92,
|
||||
contentWidth: 1018,
|
||||
contentHeight: 422,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 1096,
|
||||
|
||||
@@ -38,6 +38,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
[],
|
||||
tabSize,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -88,6 +89,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
[],
|
||||
tabSize,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
@@ -140,6 +142,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
6,
|
||||
'boundary',
|
||||
@@ -232,6 +235,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'boundary',
|
||||
@@ -295,6 +299,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -358,6 +363,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -398,6 +404,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -429,6 +436,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -530,6 +538,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -569,6 +578,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -599,6 +609,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -646,6 +657,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
lineParts,
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -728,6 +740,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens(tokens),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
renderWhitespace,
|
||||
@@ -754,6 +767,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(21, 3)]),
|
||||
[new LineDecoration(1, 22, 'link', InlineDecorationType.Regular)],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -794,6 +808,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
new LineDecoration(13, 51, 'detected-link', InlineDecorationType.Regular)
|
||||
],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -1209,6 +1224,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
new LineDecoration(2, 8, 'c', InlineDecorationType.Regular),
|
||||
],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
@@ -1250,6 +1266,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(4, 3)]),
|
||||
[new LineDecoration(1, 2, 'before', InlineDecorationType.Before)],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
@@ -1283,6 +1300,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(4, 3)]),
|
||||
[new LineDecoration(2, 3, 'before', InlineDecorationType.Before)],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
@@ -1317,6 +1335,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(0, 3)]),
|
||||
[new LineDecoration(1, 2, 'before', InlineDecorationType.Before)],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'all',
|
||||
@@ -1347,6 +1366,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(7, 3)]),
|
||||
[new LineDecoration(7, 8, 'inline-folded', InlineDecorationType.After)],
|
||||
2,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1365,7 +1385,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
assert.deepEqual(actual.html, expected);
|
||||
});
|
||||
|
||||
test('issue #37401: Allow both before and after decorations on empty line', () => {
|
||||
test('issue #37401 #40127: Allow both before and after decorations on empty line', () => {
|
||||
|
||||
let actual = renderViewLine(new RenderLineInput(
|
||||
true,
|
||||
@@ -1381,6 +1401,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
new LineDecoration(0, 1, 'after', InlineDecorationType.After),
|
||||
],
|
||||
2,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1391,7 +1412,8 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
|
||||
let expected = [
|
||||
'<span>',
|
||||
'<span class="before after"></span>',
|
||||
'<span class="before"></span>',
|
||||
'<span class="after"></span>',
|
||||
'</span>'
|
||||
].join('');
|
||||
|
||||
@@ -1414,6 +1436,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
new LineDecoration(3, 3, 'ced-TextEditorDecorationType2-5e9b9b3f-4 ced-TextEditorDecorationType2-4', InlineDecorationType.After),
|
||||
],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1445,6 +1468,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(15, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1475,6 +1499,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(15, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'all',
|
||||
@@ -1511,6 +1536,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(53, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1541,6 +1567,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(100, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1573,6 +1600,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(105, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1604,6 +1632,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(59, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'boundary',
|
||||
@@ -1633,6 +1662,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(194, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1666,6 +1696,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens([createPart(194, 3)]),
|
||||
[],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10000,
|
||||
'none',
|
||||
@@ -1695,6 +1726,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
createViewLineTokens(parts),
|
||||
[],
|
||||
tabSize,
|
||||
0,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { WrappingIndent } from 'vs/editor/common/config/editorOptions';
|
||||
import { CharacterHardWrappingLineMapperFactory } from 'vs/editor/common/viewModel/characterHardWrappingLineMapper';
|
||||
import { ILineMapperFactory, ILineMapping } from 'vs/editor/common/viewModel/splitLinesCollection';
|
||||
|
||||
function assertLineMapping(factory: ILineMapperFactory, tabSize: number, breakAfter: number, annotatedText: string, wrappingIndent = WrappingIndent.None): ILineMapping | null {
|
||||
// Create version of `annotatedText` with line break markers removed
|
||||
let rawText = '';
|
||||
let currentLineIndex = 0;
|
||||
let lineIndices: number[] = [];
|
||||
for (let i = 0, len = annotatedText.length; i < len; i++) {
|
||||
if (annotatedText.charAt(i) === '|') {
|
||||
currentLineIndex++;
|
||||
} else {
|
||||
rawText += annotatedText.charAt(i);
|
||||
lineIndices[rawText.length - 1] = currentLineIndex;
|
||||
}
|
||||
}
|
||||
|
||||
const mapper = factory.createLineMapping(rawText, tabSize, breakAfter, 2, wrappingIndent);
|
||||
|
||||
// Insert line break markers again, according to algorithm
|
||||
let actualAnnotatedText = '';
|
||||
if (mapper) {
|
||||
let previousLineIndex = 0;
|
||||
for (let i = 0, len = rawText.length; i < len; i++) {
|
||||
let r = mapper.getOutputPositionOfInputOffset(i);
|
||||
if (previousLineIndex !== r.outputLineIndex) {
|
||||
previousLineIndex = r.outputLineIndex;
|
||||
actualAnnotatedText += '|';
|
||||
}
|
||||
actualAnnotatedText += rawText.charAt(i);
|
||||
}
|
||||
} else {
|
||||
// No wrapping
|
||||
actualAnnotatedText = rawText;
|
||||
}
|
||||
|
||||
assert.equal(actualAnnotatedText, annotatedText);
|
||||
|
||||
return mapper;
|
||||
}
|
||||
|
||||
suite('Editor ViewModel - CharacterHardWrappingLineMapper', () => {
|
||||
test('CharacterHardWrappingLineMapper', () => {
|
||||
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('(', ')', '.');
|
||||
|
||||
// Empty string
|
||||
assertLineMapping(factory, 4, 5, '');
|
||||
|
||||
// No wrapping if not necessary
|
||||
assertLineMapping(factory, 4, 5, 'aaa');
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa');
|
||||
assertLineMapping(factory, 4, -1, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
|
||||
|
||||
// Acts like hard wrapping if no char found
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|a');
|
||||
|
||||
// Honors obtrusive wrapping character
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|.');
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|a.|aaa.|aa');
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|a..|aaa.|aa');
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|a...|aaa.|aa');
|
||||
assertLineMapping(factory, 4, 5, 'aaaaa|a....|aaa.|aa');
|
||||
|
||||
// Honors tabs when computing wrapping position
|
||||
assertLineMapping(factory, 4, 5, '\t');
|
||||
assertLineMapping(factory, 4, 5, '\ta|aa');
|
||||
assertLineMapping(factory, 4, 5, '\ta|\ta|a');
|
||||
assertLineMapping(factory, 4, 5, 'aa\ta');
|
||||
assertLineMapping(factory, 4, 5, 'aa\ta|a');
|
||||
|
||||
// Honors wrapping before characters (& gives it priority)
|
||||
assertLineMapping(factory, 4, 5, 'aaa.|aa');
|
||||
assertLineMapping(factory, 4, 5, 'aaa|(.aa');
|
||||
|
||||
// Honors wrapping after characters (& gives it priority)
|
||||
assertLineMapping(factory, 4, 5, 'aaa))|).aaa');
|
||||
assertLineMapping(factory, 4, 5, 'aaa))|)|.aaaa');
|
||||
assertLineMapping(factory, 4, 5, 'aaa)|()|.aaa');
|
||||
assertLineMapping(factory, 4, 5, 'aaa(|()|.aaa');
|
||||
assertLineMapping(factory, 4, 5, 'aa.(|()|.aaa');
|
||||
assertLineMapping(factory, 4, 5, 'aa.|(.)|.aaa');
|
||||
});
|
||||
|
||||
test('CharacterHardWrappingLineMapper - CJK and Kinsoku Shori', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('(', ')', '.');
|
||||
assertLineMapping(factory, 4, 5, 'aa \u5b89|\u5b89');
|
||||
assertLineMapping(factory, 4, 5, '\u3042 \u5b89|\u5b89');
|
||||
assertLineMapping(factory, 4, 5, '\u3042\u3042|\u5b89\u5b89');
|
||||
assertLineMapping(factory, 4, 5, 'aa |\u5b89)\u5b89|\u5b89');
|
||||
assertLineMapping(factory, 4, 5, 'aa \u3042|\u5b89\u3042)|\u5b89');
|
||||
assertLineMapping(factory, 4, 5, 'aa |(\u5b89aa|\u5b89');
|
||||
});
|
||||
|
||||
test('CharacterHardWrappingLineMapper - WrappingIndent.Same', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('', ' ', '');
|
||||
assertLineMapping(factory, 4, 38, ' *123456789012345678901234567890123456|7890', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('issue #16332: Scroll bar overlaying on top of text', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('', ' ', '');
|
||||
assertLineMapping(factory, 4, 24, 'a/ very/long/line/of/tex|t/that/expands/beyon|d/your/typical/line/|of/code/', WrappingIndent.Indent);
|
||||
});
|
||||
|
||||
test('issue #35162: wrappingIndent not consistently working', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('', ' ', '');
|
||||
let mapper = assertLineMapping(factory, 4, 24, ' t h i s |i s |a l |o n |g l |i n |e', WrappingIndent.Indent);
|
||||
assert.equal(mapper!.getWrappedLinesIndent(), ' \t');
|
||||
});
|
||||
|
||||
test('issue #75494: surrogate pairs', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('', ' ', '');
|
||||
assertLineMapping(factory, 4, 49, '🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇|👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('CharacterHardWrappingLineMapper - WrappingIndent.DeepIndent', () => {
|
||||
let factory = new CharacterHardWrappingLineMapperFactory('', ' ', '');
|
||||
let mapper = assertLineMapping(factory, 4, 26, ' W e A r e T e s t |i n g D e |e p I n d |e n t a t |i o n', WrappingIndent.DeepIndent);
|
||||
assert.equal(mapper!.getWrappedLinesIndent(), ' \t\t');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,256 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { WrappingIndent, EditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
import { ILineBreaksComputerFactory, LineBreakData } from 'vs/editor/common/viewModel/splitLinesCollection';
|
||||
import { FontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
|
||||
function parseAnnotatedText(annotatedText: string): { text: string; indices: number[]; } {
|
||||
let text = '';
|
||||
let currentLineIndex = 0;
|
||||
let indices: number[] = [];
|
||||
for (let i = 0, len = annotatedText.length; i < len; i++) {
|
||||
if (annotatedText.charAt(i) === '|') {
|
||||
currentLineIndex++;
|
||||
} else {
|
||||
text += annotatedText.charAt(i);
|
||||
indices[text.length - 1] = currentLineIndex;
|
||||
}
|
||||
}
|
||||
return { text: text, indices: indices };
|
||||
}
|
||||
|
||||
function toAnnotatedText(text: string, lineBreakData: LineBreakData | null): string {
|
||||
// Insert line break markers again, according to algorithm
|
||||
let actualAnnotatedText = '';
|
||||
if (lineBreakData) {
|
||||
let previousLineIndex = 0;
|
||||
for (let i = 0, len = text.length; i < len; i++) {
|
||||
let r = LineBreakData.getOutputPositionOfInputOffset(lineBreakData.breakOffsets, i);
|
||||
if (previousLineIndex !== r.outputLineIndex) {
|
||||
previousLineIndex = r.outputLineIndex;
|
||||
actualAnnotatedText += '|';
|
||||
}
|
||||
actualAnnotatedText += text.charAt(i);
|
||||
}
|
||||
} else {
|
||||
// No wrapping
|
||||
actualAnnotatedText = text;
|
||||
}
|
||||
return actualAnnotatedText;
|
||||
}
|
||||
|
||||
function getLineBreakData(factory: ILineBreaksComputerFactory, tabSize: number, breakAfter: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent, text: string, previousLineBreakData: LineBreakData | null): LineBreakData | null {
|
||||
const fontInfo = new FontInfo({
|
||||
zoomLevel: 0,
|
||||
fontFamily: 'testFontFamily',
|
||||
fontWeight: 'normal',
|
||||
fontSize: 14,
|
||||
fontFeatureSettings: '',
|
||||
lineHeight: 19,
|
||||
letterSpacing: 0,
|
||||
isMonospace: true,
|
||||
typicalHalfwidthCharacterWidth: 7,
|
||||
typicalFullwidthCharacterWidth: 14,
|
||||
canUseHalfwidthRightwardsArrow: true,
|
||||
spaceWidth: 7,
|
||||
maxDigitWidth: 7
|
||||
}, false);
|
||||
const lineBreaksComputer = factory.createLineBreaksComputer(fontInfo, tabSize, breakAfter, wrappingIndent);
|
||||
const previousLineBreakDataClone = previousLineBreakData ? new LineBreakData(previousLineBreakData.breakOffsets.slice(0), previousLineBreakData.breakOffsetsVisibleColumn.slice(0), previousLineBreakData.wrappedTextIndentLength) : null;
|
||||
lineBreaksComputer.addRequest(text, previousLineBreakDataClone);
|
||||
return lineBreaksComputer.finalize()[0];
|
||||
}
|
||||
|
||||
function assertLineBreaks(factory: ILineBreaksComputerFactory, tabSize: number, breakAfter: number, annotatedText: string, wrappingIndent = WrappingIndent.None): LineBreakData | null {
|
||||
// Create version of `annotatedText` with line break markers removed
|
||||
const text = parseAnnotatedText(annotatedText).text;
|
||||
const lineBreakData = getLineBreakData(factory, tabSize, breakAfter, 2, wrappingIndent, text, null);
|
||||
const actualAnnotatedText = toAnnotatedText(text, lineBreakData);
|
||||
|
||||
assert.equal(actualAnnotatedText, annotatedText);
|
||||
|
||||
return lineBreakData;
|
||||
}
|
||||
|
||||
suite('Editor ViewModel - MonospaceLineBreaksComputer', () => {
|
||||
test('MonospaceLineBreaksComputer', () => {
|
||||
|
||||
let factory = new MonospaceLineBreaksComputerFactory('(', '\t).');
|
||||
|
||||
// Empty string
|
||||
assertLineBreaks(factory, 4, 5, '');
|
||||
|
||||
// No wrapping if not necessary
|
||||
assertLineBreaks(factory, 4, 5, 'aaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa');
|
||||
assertLineBreaks(factory, 4, -1, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
|
||||
|
||||
// Acts like hard wrapping if no char found
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|a');
|
||||
|
||||
// Honors wrapping character
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|.');
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|a.|aaa.|aa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|a..|aaa.|aa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|a...|aaa.|aa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaaaa|a....|aaa.|aa');
|
||||
|
||||
// Honors tabs when computing wrapping position
|
||||
assertLineBreaks(factory, 4, 5, '\t');
|
||||
assertLineBreaks(factory, 4, 5, '\t|aaa');
|
||||
assertLineBreaks(factory, 4, 5, '\t|a\t|aa');
|
||||
assertLineBreaks(factory, 4, 5, 'aa\ta');
|
||||
assertLineBreaks(factory, 4, 5, 'aa\t|aa');
|
||||
|
||||
// Honors wrapping before characters (& gives it priority)
|
||||
assertLineBreaks(factory, 4, 5, 'aaa.|aa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaa(.|aa');
|
||||
|
||||
// Honors wrapping after characters (& gives it priority)
|
||||
assertLineBreaks(factory, 4, 5, 'aaa))|).aaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaa))|).|aaaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaa)|().|aaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aaa(|().|aaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aa.(|().|aaa');
|
||||
assertLineBreaks(factory, 4, 5, 'aa.(.|).aaa');
|
||||
});
|
||||
|
||||
function assertIncrementalLineBreaks(factory: ILineBreaksComputerFactory, text: string, tabSize: number, breakAfter1: number, annotatedText1: string, breakAfter2: number, annotatedText2: string, wrappingIndent = WrappingIndent.None): void {
|
||||
// sanity check the test
|
||||
assert.equal(text, parseAnnotatedText(annotatedText1).text);
|
||||
assert.equal(text, parseAnnotatedText(annotatedText2).text);
|
||||
|
||||
// check that the direct mapping is ok for 1
|
||||
const directLineBreakData1 = getLineBreakData(factory, tabSize, breakAfter1, 2, wrappingIndent, text, null);
|
||||
assert.equal(toAnnotatedText(text, directLineBreakData1), annotatedText1);
|
||||
|
||||
// check that the direct mapping is ok for 2
|
||||
const directLineBreakData2 = getLineBreakData(factory, tabSize, breakAfter2, 2, wrappingIndent, text, null);
|
||||
assert.equal(toAnnotatedText(text, directLineBreakData2), annotatedText2);
|
||||
|
||||
// check that going from 1 to 2 is ok
|
||||
const lineBreakData2from1 = getLineBreakData(factory, tabSize, breakAfter2, 2, wrappingIndent, text, directLineBreakData1);
|
||||
assert.equal(toAnnotatedText(text, lineBreakData2from1), annotatedText2);
|
||||
assert.deepEqual(lineBreakData2from1, directLineBreakData2);
|
||||
|
||||
// check that going from 2 to 1 is ok
|
||||
const lineBreakData1from2 = getLineBreakData(factory, tabSize, breakAfter1, 2, wrappingIndent, text, directLineBreakData2);
|
||||
assert.equal(toAnnotatedText(text, lineBreakData1from2), annotatedText1);
|
||||
assert.deepEqual(lineBreakData1from2, directLineBreakData1);
|
||||
}
|
||||
|
||||
test('MonospaceLineBreaksComputer incremental 1', () => {
|
||||
|
||||
let factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, 'just some text and more', 4,
|
||||
10, 'just some |text and |more',
|
||||
15, 'just some text |and more'
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, 'Cu scripserit suscipiantur eos, in affert pericula contentiones sed, cetero sanctus et pro. Ius vidit magna regione te, sit ei elaboraret liberavisse. Mundi verear eu mea, eam vero scriptorem in, vix in menandri assueverit. Natum definiebas cu vim. Vim doming vocibus efficiantur id. In indoctum deseruisse voluptatum vim, ad debitis verterem sed.', 4,
|
||||
47, 'Cu scripserit suscipiantur eos, in affert |pericula contentiones sed, cetero sanctus et |pro. Ius vidit magna regione te, sit ei |elaboraret liberavisse. Mundi verear eu mea, |eam vero scriptorem in, vix in menandri |assueverit. Natum definiebas cu vim. Vim |doming vocibus efficiantur id. In indoctum |deseruisse voluptatum vim, ad debitis verterem |sed.',
|
||||
142, 'Cu scripserit suscipiantur eos, in affert pericula contentiones sed, cetero sanctus et pro. Ius vidit magna regione te, sit ei elaboraret |liberavisse. Mundi verear eu mea, eam vero scriptorem in, vix in menandri assueverit. Natum definiebas cu vim. Vim doming vocibus efficiantur |id. In indoctum deseruisse voluptatum vim, ad debitis verterem sed.',
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, 'An his legere persecuti, oblique delicata efficiantur ex vix, vel at graecis officiis maluisset. Et per impedit voluptua, usu discere maiorum at. Ut assum ornatus temporibus vis, an sea melius pericula. Ea dicunt oblique phaedrum nam, eu duo movet nobis. His melius facilis eu, vim malorum temporibus ne. Nec no sale regione, meliore civibus placerat id eam. Mea alii fabulas definitionem te, agam volutpat ad vis, et per bonorum nonumes repudiandae.', 4,
|
||||
57, 'An his legere persecuti, oblique delicata efficiantur ex |vix, vel at graecis officiis maluisset. Et per impedit |voluptua, usu discere maiorum at. Ut assum ornatus |temporibus vis, an sea melius pericula. Ea dicunt |oblique phaedrum nam, eu duo movet nobis. His melius |facilis eu, vim malorum temporibus ne. Nec no sale |regione, meliore civibus placerat id eam. Mea alii |fabulas definitionem te, agam volutpat ad vis, et per |bonorum nonumes repudiandae.',
|
||||
58, 'An his legere persecuti, oblique delicata efficiantur ex |vix, vel at graecis officiis maluisset. Et per impedit |voluptua, usu discere maiorum at. Ut assum ornatus |temporibus vis, an sea melius pericula. Ea dicunt oblique |phaedrum nam, eu duo movet nobis. His melius facilis eu, |vim malorum temporibus ne. Nec no sale regione, meliore |civibus placerat id eam. Mea alii fabulas definitionem |te, agam volutpat ad vis, et per bonorum nonumes |repudiandae.'
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, '\t\t"owner": "vscode",', 4,
|
||||
14, '\t\t"owner|": |"vscod|e",',
|
||||
16, '\t\t"owner":| |"vscode"|,',
|
||||
WrappingIndent.Same
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, '🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇&👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬', 4,
|
||||
51, '🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇&|👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬',
|
||||
50, '🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇|&|👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬',
|
||||
WrappingIndent.Same
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, '🐇👬&🌞🌖', 4,
|
||||
5, '🐇👬&|🌞🌖',
|
||||
4, '🐇👬|&|🌞🌖',
|
||||
WrappingIndent.Same
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, '\t\tfunc(\'🌞🏇🍼🌞🏇🍼🐇&👬🌖🌞👬🌖🌞🏇🍼🐇👬\', WrappingIndent.Same);', 4,
|
||||
26, '\t\tfunc|(\'🌞🏇🍼🌞🏇🍼🐇&|👬🌖🌞👬🌖🌞🏇🍼🐇|👬\', |WrappingIndent.|Same);',
|
||||
27, '\t\tfunc|(\'🌞🏇🍼🌞🏇🍼🐇&|👬🌖🌞👬🌖🌞🏇🍼🐇|👬\', |WrappingIndent.|Same);',
|
||||
WrappingIndent.Same
|
||||
);
|
||||
|
||||
assertIncrementalLineBreaks(
|
||||
factory, 'factory, "xtxtfunc(x"🌞🏇🍼🌞🏇🍼🐇&👬🌖🌞👬🌖🌞🏇🍼🐇👬x"', 4,
|
||||
16, 'factory, |"xtxtfunc|(x"🌞🏇🍼🌞🏇🍼|🐇&|👬🌖🌞👬🌖🌞🏇🍼|🐇👬x"',
|
||||
17, 'factory, |"xtxtfunc|(x"🌞🏇🍼🌞🏇🍼🐇|&👬🌖🌞👬🌖🌞🏇🍼|🐇👬x"',
|
||||
WrappingIndent.Same
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
test('MonospaceLineBreaksComputer - CJK and Kinsoku Shori', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('(', '\t)');
|
||||
assertLineBreaks(factory, 4, 5, 'aa \u5b89|\u5b89');
|
||||
assertLineBreaks(factory, 4, 5, '\u3042 \u5b89|\u5b89');
|
||||
assertLineBreaks(factory, 4, 5, '\u3042\u3042|\u5b89\u5b89');
|
||||
assertLineBreaks(factory, 4, 5, 'aa |\u5b89)\u5b89|\u5b89');
|
||||
assertLineBreaks(factory, 4, 5, 'aa \u3042|\u5b89\u3042)|\u5b89');
|
||||
assertLineBreaks(factory, 4, 5, 'aa |(\u5b89aa|\u5b89');
|
||||
});
|
||||
|
||||
test('MonospaceLineBreaksComputer - WrappingIndent.Same', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('', '\t ');
|
||||
assertLineBreaks(factory, 4, 38, ' *123456789012345678901234567890123456|7890', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('issue #16332: Scroll bar overlaying on top of text', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('', '\t ');
|
||||
assertLineBreaks(factory, 4, 24, 'a/ very/long/line/of/tex|t/that/expands/beyon|d/your/typical/line/|of/code/', WrappingIndent.Indent);
|
||||
});
|
||||
|
||||
test('issue #35162: wrappingIndent not consistently working', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('', '\t ');
|
||||
let mapper = assertLineBreaks(factory, 4, 24, ' t h i s |i s |a l |o n |g l |i n |e', WrappingIndent.Indent);
|
||||
assert.equal(mapper!.wrappedTextIndentLength, ' '.length);
|
||||
});
|
||||
|
||||
test('issue #75494: surrogate pairs', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('\t', ' ');
|
||||
assertLineBreaks(factory, 4, 49, '🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼|🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼🐇👬🌖🌞🏇🍼|🐇👬', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('issue #75494: surrogate pairs overrun 1', () => {
|
||||
const factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue);
|
||||
assertLineBreaks(factory, 4, 4, '🐇👬|&|🌞🌖', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('issue #75494: surrogate pairs overrun 2', () => {
|
||||
const factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue);
|
||||
assertLineBreaks(factory, 4, 17, 'factory, |"xtxtfunc|(x"🌞🏇🍼🌞🏇🍼🐇|&👬🌖🌞👬🌖🌞🏇🍼|🐇👬x"', WrappingIndent.Same);
|
||||
});
|
||||
|
||||
test('MonospaceLineBreaksComputer - WrappingIndent.DeepIndent', () => {
|
||||
let factory = new MonospaceLineBreaksComputerFactory('', '\t ');
|
||||
let mapper = assertLineBreaks(factory, 4, 26, ' W e A r e T e s t |i n g D e |e p I n d |e n t a t |i o n', WrappingIndent.DeepIndent);
|
||||
assert.equal(mapper!.wrappedTextIndentLength, ' '.length);
|
||||
});
|
||||
|
||||
test('issue #33366: Word wrap algorithm behaves differently around punctuation', () => {
|
||||
const factory = new MonospaceLineBreaksComputerFactory(EditorOptions.wordWrapBreakBeforeCharacters.defaultValue, EditorOptions.wordWrapBreakAfterCharacters.defaultValue);
|
||||
assertLineBreaks(factory, 4, 23, 'this is a line of |text, text that sits |on a line', WrappingIndent.Same);
|
||||
});
|
||||
});
|
||||
@@ -4,9 +4,18 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { toUint32Array } from 'vs/base/common/uint';
|
||||
import { toUint32 } from 'vs/base/common/uint';
|
||||
import { PrefixSumComputer, PrefixSumIndexOfResult } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
|
||||
function toUint32Array(arr: number[]): Uint32Array {
|
||||
const len = arr.length;
|
||||
const r = new Uint32Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
r[i] = toUint32(arr[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
suite('Editor ViewModel - PrefixSumComputer', () => {
|
||||
|
||||
test('PrefixSumComputer', () => {
|
||||
|
||||
@@ -9,23 +9,20 @@ import { IViewLineTokens } from 'vs/editor/common/core/lineTokens';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { TokenizationResult2 } from 'vs/editor/common/core/token';
|
||||
import { toUint32Array } from 'vs/base/common/uint';
|
||||
import { EndOfLinePreference } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { NULL_STATE } from 'vs/editor/common/modes/nullMode';
|
||||
import { CharacterHardWrappingLineMapperFactory, CharacterHardWrappingLineMapping } from 'vs/editor/common/viewModel/characterHardWrappingLineMapper';
|
||||
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { ILineMapping, ISimpleModel, SplitLine, SplitLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
import { LineBreakData, ISimpleModel, SplitLine, SplitLinesCollection } from 'vs/editor/common/viewModel/splitLinesCollection';
|
||||
import { ViewLineData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
|
||||
suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
test('SplitLine', () => {
|
||||
let model1 = createModel('My First LineMy Second LineAnd another one');
|
||||
let line1 = createSplitLine([13, 14, 15], '');
|
||||
let line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 0);
|
||||
|
||||
assert.equal(line1.getViewLineCount(), 3);
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 0), 'My First Line');
|
||||
@@ -54,38 +51,38 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
}
|
||||
|
||||
model1 = createModel('My First LineMy Second LineAnd another one');
|
||||
line1 = createSplitLine([13, 14, 15], '\t');
|
||||
line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 4);
|
||||
|
||||
assert.equal(line1.getViewLineCount(), 3);
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 0), 'My First Line');
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 1), '\tMy Second Line');
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 2), '\tAnd another one');
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 1), ' My Second Line');
|
||||
assert.equal(line1.getViewLineContent(model1, 1, 2), ' And another one');
|
||||
assert.equal(line1.getViewLineMaxColumn(model1, 1, 0), 14);
|
||||
assert.equal(line1.getViewLineMaxColumn(model1, 1, 1), 16);
|
||||
assert.equal(line1.getViewLineMaxColumn(model1, 1, 2), 17);
|
||||
for (let col = 1; col <= 14; col++) {
|
||||
assert.equal(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')');
|
||||
}
|
||||
for (let col = 1; col <= 1; col++) {
|
||||
assert.equal(line1.getModelColumnOfViewPosition(1, 1), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')');
|
||||
}
|
||||
for (let col = 2; col <= 16; col++) {
|
||||
assert.equal(line1.getModelColumnOfViewPosition(1, col), 13 + col - 1, 'getInputColumnOfOutputPosition(1, ' + col + ')');
|
||||
}
|
||||
for (let col = 1; col <= 1; col++) {
|
||||
assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')');
|
||||
}
|
||||
for (let col = 2; col <= 17; col++) {
|
||||
assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col - 1, 'getInputColumnOfOutputPosition(2, ' + col + ')');
|
||||
assert.equal(line1.getViewLineMaxColumn(model1, 1, 1), 19);
|
||||
assert.equal(line1.getViewLineMaxColumn(model1, 1, 2), 20);
|
||||
|
||||
let actualViewColumnMapping: number[][] = [];
|
||||
for (let lineIndex = 0; lineIndex < line1.getViewLineCount(); lineIndex++) {
|
||||
let actualLineViewColumnMapping: number[] = [];
|
||||
for (let col = 1; col <= line1.getViewLineMaxColumn(model1, 1, lineIndex); col++) {
|
||||
actualLineViewColumnMapping.push(line1.getModelColumnOfViewPosition(lineIndex, col));
|
||||
}
|
||||
actualViewColumnMapping.push(actualLineViewColumnMapping);
|
||||
}
|
||||
assert.deepEqual(actualViewColumnMapping, [
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
|
||||
[14, 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28],
|
||||
[28, 28, 28, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43],
|
||||
]);
|
||||
|
||||
for (let col = 1; col <= 13; col++) {
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')');
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), '6.getOutputPositionOfInputPosition(' + col + ')');
|
||||
}
|
||||
for (let col = 1 + 13; col <= 14 + 13; col++) {
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 1 + col - 13), 'getOutputPositionOfInputPosition(' + col + ')');
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 4 + col - 13), '7.getOutputPositionOfInputPosition(' + col + ')');
|
||||
}
|
||||
for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 1 + col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')');
|
||||
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 4 + col - 13 - 14), '8.getOutputPositionOfInputPosition(' + col + ')');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -95,14 +92,9 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
const fontInfo = config.options.get(EditorOption.fontInfo);
|
||||
const wordWrapBreakAfterCharacters = config.options.get(EditorOption.wordWrapBreakAfterCharacters);
|
||||
const wordWrapBreakBeforeCharacters = config.options.get(EditorOption.wordWrapBreakBeforeCharacters);
|
||||
const wordWrapBreakObtrusiveCharacters = config.options.get(EditorOption.wordWrapBreakObtrusiveCharacters);
|
||||
const wrappingIndent = config.options.get(EditorOption.wrappingIndent);
|
||||
|
||||
const hardWrappingLineMapperFactory = new CharacterHardWrappingLineMapperFactory(
|
||||
wordWrapBreakBeforeCharacters,
|
||||
wordWrapBreakAfterCharacters,
|
||||
wordWrapBreakObtrusiveCharacters
|
||||
);
|
||||
const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);
|
||||
|
||||
const model = TextModel.createFromString([
|
||||
'int main() {',
|
||||
@@ -115,10 +107,12 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
|
||||
const linesCollection = new SplitLinesCollection(
|
||||
model,
|
||||
hardWrappingLineMapperFactory,
|
||||
lineBreaksComputerFactory,
|
||||
lineBreaksComputerFactory,
|
||||
fontInfo,
|
||||
model.getOptions().tabSize,
|
||||
'monospace',
|
||||
wrappingInfo.wrappingColumn,
|
||||
fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth,
|
||||
wrappingIndent
|
||||
);
|
||||
|
||||
@@ -616,12 +610,12 @@ suite('SplitLinesCollection', () => {
|
||||
]
|
||||
},
|
||||
{
|
||||
content: ' world");',
|
||||
minColumn: 4,
|
||||
maxColumn: 12,
|
||||
content: ' world");',
|
||||
minColumn: 13,
|
||||
maxColumn: 21,
|
||||
tokens: [
|
||||
{ endIndex: 9, value: 15 },
|
||||
{ endIndex: 11, value: 16 },
|
||||
{ endIndex: 18, value: 15 },
|
||||
{ endIndex: 20, value: 16 },
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -658,28 +652,28 @@ suite('SplitLinesCollection', () => {
|
||||
]
|
||||
},
|
||||
{
|
||||
content: ' world, this is a ',
|
||||
minColumn: 4,
|
||||
maxColumn: 21,
|
||||
content: ' world, this is a ',
|
||||
minColumn: 13,
|
||||
maxColumn: 30,
|
||||
tokens: [
|
||||
{ endIndex: 20, value: 28 },
|
||||
{ endIndex: 29, value: 28 },
|
||||
]
|
||||
},
|
||||
{
|
||||
content: ' somewhat longer ',
|
||||
minColumn: 4,
|
||||
content: ' somewhat longer ',
|
||||
minColumn: 13,
|
||||
maxColumn: 29,
|
||||
tokens: [
|
||||
{ endIndex: 28, value: 28 },
|
||||
]
|
||||
},
|
||||
{
|
||||
content: ' line");',
|
||||
minColumn: 13,
|
||||
maxColumn: 20,
|
||||
tokens: [
|
||||
{ endIndex: 19, value: 28 },
|
||||
]
|
||||
},
|
||||
{
|
||||
content: ' line");',
|
||||
minColumn: 4,
|
||||
maxColumn: 11,
|
||||
tokens: [
|
||||
{ endIndex: 8, value: 28 },
|
||||
{ endIndex: 10, value: 29 },
|
||||
{ endIndex: 17, value: 28 },
|
||||
{ endIndex: 19, value: 29 },
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -749,21 +743,18 @@ suite('SplitLinesCollection', () => {
|
||||
const fontInfo = configuration.options.get(EditorOption.fontInfo);
|
||||
const wordWrapBreakAfterCharacters = configuration.options.get(EditorOption.wordWrapBreakAfterCharacters);
|
||||
const wordWrapBreakBeforeCharacters = configuration.options.get(EditorOption.wordWrapBreakBeforeCharacters);
|
||||
const wordWrapBreakObtrusiveCharacters = configuration.options.get(EditorOption.wordWrapBreakObtrusiveCharacters);
|
||||
const wrappingIndent = configuration.options.get(EditorOption.wrappingIndent);
|
||||
|
||||
const factory = new CharacterHardWrappingLineMapperFactory(
|
||||
wordWrapBreakBeforeCharacters,
|
||||
wordWrapBreakAfterCharacters,
|
||||
wordWrapBreakObtrusiveCharacters
|
||||
);
|
||||
const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);
|
||||
|
||||
const linesCollection = new SplitLinesCollection(
|
||||
model,
|
||||
factory,
|
||||
lineBreaksComputerFactory,
|
||||
lineBreaksComputerFactory,
|
||||
fontInfo,
|
||||
model.getOptions().tabSize,
|
||||
'monospace',
|
||||
wrappingInfo.wrappingColumn,
|
||||
fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth,
|
||||
wrappingIndent
|
||||
);
|
||||
|
||||
@@ -778,15 +769,16 @@ function pos(lineNumber: number, column: number): Position {
|
||||
return new Position(lineNumber, column);
|
||||
}
|
||||
|
||||
function createSplitLine(splitLengths: number[], wrappedLinesPrefix: string, isVisible: boolean = true): SplitLine {
|
||||
return new SplitLine(createLineMapping(splitLengths, wrappedLinesPrefix), isVisible);
|
||||
function createSplitLine(splitLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number, isVisible: boolean = true): SplitLine {
|
||||
return new SplitLine(createLineBreakData(splitLengths, breakingOffsetsVisibleColumn, wrappedTextIndentWidth), isVisible);
|
||||
}
|
||||
|
||||
function createLineMapping(breakingLengths: number[], wrappedLinesPrefix: string): ILineMapping {
|
||||
return new CharacterHardWrappingLineMapping(
|
||||
new PrefixSumComputer(toUint32Array(breakingLengths)),
|
||||
wrappedLinesPrefix
|
||||
);
|
||||
function createLineBreakData(breakingLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number): LineBreakData {
|
||||
let sums: number[] = [];
|
||||
for (let i = 0; i < breakingLengths.length; i++) {
|
||||
sums[i] = (i > 0 ? sums[i - 1] : 0) + breakingLengths[i];
|
||||
}
|
||||
return new LineBreakData(sums, breakingOffsetsVisibleColumn, wrappedTextIndentWidth);
|
||||
}
|
||||
|
||||
function createModel(text: string): ISimpleModel {
|
||||
|
||||
@@ -7,15 +7,15 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
|
||||
export function testViewModel(text: string[], options: IEditorOptions, callback: (viewModel: ViewModel, model: TextModel) => void): void {
|
||||
const EDITOR_ID = 1;
|
||||
|
||||
let configuration = new TestConfiguration(options);
|
||||
|
||||
let model = TextModel.createFromString(text.join('\n'));
|
||||
|
||||
let viewModel = new ViewModel(EDITOR_ID, configuration, model, null!);
|
||||
const configuration = new TestConfiguration(options);
|
||||
const model = TextModel.createFromString(text.join('\n'));
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(configuration.options);
|
||||
const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
|
||||
callback(viewModel, model);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
const x01 = "string";
|
||||
/// ^^^^^^^^ string
|
||||
|
||||
|
||||
Reference in New Issue
Block a user