Initial VS Code 1.19 source merge (#571)

* Initial 1.19 xcopy

* Fix yarn build

* Fix numerous build breaks

* Next batch of build break fixes

* More build break fixes

* Runtime breaks

* Additional post merge fixes

* Fix windows setup file

* Fix test failures.

* Update license header blocks to refer to source eula
This commit is contained in:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -7,17 +7,30 @@
import * as assert from 'assert';
import { ShiftCommand } from 'vs/editor/common/commands/shiftCommand';
import { Selection } from 'vs/editor/common/core/selection';
import { Range } from 'vs/editor/common/core/range';
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
import { IndentAction } from 'vs/editor/common/modes/languageConfiguration';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { createSingleEditOp, getEditOperation, testCommand } from 'vs/editor/test/common/commands/commandTestUtils';
import { getEditOperation, testCommand } from 'vs/editor/test/browser/testCommand';
import { withEditorModel } from 'vs/editor/test/common/editorTestUtils';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { LanguageIdentifier } from 'vs/editor/common/modes';
/**
* Create single edit operation
*/
export function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
return {
identifier: null,
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text,
forceMoveMarkers: false
};
}
class DocBlockCommentMode extends MockMode {
private static _id = new LanguageIdentifier('commentMode', 3);
private static readonly _id = new LanguageIdentifier('commentMode', 3);
constructor() {
super(DocBlockCommentMode._id);

View File

@@ -10,14 +10,14 @@ 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 { IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { Model } from 'vs/editor/common/model/model';
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { Cursor } from 'vs/editor/common/controller/cursor';
function testCommand(lines: string[], selections: Selection[], edits: IIdentifiedSingleEditOperation[], expectedLines: string[], expectedSelections: Selection[]): void {
withMockCodeEditor(lines, {}, (editor, cursor) => {
withTestCodeEditor(lines, {}, (editor, cursor) => {
const model = editor.getModel();
cursor.setSelections('tests', selections);
@@ -883,4 +883,4 @@ suite('SideEditing', () => {
});
});
});
});
});

View File

