mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
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:
@@ -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);
|
||||
@@ -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', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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');
|
||||
@@ -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', () => {
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
178
src/vs/editor/test/browser/testCodeEditor.ts
Normal file
178
src/vs/editor/test/browser/testCodeEditor.ts
Normal 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;
|
||||
}
|
||||
@@ -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; }
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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
|
||||
|
||||
@@ -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', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*'),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 + ')');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user