@@ -8,10 +8,35 @@ import * as assert from 'assert';
import { TrimTrailingWhitespaceCommand, trimTrailingWhitespace } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
import { Selection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
import { createInsertDeleteSingleEditOp, createSingleEditOp, getEditOperation } from 'vs/editor/test/common/commands/commandTestUtils';
import { getEditOperation } from 'vs/editor/test/browser/testCommand';
import { withEditorModel } from 'vs/editor/test/common/editorTestUtils';
/**
* Create single edit operation
*/
function createInsertDeleteSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
return {
identifier: null,
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text,
forceMoveMarkers: true
};
}
/**
* Create single edit operation
*/
export function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
return {
identifier: null,
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text,
forceMoveMarkers: false
};
}
function assertTrimTrailingWhitespaceCommand(text: string[], expected: IIdentifiedSingleEditOperation[]): void {
return withEditorModel(text, (model) => {
var op = new TrimTrailingWhitespaceCommand(new Selection(1, 1, 1, 1), []);
@@ -79,4 +104,3 @@ suite('Editor Commands - Trim Trailing Whitespace Command', () => {
});
});

View File

@@ -22,8 +22,8 @@ import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { CoreNavigationCommands, CoreEditingCommands } from 'vs/editor/common/controller/coreCommands';
import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { CoreNavigationCommands, CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { TextModel } from 'vs/editor/common/model/textModel';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
let H = Handler;
@@ -696,7 +696,7 @@ suite('Editor Controller - Cursor', () => {
});
test('column select 1', () => {
withMockCodeEditor([
withTestCodeEditor([
'\tprivate compute(a:number): boolean {',
'\t\tif (a + 3 === 0 || a + 5 === 0) {',
'\t\t\treturn false;',
@@ -1092,7 +1092,7 @@ suite('Editor Controller - Cursor', () => {
class SurroundingMode extends MockMode {
private static _id = new LanguageIdentifier('surroundingMode', 3);
private static readonly _id = new LanguageIdentifier('surroundingMode', 3);
constructor() {
super(SurroundingMode._id);
@@ -1103,7 +1103,7 @@ class SurroundingMode extends MockMode {
}
class OnEnterMode extends MockMode {
private static _id = new LanguageIdentifier('onEnterMode', 3);
private static readonly _id = new LanguageIdentifier('onEnterMode', 3);
constructor(indentAction: IndentAction, outdentCurrentLine?: boolean) {
super(OnEnterMode._id);
@@ -1120,7 +1120,7 @@ class OnEnterMode extends MockMode {
}
class IndentRulesMode extends MockMode {
private static _id = new LanguageIdentifier('indentRulesMode', 4);
private static readonly _id = new LanguageIdentifier('indentRulesMode', 4);
constructor(indentationRules: IndentationRule) {
super(IndentRulesMode._id);
this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {
@@ -1146,7 +1146,7 @@ suite('Editor Controller - Regression tests', () => {
},
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(1, 1, 1, 13)]);
// Check that indenting maintains the selection start at column 1
@@ -1171,7 +1171,7 @@ suite('Editor Controller - Regression tests', () => {
},
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1');
@@ -1237,7 +1237,7 @@ suite('Editor Controller - Regression tests', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 1, 6, false);
assertCursor(cursor, new Selection(1, 6, 1, 6));
@@ -1264,7 +1264,7 @@ suite('Editor Controller - Regression tests', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 1, 7, false);
assertCursor(cursor, new Selection(1, 7, 1, 7));
@@ -1296,7 +1296,7 @@ suite('Editor Controller - Regression tests', () => {
},
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 7, 1, false);
assertCursor(cursor, new Selection(7, 1, 7, 1));
@@ -1311,7 +1311,7 @@ suite('Editor Controller - Regression tests', () => {
test('bug #16740: [editor] Cut line doesn\'t quite cut the last line', () => {
// Part 1 => there is text on the last line
withMockCodeEditor([
withTestCodeEditor([
'asdasd',
'qwerty'
], {}, (editor, cursor) => {
@@ -1327,7 +1327,7 @@ suite('Editor Controller - Regression tests', () => {
});
// Part 2 => there is no text on the last line
withMockCodeEditor([
withTestCodeEditor([
'asdasd',
''
], {}, (editor, cursor) => {
@@ -1385,7 +1385,7 @@ suite('Editor Controller - Regression tests', () => {
},
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 3, 2, false);
moveTo(cursor, 1, 14, true);
assertCursor(cursor, new Selection(3, 2, 1, 14));
@@ -1434,7 +1434,7 @@ suite('Editor Controller - Regression tests', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 1, 1, false);
moveTo(cursor, 3, 4, true);
@@ -1516,7 +1516,7 @@ suite('Editor Controller - Regression tests', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 3, 2, false);
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
assert.equal(model.getLineContent(3), '\t \tx: 3');
@@ -1540,7 +1540,7 @@ suite('Editor Controller - Regression tests', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 1, 15, false);
moveTo(cursor, 1, 22, true);
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
@@ -1636,7 +1636,7 @@ suite('Editor Controller - Regression tests', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
CoreNavigationCommands.WordSelect.runCoreEditorCommand(cursor, { position: new Position(1, 8) });
assert.deepEqual(cursor.getSelection(), new Selection(1, 6, 1, 10));
@@ -1744,7 +1744,7 @@ suite('Editor Controller - Regression tests', () => {
test('issue #36740: wordwrap creates an extra step / character at the wrapping point', () => {
// a single model line => 4 view lines
withMockCodeEditor([
withTestCodeEditor([
[
'Lorem ipsum ',
'dolor sit amet ',
@@ -1824,7 +1824,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
// Tab on column 1
CoreNavigationCommands.MoveTo.runCoreEditorCommand(cursor, { position: new Position(2, 1) });
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
@@ -2053,7 +2053,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 3, 1);
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
@@ -2097,7 +2097,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
// Move cursor to the end, verify that we do not trim whitespaces if line has values
moveTo(cursor, 1, model.getLineContent(1).length + 1);
@@ -2163,7 +2163,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model, useTabStops: false }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, cursor) => {
// DeleteLeft removes just one whitespace
moveTo(cursor, 2, 9);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
@@ -2189,7 +2189,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model, useTabStops: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, useTabStops: true }, (editor, cursor) => {
// DeleteLeft does not remove tab size, because some text exists before
moveTo(cursor, 2, model.getLineContent(2).length + 1);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
@@ -2260,7 +2260,7 @@ suite('Editor Controller - Cursor Configuration', () => {
}
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursorCommand(cursor, H.Type, { text: '\n' }, 'keyboard');
assert.equal(model.getValue(EndOfLinePreference.LF), '\n', 'assert1');
@@ -2428,7 +2428,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
moveTo(cursor, 2, 11, false);
assertCursor(cursor, new Selection(2, 11, 2, 11));
@@ -2907,7 +2907,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 4, 1, false);
assertCursor(cursor, new Selection(4, 1, 4, 1));
@@ -2939,7 +2939,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 4, 2, false);
assertCursor(cursor, new Selection(4, 2, 4, 2));
@@ -2971,7 +2971,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 4, 1, false);
assertCursor(cursor, new Selection(4, 1, 4, 1));
@@ -3002,7 +3002,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 4, 3, false);
assertCursor(cursor, new Selection(4, 3, 4, 3));
@@ -3033,7 +3033,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 4, 4, false);
assertCursor(cursor, new Selection(4, 4, 4, 4));
@@ -3064,7 +3064,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
moveTo(cursor, 3, 1);
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
@@ -3100,7 +3100,7 @@ suite('Editor Controller - Indentation Rules', () => {
rubyMode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: true }, (editor, cursor) => {
moveTo(cursor, 4, 7, false);
assertCursor(cursor, new Selection(4, 7, 4, 7));
@@ -3177,7 +3177,7 @@ suite('Editor Controller - Indentation Rules', () => {
test('issue #36090: JS: editor.autoIndent seems to be broken', () => {
class JSMode extends MockMode {
private static _id = new LanguageIdentifier('indentRulesMode', 4);
private static readonly _id = new LanguageIdentifier('indentRulesMode', 4);
constructor() {
super(JSMode._id);
this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {
@@ -3237,7 +3237,7 @@ suite('Editor Controller - Indentation Rules', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => {
withTestCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => {
moveTo(cursor, 7, 6, false);
assertCursor(cursor, new Selection(7, 6, 7, 6));
@@ -3261,6 +3261,67 @@ suite('Editor Controller - Indentation Rules', () => {
model.dispose();
mode.dispose();
});
test('issue #38261: TAB key results in bizarre indentation in C++ mode ', () => {
class CppMode extends MockMode {
private static readonly _id = new LanguageIdentifier('indentRulesMode', 4);
constructor() {
super(CppMode._id);
this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
indentationRules: {
increaseIndentPattern: new RegExp('^.*\\{[^}\"\\\']*$|^.*\\([^\\)\"\\\']*$|^\\s*(public|private|protected):\\s*$|^\\s*@(public|private|protected)\\s*$|^\\s*\\{\\}$'),
decreaseIndentPattern: new RegExp('^\\s*(\\s*/[*].*[*]/\\s*)*\\}|^\\s*(\\s*/[*].*[*]/\\s*)*\\)|^\\s*(public|private|protected):\\s*$|^\\s*@(public|private|protected)\\s*$'),
}
}));
}
}
let mode = new CppMode();
let model = Model.createFromString(
[
'int main() {',
' return 0;',
'}',
'',
'bool Foo::bar(const string &a,',
' const string &b) {',
' foo();',
'',
')',
].join('\n'),
{ insertSpaces: true, detectIndentation: false, tabSize: 2, trimAutoWhitespace: false, defaultEOL: DefaultEndOfLine.LF },
mode.getLanguageIdentifier()
);
withTestCodeEditor(null, { model: model, autoIndent: false }, (editor, cursor) => {
moveTo(cursor, 8, 1, false);
assertCursor(cursor, new Selection(8, 1, 8, 1));
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
assert.equal(model.getValue(),
[
'int main() {',
' return 0;',
'}',
'',
'bool Foo::bar(const string &a,',
' const string &b) {',
' foo();',
' ',
')',
].join('\n')
);
assert.deepEqual(cursor.getSelection(), new Selection(8, 3, 8, 3));
});
model.dispose();
mode.dispose();
});
});
interface ICursorOpts {
@@ -3287,7 +3348,7 @@ function usingCursor(opts: ICursorOpts, callback: (model: Model, cursor: Cursor)
class ElectricCharMode extends MockMode {
private static _id = new LanguageIdentifier('electricCharMode', 3);
private static readonly _id = new LanguageIdentifier('electricCharMode', 3);
constructor() {
super(ElectricCharMode._id);
@@ -3545,7 +3606,7 @@ suite('autoClosingPairs', () => {
class AutoClosingMode extends MockMode {
private static _id = new LanguageIdentifier('autoClosingMode', 5);
private static readonly _id = new LanguageIdentifier('autoClosingMode', 5);
constructor() {
super(AutoClosingMode._id);
@@ -3841,7 +3902,7 @@ suite('autoClosingPairs', () => {
mode.getLanguageIdentifier()
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [
new Selection(1, 4, 1, 4),
new Selection(1, 10, 1, 10),
@@ -3870,7 +3931,7 @@ suite('autoClosingPairs', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
CoreNavigationCommands.WordSelect.runEditorCommand(null, editor, {
position: new Position(3, 7)
});
@@ -3894,7 +3955,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(1, 3, 1, 3)]);
cursorCommand(cursor, H.Type, { text: 'first' }, 'keyboard');
assert.equal(model.getLineContent(1), 'A first line');
@@ -3923,7 +3984,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(1, 3, 1, 3)]);
cursorCommand(cursor, H.Type, { text: 'first' }, 'keyboard');
assert.equal(model.getLineContent(1), 'A first line');
@@ -3952,7 +4013,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(2, 8, 2, 8)]);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
@@ -3986,7 +4047,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(2, 8, 2, 8)]);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
@@ -4024,7 +4085,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(2, 9, 2, 9)]);
CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null);
@@ -4055,7 +4116,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(2, 9, 2, 9)]);
CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteRight.runEditorCommand(null, editor, null);
@@ -4091,7 +4152,7 @@ suite('Undo stops', () => {
].join('\n')
);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('test', [new Selection(1, 3, 1, 3)]);
cursorCommand(cursor, H.Type, { text: 'first and interesting' }, 'keyboard');
assert.equal(model.getLineContent(1), 'A first and interesting line');

View File

@@ -12,7 +12,7 @@ import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration
import { CursorMove } from 'vs/editor/common/controller/cursorMoveCommands';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { CoreNavigationCommands } from 'vs/editor/common/controller/coreCommands';
import { CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
suite('Cursor move command test', () => {

View File

@@ -17,11 +17,9 @@ import * as browser from 'vs/base/browser/browser';
class SingleLineTestModel implements ISimpleModel {
private _line: string;
private _eol: string;
constructor(line: string) {
this._line = line;
this._eol = '\n';
}
_setText(text: string) {

View File

@@ -5,10 +5,8 @@
'use strict';
import * as assert from 'assert';
import { ISimpleModel, TextAreaState, ITextAreaWrapper, PagedScreenReaderStrategy } from 'vs/editor/browser/controller/textAreaState';
import { Range } from 'vs/editor/common/core/range';
import { TextAreaState, ITextAreaWrapper, PagedScreenReaderStrategy } from 'vs/editor/browser/controller/textAreaState';
import { Position } from 'vs/editor/common/core/position';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { Disposable } from 'vs/base/common/lifecycle';
import { Model } from 'vs/editor/common/model/model';
import { Selection } from 'vs/editor/common/core/selection';
@@ -62,11 +60,21 @@ export class MockTextAreaWrapper extends Disposable implements ITextAreaWrapper
}
}
function equalsTextAreaState(a: TextAreaState, b: TextAreaState): boolean {
return (
a.value === b.value
&& a.selectionStart === b.selectionStart
&& a.selectionEnd === b.selectionEnd
&& Position.equals(a.selectionStartPosition, b.selectionStartPosition)
&& Position.equals(a.selectionEndPosition, b.selectionEndPosition)
);
}
suite('TextAreaState', () => {
function assertTextAreaState(actual: TextAreaState, value: string, selectionStart: number, selectionEnd: number): void {
let desired = new TextAreaState(value, selectionStart, selectionEnd, null, null);
assert.ok(desired.equals(actual), desired.toString() + ' == ' + actual.toString());
assert.ok(equalsTextAreaState(desired, actual), desired.toString() + ' == ' + actual.toString());
}
test('fromTextArea', () => {
@@ -501,7 +509,7 @@ suite('TextAreaState', () => {
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {
const model = Model.createFromString(lines.join('\n'));
const actual = PagedScreenReaderStrategy.fromEditorSelection(TextAreaState.EMPTY, model, selection, true);
assert.ok(actual.equals(expected));
assert.ok(equalsTextAreaState(actual, expected));
model.dispose();
}
@@ -587,57 +595,3 @@ suite('TextAreaState', () => {
});
});
class SimpleModel implements ISimpleModel {
private _lines: string[];
private _eol: string;
constructor(lines: string[], eol: string) {
this._lines = lines;
this._eol = eol;
}
public getLineMaxColumn(lineNumber: number): number {
return this._lines[lineNumber - 1].length + 1;
}
private _getEndOfLine(eol: EndOfLinePreference): string {
switch (eol) {
case EndOfLinePreference.LF:
return '\n';
case EndOfLinePreference.CRLF:
return '\r\n';
case EndOfLinePreference.TextDefined:
return this._eol;
}
throw new Error('Unknown EOL preference');
}
public getValueInRange(range: Range, eol: EndOfLinePreference): string {
if (Range.isEmpty(range)) {
return '';
}
if (range.startLineNumber === range.endLineNumber) {
return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);
}
var lineEnding = this._getEndOfLine(eol),
startLineIndex = range.startLineNumber - 1,
endLineIndex = range.endLineNumber - 1,
resultLines: string[] = [];
resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));
for (var i = startLineIndex + 1; i < endLineIndex; i++) {
resultLines.push(this._lines[i]);
}
resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));
return resultLines.join(lineEnding);
}
public getLineCount(): number {
return this._lines.length;
}
}

View File

@@ -7,10 +7,11 @@
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import { ICommonCodeEditor, IModel } from 'vs/editor/common/editorCommon';
import { EditorState, CodeEditorStateFlag } from 'vs/editor/common/core/editorState';
import { IModel } from 'vs/editor/common/editorCommon';
import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
import { Selection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
interface IStubEditorState {
model?: { uri?: URI, version?: number };
@@ -88,17 +89,16 @@ suite('Editor Core - Editor State', () => {
return result;
}
function createEditor({ model, position, selection, scroll }: IStubEditorState = {}): ICommonCodeEditor {
function createEditor({ model, position, selection, scroll }: IStubEditorState = {}): ICodeEditor {
let mappedModel = model ? { uri: model.uri ? model.uri : URI.parse('http://dummy.org'), getVersionId: () => model.version } : null;
return <any>{
return {
getModel: (): IModel => <any>mappedModel,
getPosition: (): Position => position,
getSelection: (): Selection => selection,
getScrollLeft: (): number => scroll && scroll.left,
getScrollTop: (): number => scroll && scroll.top
};
} as ICodeEditor;
}
});

View File

@@ -14,15 +14,7 @@ import { TestTheme, TestThemeService } from 'vs/platform/theme/test/common/testT
const themeServiceMock = new TestThemeService();
suite('Decoration Render Options', () => {
var options: IDecorationRenderOptions = {
gutterIconPath: URI.parse('https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png'),
gutterIconSize: 'contain',
backgroundColor: 'red',
borderColor: 'yellow'
};
test('register and resolve decoration type', () => {
// var s = new CodeEditorServiceImpl(themeServiceMock);
// s.registerDecorationType('example', options);
// assert.notEqual(s.resolveDecorationOptions('example', false), undefined);
assert.notEqual(true, false);
});
});

View File

@@ -0,0 +1,178 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { CommonCodeEditor } from 'vs/editor/common/commonCodeEditor';
import { CommonEditorConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { Cursor } from 'vs/editor/common/controller/cursor';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { Model } from 'vs/editor/common/model/model';
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { IDisposable } from 'vs/base/common/lifecycle';
import Event, { Emitter } from 'vs/base/common/event';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IPosition } from 'vs/editor/common/core/position';
import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions';
import { TPromise } from 'vs/base/common/winjs.base';
import { onUnexpectedError } from 'vs/base/common/errors';
export class TestCodeEditor extends CommonCodeEditor implements editorBrowser.ICodeEditor {
private readonly _onMouseUp: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseUp: Event<editorBrowser.IEditorMouseEvent> = this._onMouseUp.event;
private readonly _onMouseDown: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseDown: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDown.event;
private readonly _onMouseDrag: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseDrag: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDrag.event;
private readonly _onMouseDrop: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseDrop: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDrop.event;
private readonly _onContextMenu: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onContextMenu: Event<editorBrowser.IEditorMouseEvent> = this._onContextMenu.event;
private readonly _onMouseMove: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseMove: Event<editorBrowser.IEditorMouseEvent> = this._onMouseMove.event;
private readonly _onMouseLeave: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
public readonly onMouseLeave: Event<editorBrowser.IEditorMouseEvent> = this._onMouseLeave.event;
private readonly _onKeyUp: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;
private readonly _onKeyDown: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;
private readonly _onDidScrollChange: Emitter<editorCommon.IScrollEvent> = this._register(new Emitter<editorCommon.IScrollEvent>());
public readonly onDidScrollChange: Event<editorCommon.IScrollEvent> = this._onDidScrollChange.event;
private readonly _onDidChangeViewZones: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeViewZones: Event<void> = this._onDidChangeViewZones.event;
public _isFocused = true;
protected _createConfiguration(options: editorOptions.IEditorOptions): CommonEditorConfiguration {
return new TestConfiguration(options);
}
public layout(dimension?: editorCommon.IDimension): void { }
public focus(): void { }
public isFocused(): boolean { return this._isFocused; }
public hasWidgetFocus(): boolean { return true; }
protected _enableEmptySelectionClipboard(): boolean { return false; }
protected _scheduleAtNextAnimationFrame(callback: () => void): IDisposable { throw new Error('Notimplemented'); }
protected _createView(): void { }
protected _registerDecorationType(key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void { throw new Error('NotImplemented'); }
protected _removeDecorationType(key: string): void { throw new Error('NotImplemented'); }
protected _resolveDecorationOptions(typeKey: string, writable: boolean): editorCommon.IModelDecorationOptions { throw new Error('NotImplemented'); }
// --- test utils
getCursor(): Cursor {
return this.cursor;
}
public registerAndInstantiateContribution<T extends editorCommon.IEditorContribution>(ctor: any): T {
let r = <T>this._instantiationService.createInstance(ctor, this);
this._contributions[r.getId()] = r;
return r;
}
public dispose() {
super.dispose();
if (this.model) {
this.model.dispose();
}
this._contextKeyService.dispose();
}
protected _triggerEditorCommand(source: string, handlerId: string, payload: any): boolean {
const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
if (command) {
payload = payload || {};
payload.source = source;
TPromise.as(command.runEditorCommand(null, this, payload)).done(null, onUnexpectedError);
return true;
}
return false;
}
//#region ICodeEditor
getDomNode(): HTMLElement { throw new Error('Not implemented'); }
addContentWidget(widget: editorBrowser.IContentWidget): void { throw new Error('Not implemented'); }
layoutContentWidget(widget: editorBrowser.IContentWidget): void { throw new Error('Not implemented'); }
removeContentWidget(widget: editorBrowser.IContentWidget): void { throw new Error('Not implemented'); }
addOverlayWidget(widget: editorBrowser.IOverlayWidget): void { throw new Error('Not implemented'); }
layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void { throw new Error('Not implemented'); }
removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void { throw new Error('Not implemented'); }
changeViewZones(callback: (accessor: editorBrowser.IViewZoneChangeAccessor) => void): void { throw new Error('Not implemented'); }
getOffsetForColumn(lineNumber: number, column: number): number { throw new Error('Not implemented'); }
render(): void { throw new Error('Not implemented'); }
getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget { throw new Error('Not implemented'); }
getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; } { throw new Error('Not implemented'); }
applyFontInfo(target: HTMLElement): void { throw new Error('Not implemented'); }
//#endregion ICodeEditor
}
export class MockScopeLocation implements IContextKeyServiceTarget {
parentElement: IContextKeyServiceTarget = null;
setAttribute(attr: string, value: string): void { }
removeAttribute(attr: string): void { }
hasAttribute(attr: string): boolean { return false; }
getAttribute(attr: string): string { return undefined; }
}
export interface TestCodeEditorCreationOptions extends editorOptions.IEditorOptions {
/**
* The initial model associated with this code editor.
*/
model?: editorCommon.IModel;
serviceCollection?: ServiceCollection;
}
export function withTestCodeEditor(text: string[], options: TestCodeEditorCreationOptions, callback: (editor: TestCodeEditor, cursor: Cursor) => void): void {
// create a model if necessary and remember it in order to dispose it.
let modelToDispose: Model = null;
if (!options.model) {
modelToDispose = Model.createFromString(text.join('\n'));
options.model = modelToDispose;
}
let editor = <TestCodeEditor>_createTestCodeEditor(options);
callback(editor, editor.getCursor());
if (modelToDispose) {
modelToDispose.dispose();
}
editor.dispose();
}
export function createTestCodeEditor(model: editorCommon.IModel): TestCodeEditor {
return _createTestCodeEditor({ model: model });
}
function _createTestCodeEditor(options: TestCodeEditorCreationOptions): TestCodeEditor {
let contextKeyService = new MockContextKeyService();
let services = options.serviceCollection || new ServiceCollection();
services.set(IContextKeyService, contextKeyService);
let instantiationService = new InstantiationService(services);
let editor = new TestCodeEditor(new MockScopeLocation(), options, instantiationService, contextKeyService);
editor.setModel(options.model);
return editor;
}

View File

@@ -5,9 +5,9 @@
'use strict';
import { IDecorationRenderOptions, IModelDecorationOptions } from 'vs/editor/common/editorCommon';
import { AbstractCodeEditorService } from 'vs/editor/common/services/abstractCodeEditorService';
import { AbstractCodeEditorService } from 'vs/editor/browser/services/abstractCodeEditorService';
export class MockCodeEditorService extends AbstractCodeEditorService {
export class TestCodeEditorService extends AbstractCodeEditorService {
public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void { }
public removeDecorationType(key: string): void { }
public resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions { return null; }

View File

@@ -10,7 +10,7 @@ import { Selection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Model } from 'vs/editor/common/model/model';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
export function testCommand(
lines: string[],
@@ -21,7 +21,7 @@ export function testCommand(
expectedSelection: Selection
): void {
let model = Model.createFromString(lines.join('\n'), undefined, languageIdentifier);
withMockCodeEditor(null, { model: model }, (editor, cursor) => {
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
cursor.setSelections('tests', [selection]);
@@ -68,27 +68,3 @@ export function getEditOperation(model: editorCommon.IModel, command: editorComm
command.getEditOperations(model, editOperationBuilder);
return operations;
}
/**
* Create single edit operation
*/
export function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): editorCommon.IIdentifiedSingleEditOperation {
return {
identifier: null,
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text,
forceMoveMarkers: false
};
}
/**
* Create single edit operation
*/
export function createInsertDeleteSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): editorCommon.IIdentifiedSingleEditOperation {
return {
identifier: null,
range: new Range(selectionLineNumber, selectionColumn, positionLineNumber, positionColumn),
text: text,
forceMoveMarkers: true
};
}

View File

@@ -10,7 +10,7 @@ import { LanguageIdentifier } from 'vs/editor/common/modes';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
export class CommentMode extends MockMode {
private static _id = new LanguageIdentifier('commentMode', 3);
private static readonly _id = new LanguageIdentifier('commentMode', 3);
constructor(commentsConfig: CommentRule) {
super(CommentMode._id);

View File

@@ -50,7 +50,7 @@ suite('LineTokens', () => {
const lineTokens = createTestLineTokens();
assert.equal(lineTokens.getLineContent(), 'Hello world, this is a lovely day');
assert.equal(lineTokens.getLineLength(), 33);
assert.equal(lineTokens.getLineContent().length, 33);
assert.equal(lineTokens.getTokenCount(), 7);
assert.equal(lineTokens.getTokenStartOffset(0), 0);

View File

@@ -1,114 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { CommonCodeEditor } from 'vs/editor/common/commonCodeEditor';
import { CommonEditorConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { Cursor } from 'vs/editor/common/controller/cursor';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Model } from 'vs/editor/common/model/model';
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { IDisposable } from 'vs/base/common/lifecycle';
export class MockCodeEditor extends CommonCodeEditor {
public _isFocused = true;
protected _createConfiguration(options: editorOptions.IEditorOptions): CommonEditorConfiguration {
return new TestConfiguration(options);
}
public layout(dimension?: editorCommon.IDimension): void { }
public focus(): void { }
public isFocused(): boolean { return this._isFocused; }
public hasWidgetFocus(): boolean { return true; };
protected _enableEmptySelectionClipboard(): boolean { return false; }
protected _scheduleAtNextAnimationFrame(callback: () => void): IDisposable { throw new Error('Notimplemented'); }
protected _createView(): void { }
protected _registerDecorationType(key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void { throw new Error('NotImplemented'); }
protected _removeDecorationType(key: string): void { throw new Error('NotImplemented'); }
protected _resolveDecorationOptions(typeKey: string, writable: boolean): editorCommon.IModelDecorationOptions { throw new Error('NotImplemented'); }
// --- test utils
getCursor(): Cursor {
return this.cursor;
}
public registerAndInstantiateContribution<T extends editorCommon.IEditorContribution>(ctor: any): T {
let r = <T>this._instantiationService.createInstance(ctor, this);
this._contributions[r.getId()] = r;
return r;
}
public dispose() {
super.dispose();
if (this.model) {
this.model.dispose();
}
this._contextKeyService.dispose();
}
}
export class MockScopeLocation implements IContextKeyServiceTarget {
parentElement: IContextKeyServiceTarget = null;
setAttribute(attr: string, value: string): void { }
removeAttribute(attr: string): void { }
hasAttribute(attr: string): boolean { return false; }
getAttribute(attr: string): string { return undefined; }
}
export interface MockCodeEditorCreationOptions extends editorOptions.IEditorOptions {
/**
* The initial model associated with this code editor.
*/
model?: editorCommon.IModel;
serviceCollection?: ServiceCollection;
}
export function withMockCodeEditor(text: string[], options: MockCodeEditorCreationOptions, callback: (editor: MockCodeEditor, cursor: Cursor) => void): void {
// create a model if necessary and remember it in order to dispose it.
let modelToDispose: Model = null;
if (!options.model) {
modelToDispose = Model.createFromString(text.join('\n'));
options.model = modelToDispose;
}
let editor = <MockCodeEditor>_mockCodeEditor(options);
callback(editor, editor.getCursor());
if (modelToDispose) {
modelToDispose.dispose();
}
editor.dispose();
}
export function mockCodeEditor(text: string[], options: MockCodeEditorCreationOptions): CommonCodeEditor {
// TODO: who owns this model now?
if (!options.model) {
options.model = Model.createFromString(text.join('\n'));
}
return _mockCodeEditor(options);
}
function _mockCodeEditor(options: MockCodeEditorCreationOptions): CommonCodeEditor {
let contextKeyService = new MockContextKeyService();
let services = options.serviceCollection || new ServiceCollection();
services.set(IContextKeyService, contextKeyService);
let instantiationService = new InstantiationService(services);
let editor = new MockCodeEditor(new MockScopeLocation(), options, instantiationService, contextKeyService);
editor.setModel(options.model);
return editor;
}

View File

@@ -12,6 +12,12 @@ import { EditableTextModel, IValidatedEditOperation } from 'vs/editor/common/mod
import { MirrorModel } from 'vs/editor/common/model/mirrorModel';
import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils';
import { IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { TextModel } from 'vs/editor/common/model/textModel';
import { RawTextSource } from 'vs/editor/common/model/textSource';
function createEditableTextModelFromString(text: string): EditableTextModel {
return new EditableTextModel(RawTextSource.fromString(text), TextModel.DEFAULT_CREATION_OPTIONS, null);
}
suite('EditorModel - EditableTextModel._getInverseEdits', () => {
@@ -280,7 +286,7 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => {
}
function testSimpleApplyEdits(original: string[], edits: IValidatedEditOperation[], expected: IValidatedEditOperation): void {
let model = EditableTextModel.createFromString(original.join('\n'));
let model = createEditableTextModelFromString(original.join('\n'));
model.setEOL(EndOfLineSequence.LF);
let actual = model._toSingleEditOperation(edits);
@@ -522,7 +528,7 @@ suite('EditorModel - EditableTextModel._toSingleEditOperation', () => {
suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () => {
function testApplyEdits(original: string[], edits: IIdentifiedSingleEditOperation[], before: boolean, after: boolean): void {
let model = EditableTextModel.createFromString(original.join('\n'));
let model = createEditableTextModelFromString(original.join('\n'));
model.setEOL(EndOfLineSequence.LF);
assert.equal(model.mightContainRTL(), before);
@@ -570,7 +576,7 @@ suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () =
suite('EditorModel - EditableTextModel.applyEdits updates mightContainNonBasicASCII', () => {
function testApplyEdits(original: string[], edits: IIdentifiedSingleEditOperation[], before: boolean, after: boolean): void {
let model = EditableTextModel.createFromString(original.join('\n'));
let model = createEditableTextModelFromString(original.join('\n'));
model.setEOL(EndOfLineSequence.LF);
assert.equal(model.mightContainNonBasicASCII(), before);
@@ -1365,7 +1371,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
});
function testApplyEditsFails(original: string[], edits: IIdentifiedSingleEditOperation[]): void {
let model = EditableTextModel.createFromString(original.join('\n'));
let model = createEditableTextModelFromString(original.join('\n'));
let hasThrown = false;
try {
@@ -1506,7 +1512,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
}, (model) => {
var isFirstTime = true;
model.addBulkListener((events) => {
model.onDidChangeRawContent(() => {
if (!isFirstTime) {
return;
}
@@ -1553,7 +1559,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
});
test('issue #1580: Changes in line endings are not correctly reflected in the extension host, leading to invalid offsets sent to external refactoring tools', () => {
let model = EditableTextModel.createFromString('Hello\nWorld!');
let model = createEditableTextModelFromString('Hello\nWorld!');
assert.equal(model.getEOL(), '\n');
let mirrorModel2 = new MirrorModel(null, model.getLinesContent(), model.getEOL(), model.getVersionId());

View File

@@ -1,388 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { Model } from 'vs/editor/common/model/model';
import { computeRanges, MAX_FOLDING_REGIONS } from 'vs/editor/common/model/indentRanges';
import { FoldingMarkers } from 'vs/editor/common/modes/languageConfiguration';
export interface ExpectedIndentRange {
startLineNumber: number;
endLineNumber: number;
indent: number;
parentIndex: number;
}
function assertRanges(lines: string[], expected: ExpectedIndentRange[], offside: boolean, markers?: FoldingMarkers): void {
let model = Model.createFromString(lines.join('\n'));
let actual = computeRanges(model, offside, markers);
let actualRanges = [];
for (let i = 0; i < actual.length; i++) {
actualRanges[i] = r(actual.getStartLineNumber(i), actual.getEndLineNumber(i), actual.getIndent(i), actual.getParentIndex(i));
}
assert.deepEqual(actualRanges, expected);
model.dispose();
}
function r(startLineNumber: number, endLineNumber: number, indent: number, parentIndex: number, marker = false): ExpectedIndentRange {
return { startLineNumber, endLineNumber, indent, parentIndex };
}
suite('Indentation Folding', () => {
test('Fold one level', () => {
let range = [
'A',
' A',
' A',
' A'
];
assertRanges(range, [r(1, 4, 0, -1)], true);
assertRanges(range, [r(1, 4, 0, -1)], false);
});
test('Fold two levels', () => {
let range = [
'A',
' A',
' A',
' A',
' A'
];
assertRanges(range, [r(1, 5, 0, -1), r(3, 5, 2, 0)], true);
assertRanges(range, [r(1, 5, 0, -1), r(3, 5, 2, 0)], false);
});
test('Fold three levels', () => {
let range = [
'A',
' A',
' A',
' A',
'A'
];
assertRanges(range, [r(1, 4, 0, -1), r(2, 4, 2, 0), r(3, 4, 4, 1)], true);
assertRanges(range, [r(1, 4, 0, -1), r(2, 4, 2, 0), r(3, 4, 4, 1)], false);
});
test('Fold decreasing indent', () => {
let range = [
' A',
' A',
'A'
];
assertRanges(range, [], true);
assertRanges(range, [], false);
});
test('Fold Java', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ ' void foo() {',
/* 3*/ ' console.log();',
/* 4*/ ' console.log();',
/* 5*/ ' }',
/* 6*/ '',
/* 7*/ ' void bar() {',
/* 8*/ ' console.log();',
/* 9*/ ' }',
/*10*/ '}',
/*11*/ 'interface B {',
/*12*/ ' void bar();',
/*13*/ '}',
], [r(1, 9, 0, -1), r(2, 4, 2, 0), r(7, 8, 2, 0), r(11, 12, 0, -1)], false);
});
test('Fold Javadoc', () => {
assertRanges([
/* 1*/ '/**',
/* 2*/ ' * Comment',
/* 3*/ ' */',
/* 4*/ 'class A {',
/* 5*/ ' void foo() {',
/* 6*/ ' }',
/* 7*/ '}',
], [r(1, 3, 0, -1), r(4, 6, 0, -1)], false);
});
test('Fold Whitespace Java', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ '',
/* 3*/ ' void foo() {',
/* 4*/ ' ',
/* 5*/ ' return 0;',
/* 6*/ ' }',
/* 7*/ ' ',
/* 8*/ '}',
], [r(1, 7, 0, -1), r(3, 5, 2, 0)], false);
});
test('Fold Whitespace Python', () => {
assertRanges([
/* 1*/ 'def a:',
/* 2*/ ' pass',
/* 3*/ ' ',
/* 4*/ ' def b:',
/* 5*/ ' pass',
/* 6*/ ' ',
/* 7*/ ' ',
/* 8*/ 'def c: # since there was a deintent here'
], [r(1, 5, 0, -1), r(4, 5, 2, 0)], true);
});
test('Fold Tabs', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ '\t\t',
/* 3*/ '\tvoid foo() {',
/* 4*/ '\t \t//hello',
/* 5*/ '\t return 0;',
/* 6*/ ' \t}',
/* 7*/ ' ',
/* 8*/ '}',
], [r(1, 7, 0, -1), r(3, 5, 4, 0)], false);
});
});
let markers: FoldingMarkers = {
start: /^\s*#region\b/,
end: /^\s*#endregion\b/
};
suite('Folding with regions', () => {
test('Inside region, indented', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ ' #region',
/* 3*/ ' void foo() {',
/* 4*/ ' ',
/* 5*/ ' return 0;',
/* 6*/ ' }',
/* 7*/ ' #endregion',
/* 8*/ '}',
], [r(1, 7, 0, -1), r(2, 7, 2, 0, true), r(3, 5, 2, 1)], false, markers);
});
test('Inside region, not indented', () => {
assertRanges([
/* 1*/ 'var x;',
/* 2*/ '#region',
/* 3*/ 'void foo() {',
/* 4*/ ' ',
/* 5*/ ' return 0;',
/* 6*/ ' }',
/* 7*/ '#endregion',
/* 8*/ '',
], [r(2, 7, 0, -1, true), r(3, 6, 0, 0)], false, markers);
});
test('Empty Regions', () => {
assertRanges([
/* 1*/ 'var x;',
/* 2*/ '#region',
/* 3*/ '#endregion',
/* 4*/ '#region',
/* 5*/ '',
/* 6*/ '#endregion',
/* 7*/ 'var y;',
], [r(2, 3, 0, -1, true), r(4, 6, 0, -1, true)], false, markers);
});
test('Nested Regions', () => {
assertRanges([
/* 1*/ 'var x;',
/* 2*/ '#region',
/* 3*/ '#region',
/* 4*/ '',
/* 5*/ '#endregion',
/* 6*/ '#endregion',
/* 7*/ 'var y;',
], [r(2, 6, 0, -1, true), r(3, 5, 0, 0, true)], false, markers);
});
test('Nested Regions 2', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ ' #region',
/* 3*/ '',
/* 4*/ ' #region',
/* 5*/ '',
/* 6*/ ' #endregion',
/* 7*/ ' // comment',
/* 8*/ ' #endregion',
/* 9*/ '}',
], [r(1, 8, 0, -1), r(2, 8, 2, 0, true), r(4, 6, 2, 1, true)], false, markers);
});
test('Incomplete Regions', () => {
assertRanges([
/* 1*/ 'class A {',
/* 2*/ '#region',
/* 3*/ ' // comment',
/* 4*/ '}',
], [r(2, 3, 0, -1)], false, markers);
});
test('Incomplete Regions 2', () => {
assertRanges([
/* 1*/ '',
/* 2*/ '#region',
/* 3*/ '#region',
/* 4*/ '#region',
/* 5*/ ' // comment',
/* 6*/ '#endregion',
/* 7*/ '#endregion',
/* 8*/ ' // hello',
], [r(3, 7, 0, -1, true), r(4, 6, 0, 0, true)], false, markers);
});
test('Indented region before', () => {
assertRanges([
/* 1*/ 'if (x)',
/* 2*/ ' return;',
/* 3*/ '',
/* 4*/ '#region',
/* 5*/ ' // comment',
/* 6*/ '#endregion',
], [r(1, 3, 0, -1), r(4, 6, 0, -1, true)], false, markers);
});
test('Indented region before 2', () => {
assertRanges([
/* 1*/ 'if (x)',
/* 2*/ ' log();',
/* 3*/ '',
/* 4*/ ' #region',
/* 5*/ ' // comment',
/* 6*/ ' #endregion',
], [r(1, 6, 0, -1), r(2, 6, 2, 0), r(4, 6, 4, 1, true)], false, markers);
});
test('Indented region in-between', () => {
assertRanges([
/* 1*/ '#region',
/* 2*/ ' // comment',
/* 3*/ ' if (x)',
/* 4*/ ' return;',
/* 5*/ '',
/* 6*/ '#endregion',
], [r(1, 6, 0, -1, true), r(3, 5, 2, 0)], false, markers);
});
test('Indented region after', () => {
assertRanges([
/* 1*/ '#region',
/* 2*/ ' // comment',
/* 3*/ '',
/* 4*/ '#endregion',
/* 5*/ ' if (x)',
/* 6*/ ' return;',
], [r(1, 4, 0, -1, true), r(5, 6, 2, -1)], false, markers);
});
test('With off-side', () => {
assertRanges([
/* 1*/ '#region',
/* 2*/ ' ',
/* 3*/ '',
/* 4*/ '#endregion',
/* 5*/ '',
], [r(1, 4, 0, -1, true)], true, markers);
});
test('Nested with off-side', () => {
assertRanges([
/* 1*/ '#region',
/* 2*/ ' ',
/* 3*/ '#region',
/* 4*/ '',
/* 5*/ '#endregion',
/* 6*/ '',
/* 7*/ '#endregion',
/* 8*/ '',
], [r(1, 7, 0, -1, true), r(3, 5, 0, 0, true)], true, markers);
});
test('Issue 35981', () => {
assertRanges([
/* 1*/ 'function thisFoldsToEndOfPage() {',
/* 2*/ ' const variable = []',
/* 3*/ ' // #region',
/* 4*/ ' .reduce((a, b) => a,[]);',
/* 5*/ '}',
/* 6*/ '',
/* 7*/ 'function thisFoldsProperly() {',
/* 8*/ ' const foo = "bar"',
/* 9*/ '}',
], [r(1, 4, 0, -1), r(2, 4, 2, 0), r(7, 8, 0, -1)], false, markers);
});
test('Misspelled Markers', () => {
assertRanges([
/* 1*/ '#Region',
/* 2*/ '#endregion',
/* 3*/ '#regionsandmore',
/* 4*/ '#endregion',
/* 5*/ '#region',
/* 6*/ '#end region',
/* 7*/ '#region',
/* 8*/ '#endregionff',
], [], true, markers);
});
test('test max folding regions', () => {
let lines = [];
let nRegions = MAX_FOLDING_REGIONS;
for (let i = 0; i < nRegions; i++) {
lines.push('#region');
}
for (let i = 0; i < nRegions; i++) {
lines.push('#endregion');
}
let model = Model.createFromString(lines.join('\n'));
let actual = computeRanges(model, false, markers, MAX_FOLDING_REGIONS);
assert.equal(actual.length, nRegions, 'len');
for (let i = 0; i < nRegions; i++) {
assert.equal(actual.getStartLineNumber(i), i + 1, 'start' + i);
assert.equal(actual.getEndLineNumber(i), nRegions * 2 - i, 'end' + i);
assert.equal(actual.getParentIndex(i), i - 1, 'parent' + i);
}
});
test('findRange', () => {
let lines = [
/* 1*/ '#region',
/* 2*/ '#endregion',
/* 3*/ 'class A {',
/* 4*/ ' void foo() {',
/* 5*/ ' if (true) {',
/* 6*/ ' return;',
/* 7*/ ' }',
/* 8*/ '',
/* 9*/ ' if (true) {',
/* 10*/ ' return;',
/* 11*/ ' }',
/* 12*/ ' }',
/* 13*/ '}'];
let textModel = Model.createFromString(lines.join('\n'));
try {
let actual = computeRanges(textModel, false, markers);
// let r0 = r(1, 2);
// let r1 = r(3, 12);
// let r2 = r(4, 11);
// let r3 = r(5, 6);
// let r4 = r(9, 10);
assert.equal(actual.findRange(1), 0, '1');
assert.equal(actual.findRange(2), 0, '2');
assert.equal(actual.findRange(3), 1, '3');
assert.equal(actual.findRange(4), 2, '4');
assert.equal(actual.findRange(5), 3, '5');
assert.equal(actual.findRange(6), 3, '6');
assert.equal(actual.findRange(7), 2, '7');
assert.equal(actual.findRange(8), 2, '8');
assert.equal(actual.findRange(9), 4, '9');
assert.equal(actual.findRange(10), 4, '10');
assert.equal(actual.findRange(11), 2, '11');
assert.equal(actual.findRange(12), 1, '12');
assert.equal(actual.findRange(13), -1, '13');
} finally {
textModel.dispose();
}
});
});

View File

@@ -5,7 +5,7 @@
'use strict';
import * as assert from 'assert';
import { IntervalTree, IntervalNode } from 'vs/editor/common/model/intervalTree';
import { IntervalTree, IntervalNode, getNodeColor, NodeColor, SENTINEL, intervalCompare } from 'vs/editor/common/model/intervalTree';
const GENERATE_TESTS = false;
let TEST_COUNT = GENERATE_TESTS ? 10000 : 0;
@@ -116,10 +116,10 @@ suite('IntervalTree', () => {
}
if (PRINT_TREE) {
this._tree.print();
printTree(this._tree);
}
this._tree.assertInvariants();
assertTreeInvariants(this._tree);
let actual = this._tree.getAllInOrder().map(n => new Interval(n.cachedAbsoluteStart, n.cachedAbsoluteEnd));
let expected = this._oracle.intervals;
@@ -553,3 +553,89 @@ suite('IntervalTree', () => {
});
});
});
function printTree(T: IntervalTree): void {
if (T.root === SENTINEL) {
console.log(`~~ empty`);
return;
}
let out: string[] = [];
_printTree(T, T.root, '', 0, out);
console.log(out.join(''));
}
function _printTree(T: IntervalTree, n: IntervalNode, indent: string, delta: number, out: string[]): void {
out.push(`${indent}[${getNodeColor(n) === NodeColor.Red ? 'R' : 'B'},${n.delta}, ${n.start}->${n.end}, ${n.maxEnd}] : {${delta + n.start}->${delta + n.end}}, maxEnd: ${n.maxEnd + delta}\n`);
if (n.left !== SENTINEL) {
_printTree(T, n.left, indent + ' ', delta, out);
} else {
out.push(`${indent} NIL\n`);
}
if (n.right !== SENTINEL) {
_printTree(T, n.right, indent + ' ', delta + n.delta, out);
} else {
out.push(`${indent} NIL\n`);
}
}
//#region Assertion
function assertTreeInvariants(T: IntervalTree): void {
assert(getNodeColor(SENTINEL) === NodeColor.Black);
assert(SENTINEL.parent === SENTINEL);
assert(SENTINEL.left === SENTINEL);
assert(SENTINEL.right === SENTINEL);
assert(SENTINEL.start === 0);
assert(SENTINEL.end === 0);
assert(SENTINEL.delta === 0);
assert(T.root.parent === SENTINEL);
assertValidTree(T);
}
function depth(n: IntervalNode): number {
if (n === SENTINEL) {
// The leafs are black
return 1;
}
assert(depth(n.left) === depth(n.right));
return (getNodeColor(n) === NodeColor.Black ? 1 : 0) + depth(n.left);
}
function assertValidNode(n: IntervalNode, delta): void {
if (n === SENTINEL) {
return;
}
let l = n.left;
let r = n.right;
if (getNodeColor(n) === NodeColor.Red) {
assert(getNodeColor(l) === NodeColor.Black);
assert(getNodeColor(r) === NodeColor.Black);
}
let expectedMaxEnd = n.end;
if (l !== SENTINEL) {
assert(intervalCompare(l.start + delta, l.end + delta, n.start + delta, n.end + delta) <= 0);
expectedMaxEnd = Math.max(expectedMaxEnd, l.maxEnd);
}
if (r !== SENTINEL) {
assert(intervalCompare(n.start + delta, n.end + delta, r.start + delta + n.delta, r.end + delta + n.delta) <= 0);
expectedMaxEnd = Math.max(expectedMaxEnd, r.maxEnd + n.delta);
}
assert(n.maxEnd === expectedMaxEnd);
assertValidNode(l, delta);
assertValidNode(r, delta + n.delta);
}
function assertValidTree(T: IntervalTree): void {
if (T.root === SENTINEL) {
return;
}
assert(getNodeColor(T.root) === NodeColor.Black);
assert(depth(T.root.left) === depth(T.root.right));
assertValidNode(T.root, 0);
}
//#endregion

View File

@@ -11,7 +11,7 @@ import { MetadataConsts } from 'vs/editor/common/modes';
import { ViewLineToken, ViewLineTokenFactory } from 'vs/editor/common/core/viewLineToken';
function assertLineTokens(_actual: LineTokens, _expected: TestToken[]): void {
let expected = ViewLineTokenFactory.inflateArr(TestToken.toTokens(_expected), _actual.getLineLength());
let expected = ViewLineTokenFactory.inflateArr(TestToken.toTokens(_expected), _actual.getLineContent().length);
let actual = _actual.inflate();
let decode = (token: ViewLineToken) => {
return {
@@ -1521,4 +1521,3 @@ suite('Editor Model - modelLine.append', () => {
);
});
});

View File

@@ -1154,7 +1154,6 @@ suite('deltaDecorations', () => {
assert.equal(initialIds.length, decorations.length, 'returns expected cnt of ids');
assert.equal(initialIds.length, model.getAllDecorations().length, 'does not leak decorations');
assert.equal(initialIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges');
actualDecorations.sort((a, b) => strcmp(a.id, b.id));
decorations.sort((a, b) => strcmp(a.id, b.id));
assert.deepEqual(actualDecorations, decorations);
@@ -1164,7 +1163,6 @@ suite('deltaDecorations', () => {
assert.equal(newIds.length, newDecorations.length, 'returns expected cnt of ids');
assert.equal(newIds.length, model.getAllDecorations().length, 'does not leak decorations');
assert.equal(newIds.length, model._getTrackedRangesCount(), 'does not leak tracked ranges');
actualNewDecorations.sort((a, b) => strcmp(a.id, b.id));
newDecorations.sort((a, b) => strcmp(a.id, b.id));
assert.deepEqual(actualDecorations, decorations);

View File

@@ -197,7 +197,7 @@ suite('Editor Modes - textToHtmlTokenizer', () => {
class Mode extends MockMode {
private static _id = new LanguageIdentifier('textToHtmlTokenizerMode', 3);
private static readonly _id = new LanguageIdentifier('textToHtmlTokenizerMode', 3);
constructor() {
super(Mode._id);

View File

@@ -7,19 +7,15 @@
import * as assert from 'assert';
import { DecorationSegment, LineDecorationsNormalizer, LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { Range } from 'vs/editor/common/core/range';
import { InlineDecoration } from 'vs/editor/common/viewModel/viewModel';
import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
suite('Editor ViewLayout - ViewLineParts', () => {
function newDecoration(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, inlineClassName: string): InlineDecoration {
return new InlineDecoration(new Range(startLineNumber, startColumn, endLineNumber, endColumn), inlineClassName, false);
}
test('Bug 9827:Overlapping inline decorations can cause wrong inline class to be applied', () => {
var result = LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 11, 'c1', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 11, 'c1', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]);
assert.deepEqual(result, [
@@ -32,8 +28,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
test('issue #3462: no whitespace shown at the end of a decorated line', () => {
var result = LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(15, 21, 'vs-whitespace', false),
new LineDecoration(20, 21, 'inline-folded', false),
new LineDecoration(15, 21, 'vs-whitespace', InlineDecorationType.Regular),
new LineDecoration(20, 21, 'inline-folded', InlineDecorationType.Regular),
]);
assert.deepEqual(result, [
@@ -45,76 +41,88 @@ suite('Editor ViewLayout - ViewLineParts', () => {
test('issue #3661: Link decoration bleeds to next line when wrapping', () => {
let result = LineDecoration.filter([
newDecoration(2, 12, 3, 30, 'detected-link')
new InlineDecoration(new Range(2, 12, 3, 30), 'detected-link', InlineDecorationType.Regular)
], 3, 12, 500);
assert.deepEqual(result, [
new LineDecoration(12, 30, 'detected-link', false),
new LineDecoration(12, 30, 'detected-link', InlineDecorationType.Regular),
]);
});
test('issue #37401: Allow both before and after decorations on empty line', () => {
let result = LineDecoration.filter([
new InlineDecoration(new Range(4, 1, 4, 2), 'before', InlineDecorationType.Before),
new InlineDecoration(new Range(4, 0, 4, 1), 'after', InlineDecorationType.After),
], 4, 1, 500);
assert.deepEqual(result, [
new LineDecoration(1, 2, 'before', InlineDecorationType.Before),
new LineDecoration(0, 1, 'after', InlineDecorationType.After),
]);
});
test('ViewLineParts', () => {
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 2, 'c1', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 2, 'c1', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 0, 'c1'),
new DecorationSegment(2, 2, 'c2')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 3, 'c1', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 3, 'c1', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1'),
new DecorationSegment(2, 2, 'c2')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 4, 'c1', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1'),
new DecorationSegment(2, 2, 'c1 c2')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 4, 'c1', false),
new LineDecoration(1, 4, 'c1*', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1 c1*'),
new DecorationSegment(2, 2, 'c1 c1* c2')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 4, 'c1', false),
new LineDecoration(1, 4, 'c1*', false),
new LineDecoration(1, 4, 'c1**', false),
new LineDecoration(3, 4, 'c2', false)
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1 c1* c1**'),
new DecorationSegment(2, 2, 'c1 c1* c1** c2')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 4, 'c1', false),
new LineDecoration(1, 4, 'c1*', false),
new LineDecoration(1, 4, 'c1**', false),
new LineDecoration(3, 4, 'c2', false),
new LineDecoration(3, 4, 'c2*', false)
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2*', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1 c1* c1**'),
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*')
]);
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
new LineDecoration(1, 4, 'c1', false),
new LineDecoration(1, 4, 'c1*', false),
new LineDecoration(1, 4, 'c1**', false),
new LineDecoration(3, 4, 'c2', false),
new LineDecoration(3, 5, 'c2*', false)
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular),
new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular),
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular),
new LineDecoration(3, 5, 'c2*', InlineDecorationType.Regular)
]), [
new DecorationSegment(0, 1, 'c1 c1* c1**'),
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*'),

View File

@@ -10,6 +10,7 @@ import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
import { CharCode } from 'vs/base/common/charCode';
import { MetadataConsts } from 'vs/editor/common/modes';
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
suite('viewLineRenderer.renderLine', () => {
@@ -700,7 +701,7 @@ suite('viewLineRenderer.renderLine 2', () => {
false,
0,
[createPart(21, 3)],
[new LineDecoration(1, 22, 'link', false)],
[new LineDecoration(1, 22, 'link', InlineDecorationType.Regular)],
4,
10,
-1,
@@ -735,7 +736,7 @@ suite('viewLineRenderer.renderLine 2', () => {
createPart(84, 6),
],
[
new LineDecoration(13, 51, 'detected-link', false)
new LineDecoration(13, 51, 'detected-link', InlineDecorationType.Regular)
],
4,
10,
@@ -993,9 +994,9 @@ suite('viewLineRenderer.renderLine 2', () => {
0,
[createPart(11, 0)],
[
new LineDecoration(5, 7, 'a', false),
new LineDecoration(1, 3, 'b', false),
new LineDecoration(2, 8, 'c', false),
new LineDecoration(5, 7, 'a', InlineDecorationType.Regular),
new LineDecoration(1, 3, 'b', InlineDecorationType.Regular),
new LineDecoration(2, 8, 'c', InlineDecorationType.Regular),
],
4,
10,
@@ -1033,7 +1034,7 @@ suite('viewLineRenderer.renderLine 2', () => {
false,
0,
[createPart(4, 3)],
[new LineDecoration(1, 2, 'before', true)],
[new LineDecoration(1, 2, 'before', InlineDecorationType.Before)],
4,
10,
-1,
@@ -1062,7 +1063,7 @@ suite('viewLineRenderer.renderLine 2', () => {
false,
0,
[createPart(4, 3)],
[new LineDecoration(2, 3, 'before', true)],
[new LineDecoration(2, 3, 'before', InlineDecorationType.Before)],
4,
10,
-1,
@@ -1092,7 +1093,7 @@ suite('viewLineRenderer.renderLine 2', () => {
false,
0,
[createPart(0, 3)],
[new LineDecoration(1, 2, 'before', true)],
[new LineDecoration(1, 2, 'before', InlineDecorationType.Before)],
4,
10,
-1,
@@ -1103,7 +1104,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let expected = [
'<span>',
'<span class="before">\u00a0</span>',
'<span class="before"></span>',
'</span>'
].join('');
@@ -1118,7 +1119,7 @@ suite('viewLineRenderer.renderLine 2', () => {
false,
0,
[createPart(7, 3)],
[new LineDecoration(7, 8, 'inline-folded', true)],
[new LineDecoration(7, 8, 'inline-folded', InlineDecorationType.After)],
2,
10,
10000,
@@ -1137,6 +1138,65 @@ suite('viewLineRenderer.renderLine 2', () => {
assert.deepEqual(actual.html, expected);
});
test('issue #37401: Allow both before and after decorations on empty line', () => {
let actual = renderViewLine(new RenderLineInput(
true,
'',
false,
0,
[createPart(0, 3)],
[
new LineDecoration(1, 2, 'before', InlineDecorationType.Before),
new LineDecoration(0, 1, 'after', InlineDecorationType.After),
],
2,
10,
10000,
'none',
false,
false
));
let expected = [
'<span>',
'<span class="before after"></span>',
'</span>'
].join('');
assert.deepEqual(actual.html, expected);
});
test('issue #38935: GitLens end-of-line blame no longer rendering', () => {
let actual = renderViewLine(new RenderLineInput(
true,
'\t}',
false,
0,
[createPart(2, 3)],
[
new LineDecoration(3, 3, 'ced-TextEditorDecorationType2-5e9b9b3f-3 ced-TextEditorDecorationType2-3', InlineDecorationType.Before),
new LineDecoration(3, 3, 'ced-TextEditorDecorationType2-5e9b9b3f-4 ced-TextEditorDecorationType2-4', InlineDecorationType.After),
],
4,
10,
10000,
'none',
false,
false
));
let expected = [
'<span>',
'<span class="mtk3">\u00a0\u00a0\u00a0\u00a0}</span>',
'<span class="ced-TextEditorDecorationType2-5e9b9b3f-3 ced-TextEditorDecorationType2-3 ced-TextEditorDecorationType2-5e9b9b3f-4 ced-TextEditorDecorationType2-4"></span>',
'</span>'
].join('');
assert.deepEqual(actual.html, expected);
});
function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[], expectedPartLengths: number[]): (partIndex: number, partLength: number, offset: number, expected: number) => void {
let renderLineOutput = renderViewLine(new RenderLineInput(
false,

View File

@@ -32,22 +32,22 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
assert.equal(line1.getViewLineMaxColumn(model1, 1, 0), 14);
assert.equal(line1.getViewLineMaxColumn(model1, 1, 1), 15);
assert.equal(line1.getViewLineMaxColumn(model1, 1, 2), 16);
for (var col = 1; col <= 14; col++) {
for (let col = 1; col <= 14; col++) {
assert.equal(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')');
}
for (var col = 1; col <= 15; col++) {
for (let col = 1; col <= 15; col++) {
assert.equal(line1.getModelColumnOfViewPosition(1, col), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')');
}
for (var col = 1; col <= 16; col++) {
for (let col = 1; col <= 16; col++) {
assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')');
}
for (var col = 1; col <= 13; col++) {
for (let col = 1; col <= 13; col++) {
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')');
}
for (var col = 1 + 13; col <= 14 + 13; col++) {
for (let col = 1 + 13; col <= 14 + 13; col++) {
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, col - 13), 'getOutputPositionOfInputPosition(' + col + ')');
}
for (var col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {
for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')');
}
@@ -61,28 +61,28 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
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 (var col = 1; col <= 14; col++) {
for (let col = 1; col <= 14; col++) {
assert.equal(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')');
}
for (var col = 1; col <= 1; col++) {
for (let col = 1; col <= 1; col++) {
assert.equal(line1.getModelColumnOfViewPosition(1, 1), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')');
}
for (var col = 2; col <= 16; col++) {
for (let col = 2; col <= 16; col++) {
assert.equal(line1.getModelColumnOfViewPosition(1, col), 13 + col - 1, 'getInputColumnOfOutputPosition(1, ' + col + ')');
}
for (var col = 1; col <= 1; col++) {
for (let col = 1; col <= 1; col++) {
assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')');
}
for (var col = 2; col <= 17; col++) {
for (let col = 2; col <= 17; col++) {
assert.equal(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col - 1, 'getInputColumnOfOutputPosition(2, ' + col + ')');
}
for (var col = 1; col <= 13; col++) {
for (let col = 1; col <= 13; col++) {
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')');
}
for (var col = 1 + 13; col <= 14 + 13; col++) {
for (let col = 1 + 13; col <= 14 + 13; col++) {
assert.deepEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 1 + col - 13), 'getOutputPositionOfInputPosition(' + col + ')');
}
for (var col = 1 + 13 + 14; col <= 15 + 14 + 13; 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 + ')');
}
});

View File

@@ -7,9 +7,9 @@
import { Model } from 'vs/editor/common/model/model';
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { MockCodeEditorCreationOptions } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
export function testViewModel(text: string[], options: MockCodeEditorCreationOptions, callback: (viewModel: ViewModel, model: Model) => void): void {
export function testViewModel(text: string[], options: IEditorOptions, callback: (viewModel: ViewModel, model: Model) => void): void {
const EDITOR_ID = 1;
let configuration = new TestConfiguration(options);

View File

@@ -7,14 +7,15 @@
import * as assert from 'assert';
import { Range } from 'vs/editor/common/core/range';
import { testViewModel } from 'vs/editor/test/common/viewModel/testViewModel';
import { MockCodeEditorCreationOptions } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
suite('ViewModelDecorations', () => {
test('getDecorationsViewportData', () => {
const text = [
'hello world, this is a buffer that will be wrapped'
];
const opts: MockCodeEditorCreationOptions = {
const opts: IEditorOptions = {
wordWrap: 'wordWrapColumn',
wordWrapColumn: 13
};
@@ -25,21 +26,6 @@ suite('ViewModelDecorations', () => {
assert.equal(viewModel.getLineContent(4), 'will be ');
assert.equal(viewModel.getLineContent(5), 'wrapped');
let dec1: string;
let dec2: string;
let dec3: string;
let dec4: string;
let dec5: string;
let dec6: string;
let dec7: string;
let dec8: string;
let dec9: string;
let dec10: string;
let dec11: string;
let dec12: string;
let dec13: string;
let dec14: string;
let dec15: string;
model.changeDecorations((accessor) => {
let createOpts = (id: string) => {
return {
@@ -53,39 +39,39 @@ suite('ViewModelDecorations', () => {
// VIEWPORT will be (1,14) -> (1,36)
// completely before viewport
dec1 = accessor.addDecoration(new Range(1, 2, 1, 3), createOpts('dec1'));
accessor.addDecoration(new Range(1, 2, 1, 3), createOpts('dec1'));
// starts before viewport, ends at viewport start
dec2 = accessor.addDecoration(new Range(1, 2, 1, 14), createOpts('dec2'));
accessor.addDecoration(new Range(1, 2, 1, 14), createOpts('dec2'));
// starts before viewport, ends inside viewport
dec3 = accessor.addDecoration(new Range(1, 2, 1, 15), createOpts('dec3'));
accessor.addDecoration(new Range(1, 2, 1, 15), createOpts('dec3'));
// starts before viewport, ends at viewport end
dec4 = accessor.addDecoration(new Range(1, 2, 1, 36), createOpts('dec4'));
accessor.addDecoration(new Range(1, 2, 1, 36), createOpts('dec4'));
// starts before viewport, ends after viewport
dec5 = accessor.addDecoration(new Range(1, 2, 1, 51), createOpts('dec5'));
accessor.addDecoration(new Range(1, 2, 1, 51), createOpts('dec5'));
// starts at viewport start, ends at viewport start
dec6 = accessor.addDecoration(new Range(1, 14, 1, 14), createOpts('dec6'));
accessor.addDecoration(new Range(1, 14, 1, 14), createOpts('dec6'));
// starts at viewport start, ends inside viewport
dec7 = accessor.addDecoration(new Range(1, 14, 1, 16), createOpts('dec7'));
accessor.addDecoration(new Range(1, 14, 1, 16), createOpts('dec7'));
// starts at viewport start, ends at viewport end
dec8 = accessor.addDecoration(new Range(1, 14, 1, 36), createOpts('dec8'));
accessor.addDecoration(new Range(1, 14, 1, 36), createOpts('dec8'));
// starts at viewport start, ends after viewport
dec9 = accessor.addDecoration(new Range(1, 14, 1, 51), createOpts('dec9'));
accessor.addDecoration(new Range(1, 14, 1, 51), createOpts('dec9'));
// starts inside viewport, ends inside viewport
dec10 = accessor.addDecoration(new Range(1, 16, 1, 18), createOpts('dec10'));
accessor.addDecoration(new Range(1, 16, 1, 18), createOpts('dec10'));
// starts inside viewport, ends at viewport end
dec11 = accessor.addDecoration(new Range(1, 16, 1, 36), createOpts('dec11'));
accessor.addDecoration(new Range(1, 16, 1, 36), createOpts('dec11'));
// starts inside viewport, ends after viewport
dec12 = accessor.addDecoration(new Range(1, 16, 1, 51), createOpts('dec12'));
accessor.addDecoration(new Range(1, 16, 1, 51), createOpts('dec12'));
// starts at viewport end, ends at viewport end
dec13 = accessor.addDecoration(new Range(1, 36, 1, 36), createOpts('dec13'));
accessor.addDecoration(new Range(1, 36, 1, 36), createOpts('dec13'));
// starts at viewport end, ends after viewport
dec14 = accessor.addDecoration(new Range(1, 36, 1, 51), createOpts('dec14'));
accessor.addDecoration(new Range(1, 36, 1, 51), createOpts('dec14'));
// starts after viewport, ends after viewport
dec15 = accessor.addDecoration(new Range(1, 40, 1, 51), createOpts('dec15'));
accessor.addDecoration(new Range(1, 40, 1, 51), createOpts('dec15'));
});
let actualDecorations = viewModel.getDecorationsInViewport(
@@ -120,107 +106,117 @@ suite('ViewModelDecorations', () => {
{
range: new Range(1, 2, 2, 1),
inlineClassName: 'i-dec2',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 1),
inlineClassName: 'a-dec2',
type: InlineDecorationType.After
},
{
range: new Range(1, 2, 2, 2),
inlineClassName: 'i-dec3',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 2),
range: new Range(2, 2, 2, 2),
inlineClassName: 'a-dec3',
insertsBeforeOrAfter: true
type: InlineDecorationType.After
},
{
range: new Range(1, 2, 4, 1),
inlineClassName: 'i-dec4',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(1, 2, 5, 8),
inlineClassName: 'i-dec5',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 1),
inlineClassName: 'i-dec6',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 2),
range: new Range(2, 1, 2, 1),
inlineClassName: 'b-dec6',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 1, 2, 1),
inlineClassName: 'a-dec6',
type: InlineDecorationType.After
},
{
range: new Range(2, 1, 2, 3),
inlineClassName: 'i-dec7',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 2),
range: new Range(2, 1, 2, 1),
inlineClassName: 'b-dec7',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 2, 2, 3),
range: new Range(2, 3, 2, 3),
inlineClassName: 'a-dec7',
insertsBeforeOrAfter: true
type: InlineDecorationType.After
},
{
range: new Range(2, 1, 4, 1),
inlineClassName: 'i-dec8',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 2),
range: new Range(2, 1, 2, 1),
inlineClassName: 'b-dec8',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 1, 5, 8),
inlineClassName: 'i-dec9',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 2, 2),
range: new Range(2, 1, 2, 1),
inlineClassName: 'b-dec9',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 3, 2, 5),
inlineClassName: 'i-dec10',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 3, 2, 4),
range: new Range(2, 3, 2, 3),
inlineClassName: 'b-dec10',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 4, 2, 5),
range: new Range(2, 5, 2, 5),
inlineClassName: 'a-dec10',
insertsBeforeOrAfter: true
type: InlineDecorationType.After
},
{
range: new Range(2, 3, 4, 1),
inlineClassName: 'i-dec11',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 3, 2, 4),
range: new Range(2, 3, 2, 3),
inlineClassName: 'b-dec11',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
{
range: new Range(2, 3, 5, 8),
inlineClassName: 'i-dec12',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 3, 2, 4),
range: new Range(2, 3, 2, 3),
inlineClassName: 'b-dec12',
insertsBeforeOrAfter: true
type: InlineDecorationType.Before
},
]);
@@ -234,32 +230,32 @@ suite('ViewModelDecorations', () => {
{
range: new Range(1, 2, 4, 1),
inlineClassName: 'i-dec4',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(1, 2, 5, 8),
inlineClassName: 'i-dec5',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 4, 1),
inlineClassName: 'i-dec8',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 1, 5, 8),
inlineClassName: 'i-dec9',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 3, 4, 1),
inlineClassName: 'i-dec11',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
{
range: new Range(2, 3, 5, 8),
inlineClassName: 'i-dec12',
insertsBeforeOrAfter: false
type: InlineDecorationType.Regular
},
]);
});
@@ -269,7 +265,7 @@ suite('ViewModelDecorations', () => {
const text = [
'hello world, this is a buffer that will be wrapped'
];
const opts: MockCodeEditorCreationOptions = {
const opts: IEditorOptions = {
wordWrap: 'wordWrapColumn',
wordWrapColumn: 13
};
@@ -280,9 +276,8 @@ suite('ViewModelDecorations', () => {
assert.equal(viewModel.getLineContent(4), 'will be ');
assert.equal(viewModel.getLineContent(5), 'wrapped');
let dec1: string;
model.changeDecorations((accessor) => {
dec1 = accessor.addDecoration(
accessor.addDecoration(
new Range(1, 50, 1, 51),
{
beforeContentClassName: 'dec1'
@@ -308,4 +303,39 @@ suite('ViewModelDecorations', () => {
assert.deepEqual(inlineDecorations2, []);
});
});
test('issue #37401: Allow both before and after decorations on empty line', () => {
const text = [
''
];
testViewModel(text, {}, (viewModel, model) => {
model.changeDecorations((accessor) => {
accessor.addDecoration(
new Range(1, 1, 1, 1),
{
beforeContentClassName: 'before1',
afterContentClassName: 'after1'
}
);
});
let inlineDecorations = viewModel.getViewLineRenderingData(
new Range(1, 1, 1, 1),
1
).inlineDecorations;
assert.deepEqual(inlineDecorations, [
{
range: new Range(1, 1, 1, 1),
inlineClassName: 'before1',
type: InlineDecorationType.Before
},
{
range: new Range(1, 1, 1, 1),
inlineClassName: 'after1',
type: InlineDecorationType.After
}
]);
});
});
});