mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-08 09:38:26 -05:00
Merge from vscode e3c4990c67c40213af168300d1cfeb71d680f877 (#16569)
This commit is contained in:
@@ -2608,6 +2608,186 @@ suite('Editor Controller - Regression tests', () => {
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #122914: Left delete behavior in some languages is changed (useTabStops: false)', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
'สวัสดี'
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, viewModel) => {
|
||||
editor.setSelections([
|
||||
new Selection(1, 7, 1, 7)
|
||||
]);
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัสด');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัส');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวั');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สว');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ส');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #99629: Emoji modifiers in text treated separately when using backspace', () => {
|
||||
const model = createTextModel(
|
||||
[
|
||||
'👶🏾'
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, viewModel) => {
|
||||
const len = model.getValueLength();
|
||||
editor.setSelections([
|
||||
new Selection(1, 1 + len, 1, 1 + len)
|
||||
]);
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #99629: Emoji modifiers in text treated separately when using backspace (ZWJ sequence)', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
'👨👩🏽👧👦'
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, viewModel) => {
|
||||
const len = model.getValueLength();
|
||||
editor.setSelections([
|
||||
new Selection(1, 1 + len, 1, 1 + len)
|
||||
]);
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '👨👩🏽👧');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '👨👩🏽');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '👨');
|
||||
|
||||
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '');
|
||||
});
|
||||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('issue #105730: move left behaves differently for multiple cursors', () => {
|
||||
const model = createTextModel('asdfghjkl, asdfghjkl, asdfghjkl, ');
|
||||
|
||||
withTestCodeEditor(
|
||||
null,
|
||||
{
|
||||
model: model,
|
||||
wordWrap: 'wordWrapColumn',
|
||||
wordWrapColumn: 24
|
||||
},
|
||||
(editor, viewModel) => {
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(1, 10, 1, 12),
|
||||
new Selection(1, 21, 1, 23),
|
||||
new Selection(1, 32, 1, 34)
|
||||
]);
|
||||
moveLeft(editor, viewModel, false);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 10, 1, 10),
|
||||
new Selection(1, 21, 1, 21),
|
||||
new Selection(1, 32, 1, 32)
|
||||
]);
|
||||
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(1, 10, 1, 12),
|
||||
new Selection(1, 21, 1, 23),
|
||||
new Selection(1, 32, 1, 34)
|
||||
]);
|
||||
moveLeft(editor, viewModel, true);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 10, 1, 11),
|
||||
new Selection(1, 21, 1, 22),
|
||||
new Selection(1, 32, 1, 33)
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #105730: move right should always skip wrap point', () => {
|
||||
const model = createTextModel('asdfghjkl, asdfghjkl, asdfghjkl, \nasdfghjkl,');
|
||||
|
||||
withTestCodeEditor(
|
||||
null,
|
||||
{
|
||||
model: model,
|
||||
wordWrap: 'wordWrapColumn',
|
||||
wordWrapColumn: 24
|
||||
},
|
||||
(editor, viewModel) => {
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(1, 22, 1, 22)
|
||||
]);
|
||||
moveRight(editor, viewModel, false);
|
||||
moveRight(editor, viewModel, false);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 24, 1, 24),
|
||||
]);
|
||||
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(1, 22, 1, 22)
|
||||
]);
|
||||
moveRight(editor, viewModel, true);
|
||||
moveRight(editor, viewModel, true);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 22, 1, 24),
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #123178: sticky tab in consecutive wrapped lines', () => {
|
||||
const model = createTextModel(' aaaa aaaa', { tabSize: 4 });
|
||||
|
||||
withTestCodeEditor(
|
||||
null,
|
||||
{
|
||||
model: model,
|
||||
wordWrap: 'wordWrapColumn',
|
||||
wordWrapColumn: 8,
|
||||
stickyTabStops: true,
|
||||
},
|
||||
(editor, viewModel) => {
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(1, 9, 1, 9)
|
||||
]);
|
||||
moveRight(editor, viewModel, false);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 10, 1, 10),
|
||||
]);
|
||||
|
||||
moveLeft(editor, viewModel, false);
|
||||
assertCursor(viewModel, [
|
||||
new Selection(1, 9, 1, 9),
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Editor Controller - Cursor Configuration', () => {
|
||||
@@ -4299,6 +4479,29 @@ suite('Editor Controller - Indentation Rules', () => {
|
||||
assert.strictEqual(model.getValue(), ' let a,\n\t b,\n\t c;');
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #122714: tabSize=1 prevent typing a string matching decreaseIndentPattern in an empty file', () => {
|
||||
let latexMode = new IndentRulesMode({
|
||||
increaseIndentPattern: new RegExp('\\\\begin{(?!document)([^}]*)}(?!.*\\\\end{\\1})'),
|
||||
decreaseIndentPattern: new RegExp('^\\s*\\\\end{(?!document)')
|
||||
});
|
||||
let model = createTextModel(
|
||||
'\\end',
|
||||
{ tabSize: 1 },
|
||||
latexMode.getLanguageIdentifier()
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model, autoIndent: 'full' }, (editor, viewModel) => {
|
||||
moveTo(editor, viewModel, 1, 5, false);
|
||||
assertCursor(viewModel, new Selection(1, 5, 1, 5));
|
||||
|
||||
viewModel.type('{', 'keyboard');
|
||||
assert.strictEqual(model.getLineContent(1), '\\end{}');
|
||||
});
|
||||
|
||||
latexMode.dispose();
|
||||
model.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
interface ICursorOpts {
|
||||
@@ -6080,4 +6283,62 @@ suite('Undo stops', () => {
|
||||
assert.strictEqual(model.getValue(), 'hello world\nhello world');
|
||||
});
|
||||
});
|
||||
|
||||
test('there is a single undo stop for consecutive whitespaces', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
''
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: false,
|
||||
}
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, viewModel) => {
|
||||
viewModel.type('a', 'keyboard');
|
||||
viewModel.type('b', 'keyboard');
|
||||
viewModel.type(' ', 'keyboard');
|
||||
viewModel.type(' ', 'keyboard');
|
||||
viewModel.type('c', 'keyboard');
|
||||
viewModel.type('d', 'keyboard');
|
||||
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ab cd', 'assert1');
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ab ', 'assert2');
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ab', 'assert3');
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '', 'assert4');
|
||||
});
|
||||
});
|
||||
|
||||
test('there is no undo stop after a single whitespace', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
''
|
||||
].join('\n'),
|
||||
{
|
||||
insertSpaces: false,
|
||||
}
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, viewModel) => {
|
||||
viewModel.type('a', 'keyboard');
|
||||
viewModel.type('b', 'keyboard');
|
||||
viewModel.type(' ', 'keyboard');
|
||||
viewModel.type('c', 'keyboard');
|
||||
viewModel.type('d', 'keyboard');
|
||||
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ab cd', 'assert1');
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ab', 'assert3');
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.strictEqual(model.getValue(EndOfLinePreference.LF), '', 'assert4');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,9 +19,9 @@ export class TestCodeEditorService extends AbstractCodeEditorService {
|
||||
this.lastInput = input;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
public registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void { }
|
||||
public registerDecorationType(description: string, key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void { }
|
||||
public removeDecorationType(key: string): void { }
|
||||
public resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions { return {}; }
|
||||
public resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions { return { description: 'test' }; }
|
||||
public resolveDecorationCSSRules(decorationTypeKey: string): CSSRuleList | null { return null; }
|
||||
}
|
||||
|
||||
|
||||
@@ -59,12 +59,12 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
};
|
||||
test('register and resolve decoration type', () => {
|
||||
let s = new TestCodeEditorServiceImpl(null, themeServiceMock);
|
||||
s.registerDecorationType('example', options);
|
||||
s.registerDecorationType('test', 'example', options);
|
||||
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
|
||||
});
|
||||
test('remove decoration type', () => {
|
||||
let s = new TestCodeEditorServiceImpl(null, themeServiceMock);
|
||||
s.registerDecorationType('example', options);
|
||||
s.registerDecorationType('test', 'example', options);
|
||||
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
|
||||
s.removeDecorationType('example');
|
||||
assert.throws(() => s.resolveDecorationOptions('example', false));
|
||||
@@ -77,7 +77,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
test('css properties', () => {
|
||||
const styleSheet = new TestGlobalStyleSheet();
|
||||
const s = new TestCodeEditorServiceImpl(styleSheet, themeServiceMock);
|
||||
s.registerDecorationType('example', options);
|
||||
s.registerDecorationType('test', 'example', options);
|
||||
const sheet = readStyleSheet(styleSheet);
|
||||
assert(sheet.indexOf(`{background:url('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png') center center no-repeat;background-size:contain;}`) >= 0);
|
||||
assert(sheet.indexOf(`{background-color:red;border-color:yellow;box-sizing: border-box;}`) >= 0);
|
||||
@@ -94,7 +94,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
editorBackground: '#FF0000'
|
||||
}));
|
||||
const s = new TestCodeEditorServiceImpl(styleSheet, themeService);
|
||||
s.registerDecorationType('example', options);
|
||||
s.registerDecorationType('test', 'example', options);
|
||||
assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ff0000;border-color:transparent;box-sizing: border-box;}');
|
||||
|
||||
themeService.setTheme(new TestColorTheme({
|
||||
@@ -127,7 +127,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
infoForeground: '#444444'
|
||||
}));
|
||||
const s = new TestCodeEditorServiceImpl(styleSheet, themeService);
|
||||
s.registerDecorationType('example', options);
|
||||
s.registerDecorationType('test', 'example', options);
|
||||
const expected = [
|
||||
'.vs-dark.monaco-editor .ced-example-4::after, .hc-black.monaco-editor .ced-example-4::after {color:#444444 !important;}',
|
||||
'.vs-dark.monaco-editor .ced-example-1, .hc-black.monaco-editor .ced-example-1 {color:#000000 !important;}',
|
||||
@@ -145,7 +145,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
const s = new TestCodeEditorServiceImpl(styleSheet, themeServiceMock);
|
||||
|
||||
// URI, only minimal encoding
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.parse('data:image/svg+xml;base64,PHN2ZyB4b+') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.parse('data:image/svg+xml;base64,PHN2ZyB4b+') });
|
||||
assert(readStyleSheet(styleSheet).indexOf(`{background:url('data:image/svg+xml;base64,PHN2ZyB4b+') center center no-repeat;}`) > 0);
|
||||
s.removeDecorationType('example');
|
||||
|
||||
@@ -159,27 +159,27 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
|
||||
|
||||
if (platform.isWindows) {
|
||||
// windows file path (used as string)
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\miles\\more.png') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.file('c:\\files\\miles\\more.png') });
|
||||
assertBackground('file:///c:/files/miles/more.png', 'vscode-file://vscode-app/c:/files/miles/more.png');
|
||||
s.removeDecorationType('example');
|
||||
|
||||
// single quote must always be escaped/encoded
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\foo\\b\'ar.png') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.file('c:\\files\\foo\\b\'ar.png') });
|
||||
assertBackground('file:///c:/files/foo/b%27ar.png', 'vscode-file://vscode-app/c:/files/foo/b%27ar.png');
|
||||
s.removeDecorationType('example');
|
||||
} else {
|
||||
// unix file path (used as string)
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/bar.png') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.file('/Users/foo/bar.png') });
|
||||
assertBackground('file:///Users/foo/bar.png', 'vscode-file://vscode-app/Users/foo/bar.png');
|
||||
s.removeDecorationType('example');
|
||||
|
||||
// single quote must always be escaped/encoded
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/b\'ar.png') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.file('/Users/foo/b\'ar.png') });
|
||||
assertBackground('file:///Users/foo/b%27ar.png', 'vscode-file://vscode-app/Users/foo/b%27ar.png');
|
||||
s.removeDecorationType('example');
|
||||
}
|
||||
|
||||
s.registerDecorationType('example', { gutterIconPath: URI.parse('http://test/pa\'th') });
|
||||
s.registerDecorationType('test', 'example', { gutterIconPath: URI.parse('http://test/pa\'th') });
|
||||
assert(readStyleSheet(styleSheet).indexOf(`{background:url('http://test/pa%27th') center center no-repeat;}`) > 0);
|
||||
s.removeDecorationType('example');
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { OpenerService } from 'vs/editor/browser/services/openerService';
|
||||
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
|
||||
import { CommandsRegistry, ICommandService, NullCommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
|
||||
suite('OpenerService', function () {
|
||||
@@ -32,28 +33,28 @@ suite('OpenerService', function () {
|
||||
test('delegate to editorService, scheme:///fff', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
await openerService.open(URI.parse('another:///somepath'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection, undefined);
|
||||
});
|
||||
|
||||
test('delegate to editorService, scheme:///fff#L123', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
|
||||
await openerService.open(URI.parse('file:///somepath#L23'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.resource.fragment, '');
|
||||
|
||||
await openerService.open(URI.parse('another:///somepath#L23'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1);
|
||||
|
||||
await openerService.open(URI.parse('another:///somepath#L23,45'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 45);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 45);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.resource.fragment, '');
|
||||
});
|
||||
|
||||
@@ -61,17 +62,17 @@ suite('OpenerService', function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
|
||||
await openerService.open(URI.parse('file:///somepath#23'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.resource.fragment, '');
|
||||
|
||||
await openerService.open(URI.parse('file:///somepath#23,45'));
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 45);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 45);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined);
|
||||
assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined);
|
||||
assert.strictEqual(editorService.lastInput!.resource.fragment, '');
|
||||
});
|
||||
|
||||
@@ -125,33 +126,6 @@ suite('OpenerService', function () {
|
||||
assert.strictEqual(httpsResult, false);
|
||||
});
|
||||
|
||||
test('delegate to commandsService, command:someid', async function () {
|
||||
const openerService = new OpenerService(editorService, commandService);
|
||||
|
||||
const id = `aCommand${Math.random()}`;
|
||||
CommandsRegistry.registerCommand(id, function () { });
|
||||
|
||||
await openerService.open(URI.parse('command:' + id).with({ query: '\"123\"' }), { allowCommands: true });
|
||||
assert.strictEqual(lastCommand!.id, id);
|
||||
assert.strictEqual(lastCommand!.args.length, 1);
|
||||
assert.strictEqual(lastCommand!.args[0], '123');
|
||||
|
||||
await openerService.open(URI.parse('command:' + id), { allowCommands: true });
|
||||
assert.strictEqual(lastCommand!.id, id);
|
||||
assert.strictEqual(lastCommand!.args.length, 0);
|
||||
|
||||
await openerService.open(URI.parse('command:' + id).with({ query: '123' }), { allowCommands: true });
|
||||
assert.strictEqual(lastCommand!.id, id);
|
||||
assert.strictEqual(lastCommand!.args.length, 1);
|
||||
assert.strictEqual(lastCommand!.args[0], 123);
|
||||
|
||||
await openerService.open(URI.parse('command:' + id).with({ query: JSON.stringify([12, true]) }), { allowCommands: true });
|
||||
assert.strictEqual(lastCommand!.id, id);
|
||||
assert.strictEqual(lastCommand!.args.length, 2);
|
||||
assert.strictEqual(lastCommand!.args[0], 12);
|
||||
assert.strictEqual(lastCommand!.args[1], true);
|
||||
});
|
||||
|
||||
test('links validated by validators go to openers', async function () {
|
||||
const openerService = new OpenerService(editorService, commandService);
|
||||
|
||||
@@ -272,4 +246,25 @@ suite('OpenerService', function () {
|
||||
assert.ok(!matchesScheme(URI.parse('htt://microsoft.com'), 'http'));
|
||||
assert.ok(!matchesScheme(URI.parse('z://microsoft.com'), 'http'));
|
||||
});
|
||||
|
||||
test('resolveExternalUri', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
|
||||
try {
|
||||
await openerService.resolveExternalUri(URI.parse('file:///Users/user/folder'));
|
||||
assert.fail('Should not reach here');
|
||||
} catch {
|
||||
// OK
|
||||
}
|
||||
|
||||
const disposable = openerService.registerExternalUriResolver({
|
||||
async resolveExternalUri(uri) {
|
||||
return { resolved: uri, dispose() { } };
|
||||
}
|
||||
});
|
||||
|
||||
const result = await openerService.resolveExternalUri(URI.parse('file:///Users/user/folder'));
|
||||
assert.deepStrictEqual(result.resolved.toString(), 'file:///Users/user/folder');
|
||||
disposable.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
@@ -916,4 +916,55 @@ suite('Editor Diff - DiffComputer', () => {
|
||||
];
|
||||
assertDiff(original, modified, expected, false, false, false);
|
||||
});
|
||||
|
||||
test('issue #121436: Diff chunk contains an unchanged line part 1', () => {
|
||||
const original = [
|
||||
'if (cond) {',
|
||||
' cmd',
|
||||
'}',
|
||||
];
|
||||
const modified = [
|
||||
'if (cond) {',
|
||||
' if (other_cond) {',
|
||||
' cmd',
|
||||
' }',
|
||||
'}',
|
||||
];
|
||||
const expected = [
|
||||
createLineChange(
|
||||
1, 0, 2, 2
|
||||
),
|
||||
createLineChange(
|
||||
2, 0, 4, 4
|
||||
)
|
||||
];
|
||||
assertDiff(original, modified, expected, false, false, true);
|
||||
});
|
||||
|
||||
test('issue #121436: Diff chunk contains an unchanged line part 2', () => {
|
||||
const original = [
|
||||
'if (cond) {',
|
||||
' cmd',
|
||||
'}',
|
||||
];
|
||||
const modified = [
|
||||
'if (cond) {',
|
||||
' if (other_cond) {',
|
||||
' cmd',
|
||||
' }',
|
||||
'}',
|
||||
];
|
||||
const expected = [
|
||||
createLineChange(
|
||||
1, 0, 2, 2
|
||||
),
|
||||
createLineChange(
|
||||
2, 2, 3, 3
|
||||
),
|
||||
createLineChange(
|
||||
2, 0, 4, 4
|
||||
)
|
||||
];
|
||||
assertDiff(original, modified, expected, false, false, false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
require('../../../../../../bootstrap-amd').load('vs/editor/test/common/model/benchmark/entry');
|
||||
require('../../../../../../bootstrap-amd').load('vs/editor/test/common/model/benchmark/entry');
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
import 'vs/editor/test/common/model/benchmark/modelbuilder.benchmark';
|
||||
import 'vs/editor/test/common/model/benchmark/operations.benchmark';
|
||||
import 'vs/editor/test/common/model/benchmark/searchNReplace.benchmark';
|
||||
import 'vs/editor/test/common/model/benchmark/searchNReplace.benchmark';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
@@ -45,6 +45,7 @@ function modelHasNoDecorations(model: TextModel) {
|
||||
function addDecoration(model: TextModel, startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, className: string): string {
|
||||
return model.changeDecorations((changeAccessor) => {
|
||||
return changeAccessor.addDecoration(new Range(startLineNumber, startColumn, endLineNumber, endColumn), {
|
||||
description: 'test',
|
||||
className: className
|
||||
});
|
||||
})!;
|
||||
@@ -407,7 +408,7 @@ suite('Editor Model - Model Decorations', () => {
|
||||
});
|
||||
|
||||
test('removeAllDecorationsWithOwnerId works', () => {
|
||||
thisModel.deltaDecorations([], [{ range: new Range(1, 2, 4, 1), options: { className: 'myType1' } }], 1);
|
||||
thisModel.deltaDecorations([], [{ range: new Range(1, 2, 4, 1), options: { description: 'test', className: 'myType1' } }], 1);
|
||||
thisModel.removeAllDecorationsWithOwnerId(1);
|
||||
modelHasNoDecorations(thisModel);
|
||||
});
|
||||
@@ -422,7 +423,7 @@ suite('Decorations and editing', () => {
|
||||
'Third Line'
|
||||
].join('\n'));
|
||||
|
||||
const id = model.deltaDecorations([], [{ range: decRange, options: { stickiness: stickiness } }])[0];
|
||||
const id = model.deltaDecorations([], [{ range: decRange, options: { description: 'test', stickiness: stickiness } }])[0];
|
||||
model.applyEdits([{
|
||||
range: editRange,
|
||||
text: editText,
|
||||
@@ -1123,6 +1124,7 @@ suite('deltaDecorations', () => {
|
||||
return {
|
||||
range: dec.range,
|
||||
options: {
|
||||
description: 'test',
|
||||
className: dec.id
|
||||
}
|
||||
};
|
||||
@@ -1276,6 +1278,7 @@ suite('deltaDecorations', () => {
|
||||
endColumn: 1
|
||||
},
|
||||
options: {
|
||||
description: 'test',
|
||||
hoverMessage: { value: 'hello1' }
|
||||
}
|
||||
}]);
|
||||
@@ -1288,6 +1291,7 @@ suite('deltaDecorations', () => {
|
||||
endColumn: 1
|
||||
},
|
||||
options: {
|
||||
description: 'test',
|
||||
hoverMessage: { value: 'hello2' }
|
||||
}
|
||||
}]);
|
||||
@@ -1312,9 +1316,11 @@ suite('deltaDecorations', () => {
|
||||
startColumn: 1,
|
||||
endLineNumber: 1,
|
||||
endColumn: 1
|
||||
}, {
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges
|
||||
}
|
||||
},
|
||||
{
|
||||
description: 'test',
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges
|
||||
}
|
||||
);
|
||||
});
|
||||
model.changeDecorations((changeAccessor) => {
|
||||
@@ -1349,16 +1355,16 @@ suite('deltaDecorations', () => {
|
||||
].join('\n'));
|
||||
|
||||
model.deltaDecorations([], [
|
||||
{ range: new Range(1, 1, 1, 1), options: { className: '1' } },
|
||||
{ range: new Range(1, 13, 1, 13), options: { className: '2' } },
|
||||
{ range: new Range(2, 1, 2, 1), options: { className: '3' } },
|
||||
{ range: new Range(2, 1, 2, 4), options: { className: '4' } },
|
||||
{ range: new Range(2, 8, 2, 13), options: { className: '5' } },
|
||||
{ range: new Range(3, 1, 4, 6), options: { className: '6' } },
|
||||
{ range: new Range(1, 1, 3, 6), options: { className: 'x1' } },
|
||||
{ range: new Range(2, 5, 2, 8), options: { className: 'x2' } },
|
||||
{ range: new Range(1, 1, 2, 8), options: { className: 'x3' } },
|
||||
{ range: new Range(2, 5, 3, 1), options: { className: 'x4' } },
|
||||
{ range: new Range(1, 1, 1, 1), options: { description: 'test', className: '1' } },
|
||||
{ range: new Range(1, 13, 1, 13), options: { description: 'test', className: '2' } },
|
||||
{ range: new Range(2, 1, 2, 1), options: { description: 'test', className: '3' } },
|
||||
{ range: new Range(2, 1, 2, 4), options: { description: 'test', className: '4' } },
|
||||
{ range: new Range(2, 8, 2, 13), options: { description: 'test', className: '5' } },
|
||||
{ range: new Range(3, 1, 4, 6), options: { description: 'test', className: '6' } },
|
||||
{ range: new Range(1, 1, 3, 6), options: { description: 'test', className: 'x1' } },
|
||||
{ range: new Range(2, 5, 2, 8), options: { description: 'test', className: 'x2' } },
|
||||
{ range: new Range(1, 1, 2, 8), options: { description: 'test', className: 'x3' } },
|
||||
{ range: new Range(2, 5, 3, 1), options: { description: 'test', className: 'x4' } },
|
||||
]);
|
||||
|
||||
let inRange = model.getDecorationsInRange(new Range(2, 6, 2, 6));
|
||||
@@ -1376,7 +1382,7 @@ suite('deltaDecorations', () => {
|
||||
'My First Line'
|
||||
].join('\n'));
|
||||
|
||||
const id = model.deltaDecorations([], [{ range: new Range(1, 2, 1, 14), options: { stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, collapseOnReplaceEdit: true } }])[0];
|
||||
const id = model.deltaDecorations([], [{ range: new Range(1, 2, 1, 14), options: { description: 'test', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, collapseOnReplaceEdit: true } }])[0];
|
||||
model.applyEdits([{
|
||||
range: new Range(1, 1, 1, 14),
|
||||
text: 'Some new text that is longer than the previous one',
|
||||
|
||||
@@ -230,4 +230,25 @@ suite('Editor Modes - Link Computer', () => {
|
||||
' http://tree-mark.chips.jp/レーズン&ベリーミックス '
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #121438: Link detection stops at【...】', () => {
|
||||
assertLink(
|
||||
'aa https://zh.wikipedia.org/wiki/【我推的孩子】 aa',
|
||||
' https://zh.wikipedia.org/wiki/【我推的孩子】 '
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #121438: Link detection stops at《...》', () => {
|
||||
assertLink(
|
||||
'aa https://zh.wikipedia.org/wiki/《新青年》编辑部旧址 aa',
|
||||
' https://zh.wikipedia.org/wiki/《新青年》编辑部旧址 '
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #121438: Link detection stops at “...”', () => {
|
||||
assertLink(
|
||||
'aa https://zh.wikipedia.org/wiki/“常凯申”误译事件 aa',
|
||||
' https://zh.wikipedia.org/wiki/“常凯申”误译事件 '
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,6 +47,40 @@ suite('OnEnter', () => {
|
||||
testIndentAction('begin', '', IndentAction.Indent);
|
||||
});
|
||||
|
||||
|
||||
test('Issue #121125: onEnterRules with global modifier', () => {
|
||||
const support = new OnEnterSupport({
|
||||
onEnterRules: [
|
||||
{
|
||||
action: {
|
||||
appendText: '/// ',
|
||||
indentAction: IndentAction.Outdent
|
||||
},
|
||||
beforeText: /^\s*\/{3}.*$/gm
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let testIndentAction = (previousLineText: string, beforeText: string, afterText: string, expectedIndentAction: IndentAction | null, expectedAppendText: string | null, removeText: number = 0) => {
|
||||
let actual = support.onEnter(EditorAutoIndentStrategy.Advanced, previousLineText, beforeText, afterText);
|
||||
if (expectedIndentAction === null) {
|
||||
assert.strictEqual(actual, null, 'isNull:' + beforeText);
|
||||
} else {
|
||||
assert.strictEqual(actual !== null, true, 'isNotNull:' + beforeText);
|
||||
assert.strictEqual(actual!.indentAction, expectedIndentAction, 'indentAction:' + beforeText);
|
||||
if (expectedAppendText !== null) {
|
||||
assert.strictEqual(actual!.appendText, expectedAppendText, 'appendText:' + beforeText);
|
||||
}
|
||||
if (removeText !== 0) {
|
||||
assert.strictEqual(actual!.removeText, removeText, 'removeText:' + beforeText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
testIndentAction('/// line', '/// line', '', IndentAction.Outdent, '/// ');
|
||||
testIndentAction('/// line', '/// line', '', IndentAction.Outdent, '/// ');
|
||||
});
|
||||
|
||||
test('uses regExpRules', () => {
|
||||
let support = new OnEnterSupport({
|
||||
onEnterRules: javascriptOnEnterRules
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as strings from 'vs/base/common/strings';
|
||||
import { IViewLineTokens } from 'vs/editor/common/core/lineTokens';
|
||||
import { MetadataConsts } from 'vs/editor/common/modes';
|
||||
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
|
||||
import { CharacterMapping, RenderLineInput, renderViewLine2 as renderViewLine, LineRange } from 'vs/editor/common/viewLayout/viewLineRenderer';
|
||||
import { CharacterMapping, RenderLineInput, renderViewLine2 as renderViewLine, LineRange, DomPosition } from 'vs/editor/common/viewLayout/viewLineRenderer';
|
||||
import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ViewLineToken, ViewLineTokens } from 'vs/editor/test/common/core/viewLineToken';
|
||||
|
||||
@@ -25,8 +25,8 @@ function createPart(endIndex: number, foreground: number): ViewLineToken {
|
||||
|
||||
suite('viewLineRenderer.renderLine', () => {
|
||||
|
||||
function assertCharacterReplacement(lineContent: string, tabSize: number, expected: string, expectedCharOffsetInPart: number[][], expectedPartLengts: number[]): void {
|
||||
let _actual = renderViewLine(new RenderLineInput(
|
||||
function assertCharacterReplacement(lineContent: string, tabSize: number, expected: string, expectedCharOffsetInPart: number[]): void {
|
||||
const _actual = renderViewLine(new RenderLineInput(
|
||||
false,
|
||||
true,
|
||||
lineContent,
|
||||
@@ -49,36 +49,37 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
));
|
||||
|
||||
assert.strictEqual(_actual.html, '<span><span class="mtk0">' + expected + '</span></span>');
|
||||
assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart, expectedPartLengts);
|
||||
const info = expectedCharOffsetInPart.map<CharacterMappingInfo>((absoluteOffset) => [absoluteOffset, [0, absoluteOffset]]);
|
||||
assertCharacterMapping3(_actual.characterMapping, info);
|
||||
}
|
||||
|
||||
test('replaces spaces', () => {
|
||||
assertCharacterReplacement(' ', 4, '\u00a0', [[0, 1]], [1]);
|
||||
assertCharacterReplacement(' ', 4, '\u00a0\u00a0', [[0, 1, 2]], [2]);
|
||||
assertCharacterReplacement('a b', 4, 'a\u00a0\u00a0b', [[0, 1, 2, 3, 4]], [4]);
|
||||
assertCharacterReplacement(' ', 4, '\u00a0', [0, 1]);
|
||||
assertCharacterReplacement(' ', 4, '\u00a0\u00a0', [0, 1, 2]);
|
||||
assertCharacterReplacement('a b', 4, 'a\u00a0\u00a0b', [0, 1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
test('escapes HTML markup', () => {
|
||||
assertCharacterReplacement('a<b', 4, 'a<b', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a>b', 4, 'a>b', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a&b', 4, 'a&b', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a<b', 4, 'a<b', [0, 1, 2, 3]);
|
||||
assertCharacterReplacement('a>b', 4, 'a>b', [0, 1, 2, 3]);
|
||||
assertCharacterReplacement('a&b', 4, 'a&b', [0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
test('replaces some bad characters', () => {
|
||||
assertCharacterReplacement('a\0b', 4, 'a�b', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a' + String.fromCharCode(CharCode.UTF8_BOM) + 'b', 4, 'a\ufffdb', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a\u2028b', 4, 'a\ufffdb', [[0, 1, 2, 3]], [3]);
|
||||
assertCharacterReplacement('a\0b', 4, 'a�b', [0, 1, 2, 3]);
|
||||
assertCharacterReplacement('a' + String.fromCharCode(CharCode.UTF8_BOM) + 'b', 4, 'a\ufffdb', [0, 1, 2, 3]);
|
||||
assertCharacterReplacement('a\u2028b', 4, 'a\ufffdb', [0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
test('handles tabs', () => {
|
||||
assertCharacterReplacement('\t', 4, '\u00a0\u00a0\u00a0\u00a0', [[0, 4]], [4]);
|
||||
assertCharacterReplacement('x\t', 4, 'x\u00a0\u00a0\u00a0', [[0, 1, 4]], [4]);
|
||||
assertCharacterReplacement('xx\t', 4, 'xx\u00a0\u00a0', [[0, 1, 2, 4]], [4]);
|
||||
assertCharacterReplacement('xxx\t', 4, 'xxx\u00a0', [[0, 1, 2, 3, 4]], [4]);
|
||||
assertCharacterReplacement('xxxx\t', 4, 'xxxx\u00a0\u00a0\u00a0\u00a0', [[0, 1, 2, 3, 4, 8]], [8]);
|
||||
assertCharacterReplacement('\t', 4, '\u00a0\u00a0\u00a0\u00a0', [0, 4]);
|
||||
assertCharacterReplacement('x\t', 4, 'x\u00a0\u00a0\u00a0', [0, 1, 4]);
|
||||
assertCharacterReplacement('xx\t', 4, 'xx\u00a0\u00a0', [0, 1, 2, 4]);
|
||||
assertCharacterReplacement('xxx\t', 4, 'xxx\u00a0', [0, 1, 2, 3, 4]);
|
||||
assertCharacterReplacement('xxxx\t', 4, 'xxxx\u00a0\u00a0\u00a0\u00a0', [0, 1, 2, 3, 4, 8]);
|
||||
});
|
||||
|
||||
function assertParts(lineContent: string, tabSize: number, parts: ViewLineToken[], expected: string, expectedCharOffsetInPart: number[][], expectedPartLengts: number[]): void {
|
||||
function assertParts(lineContent: string, tabSize: number, parts: ViewLineToken[], expected: string, info: CharacterMappingInfo[]): void {
|
||||
let _actual = renderViewLine(new RenderLineInput(
|
||||
false,
|
||||
true,
|
||||
@@ -102,23 +103,23 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
));
|
||||
|
||||
assert.strictEqual(_actual.html, '<span>' + expected + '</span>');
|
||||
assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart, expectedPartLengts);
|
||||
assertCharacterMapping3(_actual.characterMapping, info);
|
||||
}
|
||||
|
||||
test('empty line', () => {
|
||||
assertParts('', 4, [], '<span></span>', [], []);
|
||||
assertParts('', 4, [], '<span></span>', []);
|
||||
});
|
||||
|
||||
test('uses part type', () => {
|
||||
assertParts('x', 4, [createPart(1, 10)], '<span class="mtk10">x</span>', [[0, 1]], [1]);
|
||||
assertParts('x', 4, [createPart(1, 20)], '<span class="mtk20">x</span>', [[0, 1]], [1]);
|
||||
assertParts('x', 4, [createPart(1, 30)], '<span class="mtk30">x</span>', [[0, 1]], [1]);
|
||||
assertParts('x', 4, [createPart(1, 10)], '<span class="mtk10">x</span>', [[0, [0, 0]], [1, [0, 1]]]);
|
||||
assertParts('x', 4, [createPart(1, 20)], '<span class="mtk20">x</span>', [[0, [0, 0]], [1, [0, 1]]]);
|
||||
assertParts('x', 4, [createPart(1, 30)], '<span class="mtk30">x</span>', [[0, [0, 0]], [1, [0, 1]]]);
|
||||
});
|
||||
|
||||
test('two parts', () => {
|
||||
assertParts('xy', 4, [createPart(1, 1), createPart(2, 2)], '<span class="mtk1">x</span><span class="mtk2">y</span>', [[0], [0, 1]], [1, 1]);
|
||||
assertParts('xyz', 4, [createPart(1, 1), createPart(3, 2)], '<span class="mtk1">x</span><span class="mtk2">yz</span>', [[0], [0, 1, 2]], [1, 2]);
|
||||
assertParts('xyz', 4, [createPart(2, 1), createPart(3, 2)], '<span class="mtk1">xy</span><span class="mtk2">z</span>', [[0, 1], [0, 1]], [2, 1]);
|
||||
assertParts('xy', 4, [createPart(1, 1), createPart(2, 2)], '<span class="mtk1">x</span><span class="mtk2">y</span>', [[0, [0, 0]], [1, [1, 0]], [2, [1, 1]]]);
|
||||
assertParts('xyz', 4, [createPart(1, 1), createPart(3, 2)], '<span class="mtk1">x</span><span class="mtk2">yz</span>', [[0, [0, 0]], [1, [1, 0]], [2, [1, 1]], [3, [1, 2]]]);
|
||||
assertParts('xyz', 4, [createPart(2, 1), createPart(3, 2)], '<span class="mtk1">xy</span><span class="mtk2">z</span>', [[0, [0, 0]], [1, [0, 1]], [2, [1, 0]], [3, [1, 1]]]);
|
||||
});
|
||||
|
||||
test('overflow', () => {
|
||||
@@ -168,16 +169,17 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
].join('');
|
||||
|
||||
assert.strictEqual(_actual.html, '<span>' + expectedOutput + '</span>');
|
||||
assertCharacterMapping(_actual.characterMapping,
|
||||
assertCharacterMapping3(
|
||||
_actual.characterMapping,
|
||||
[
|
||||
[0],
|
||||
[0],
|
||||
[0],
|
||||
[0],
|
||||
[0],
|
||||
[0, 1],
|
||||
],
|
||||
[1, 1, 1, 1, 1, 1]
|
||||
[0, [0, 0]],
|
||||
[1, [1, 0]],
|
||||
[2, [2, 0]],
|
||||
[3, [3, 0]],
|
||||
[4, [4, 0]],
|
||||
[5, [5, 0]],
|
||||
[6, [5, 1]],
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -213,24 +215,25 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
'<span class="mtkz" style="width:20px">\u00b7\u00b7</span>',
|
||||
'<span class="mtkz" style="width:30px">\u00b7\u00b7\u00b7</span>'
|
||||
].join('');
|
||||
let expectedOffsetsArr = [
|
||||
[0],
|
||||
[0, 1, 2, 3],
|
||||
[0, 1, 2, 3, 4, 5],
|
||||
[0],
|
||||
[0, 1, 2, 3, 4],
|
||||
[0],
|
||||
[0, 1, 2, 3],
|
||||
[0],
|
||||
[0],
|
||||
[0],
|
||||
[0, 1, 2],
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
|
||||
[0, 1],
|
||||
[0, 1, 2, 3],
|
||||
|
||||
const info: CharacterMappingInfo[] = [
|
||||
[0, [0, 0]],
|
||||
[4, [1, 0]], [5, [1, 1]], [6, [1, 2]], [7, [1, 3]],
|
||||
[8, [2, 0]], [9, [2, 1]], [10, [2, 2]], [11, [2, 3]], [12, [2, 4]], [13, [2, 5]],
|
||||
[14, [3, 0]],
|
||||
[15, [4, 0]], [16, [4, 1]], [17, [4, 2]], [18, [4, 3]], [19, [4, 4]],
|
||||
[20, [5, 0]],
|
||||
[21, [6, 0]], [22, [6, 1]], [23, [6, 2]], [24, [6, 3]],
|
||||
[25, [7, 0]],
|
||||
[26, [8, 0]],
|
||||
[27, [9, 0]],
|
||||
[28, [10, 0]], [29, [10, 1]], [30, [10, 2]],
|
||||
[31, [11, 0]], [32, [11, 1]], [33, [11, 2]], [34, [11, 3]], [35, [11, 4]], [36, [11, 5]], [37, [11, 6]], [38, [11, 7]], [39, [11, 8]], [40, [11, 9]], [41, [11, 10]], [42, [11, 11]], [43, [11, 12]], [44, [11, 13]], [45, [11, 14]],
|
||||
[46, [12, 0]], [47, [12, 1]],
|
||||
[48, [13, 0]], [49, [13, 1]], [50, [13, 2]], [51, [13, 3]],
|
||||
];
|
||||
|
||||
let _actual = renderViewLine(new RenderLineInput(
|
||||
const _actual = renderViewLine(new RenderLineInput(
|
||||
false,
|
||||
true,
|
||||
lineText,
|
||||
@@ -253,7 +256,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
));
|
||||
|
||||
assert.strictEqual(_actual.html, '<span>' + expectedOutput + '</span>');
|
||||
assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [4, 4, 6, 1, 5, 1, 4, 1, 1, 1, 3, 15, 2, 3]);
|
||||
assertCharacterMapping3(_actual.characterMapping, info);
|
||||
});
|
||||
|
||||
test('issue #2255: Weird line rendering part 1', () => {
|
||||
@@ -283,20 +286,21 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
'<span class="mtk9">)</span>',
|
||||
'<span class="mtk10">,</span>',
|
||||
].join('');
|
||||
let expectedOffsetsArr = [
|
||||
[0, 4, 8], // 3 chars
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // 12 chars
|
||||
[0, 4, 8, 12, 16, 20], // 6 chars
|
||||
[0], // 1 char
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], // 21 chars
|
||||
[0, 1], // 2 chars
|
||||
[0], // 1 char
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], // 20 chars
|
||||
[0], // 1 char
|
||||
[0, 1] // 2 chars
|
||||
|
||||
const info: CharacterMappingInfo[] = [
|
||||
[0, [0, 0]], [4, [0, 4]], [8, [0, 8]],
|
||||
[12, [1, 0]], [13, [1, 1]], [14, [1, 2]], [15, [1, 3]], [16, [1, 4]], [17, [1, 5]], [18, [1, 6]], [19, [1, 7]], [20, [1, 8]], [21, [1, 9]], [22, [1, 10]], [23, [1, 11]],
|
||||
[24, [2, 0]], [28, [2, 4]], [32, [2, 8]], [36, [2, 12]], [40, [2, 16]], [44, [2, 20]],
|
||||
[48, [3, 0]],
|
||||
[49, [4, 0]], [50, [4, 1]], [51, [4, 2]], [52, [4, 3]], [53, [4, 4]], [54, [4, 5]], [55, [4, 6]], [56, [4, 7]], [57, [4, 8]], [58, [4, 9]], [59, [4, 10]], [60, [4, 11]], [61, [4, 12]], [62, [4, 13]], [63, [4, 14]], [64, [4, 15]], [65, [4, 16]], [66, [4, 17]], [67, [4, 18]], [68, [4, 19]], [69, [4, 20]],
|
||||
[70, [5, 0]], [71, [5, 1]],
|
||||
[72, [6, 0]],
|
||||
[73, [7, 0]], [74, [7, 1]], [75, [7, 2]], [76, [7, 3]], [77, [7, 4]], [78, [7, 5]], [79, [7, 6]], [80, [7, 7]], [81, [7, 8]], [82, [7, 9]], [83, [7, 10]], [84, [7, 11]], [85, [7, 12]], [86, [7, 13]], [87, [7, 14]], [88, [7, 15]], [89, [7, 16]], [90, [7, 17]], [91, [7, 18]], [92, [7, 19]],
|
||||
[93, [8, 0]],
|
||||
[94, [9, 0]], [95, [9, 1]],
|
||||
];
|
||||
|
||||
let _actual = renderViewLine(new RenderLineInput(
|
||||
const _actual = renderViewLine(new RenderLineInput(
|
||||
false,
|
||||
true,
|
||||
lineText,
|
||||
@@ -319,7 +323,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
));
|
||||
|
||||
assert.strictEqual(_actual.html, '<span>' + expectedOutput + '</span>');
|
||||
assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]);
|
||||
assertCharacterMapping3(_actual.characterMapping, info);
|
||||
});
|
||||
|
||||
test('issue #2255: Weird line rendering part 2', () => {
|
||||
@@ -349,20 +353,21 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
'<span class="mtk9">)</span>',
|
||||
'<span class="mtk10">,</span>',
|
||||
].join('');
|
||||
let expectedOffsetsArr = [
|
||||
[0, 1, 4, 8], // 4 chars
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // 12 chars
|
||||
[0, 4, 8, 12, 16, 20], // 6 chars
|
||||
[0], // 1 char
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], // 21 chars
|
||||
[0, 1], // 2 chars
|
||||
[0], // 1 char
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], // 20 chars
|
||||
[0], // 1 char
|
||||
[0, 1] // 2 chars
|
||||
|
||||
const info: CharacterMappingInfo[] = [
|
||||
[0, [0, 0]], [1, [0, 1]], [4, [0, 4]], [8, [0, 8]],
|
||||
[12, [1, 0]], [13, [1, 1]], [14, [1, 2]], [15, [1, 3]], [16, [1, 4]], [17, [1, 5]], [18, [1, 6]], [19, [1, 7]], [20, [1, 8]], [21, [1, 9]], [22, [1, 10]], [23, [1, 11]],
|
||||
[24, [2, 0]], [28, [2, 4]], [32, [2, 8]], [36, [2, 12]], [40, [2, 16]], [44, [2, 20]],
|
||||
[48, [3, 0]],
|
||||
[49, [4, 0]], [50, [4, 1]], [51, [4, 2]], [52, [4, 3]], [53, [4, 4]], [54, [4, 5]], [55, [4, 6]], [56, [4, 7]], [57, [4, 8]], [58, [4, 9]], [59, [4, 10]], [60, [4, 11]], [61, [4, 12]], [62, [4, 13]], [63, [4, 14]], [64, [4, 15]], [65, [4, 16]], [66, [4, 17]], [67, [4, 18]], [68, [4, 19]], [69, [4, 20]],
|
||||
[70, [5, 0]], [71, [5, 1]],
|
||||
[72, [6, 0]],
|
||||
[73, [7, 0]], [74, [7, 1]], [75, [7, 2]], [76, [7, 3]], [77, [7, 4]], [78, [7, 5]], [79, [7, 6]], [80, [7, 7]], [81, [7, 8]], [82, [7, 9]], [83, [7, 10]], [84, [7, 11]], [85, [7, 12]], [86, [7, 13]], [87, [7, 14]], [88, [7, 15]], [89, [7, 16]], [90, [7, 17]], [91, [7, 18]], [92, [7, 19]],
|
||||
[93, [8, 0]],
|
||||
[94, [9, 0]], [95, [9, 1]],
|
||||
];
|
||||
|
||||
let _actual = renderViewLine(new RenderLineInput(
|
||||
const _actual = renderViewLine(new RenderLineInput(
|
||||
false,
|
||||
true,
|
||||
lineText,
|
||||
@@ -385,7 +390,7 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
));
|
||||
|
||||
assert.strictEqual(_actual.html, '<span>' + expectedOutput + '</span>');
|
||||
assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]);
|
||||
assertCharacterMapping3(_actual.characterMapping, info);
|
||||
});
|
||||
|
||||
test('issue #91178: after decoration type shown before cursor', () => {
|
||||
@@ -401,23 +406,23 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
].join('');
|
||||
|
||||
const expectedCharacterMapping = new CharacterMapping(17, 4);
|
||||
expectedCharacterMapping.setPartData(0, 0, 0, 0);
|
||||
expectedCharacterMapping.setPartData(1, 0, 1, 0);
|
||||
expectedCharacterMapping.setPartData(2, 0, 2, 0);
|
||||
expectedCharacterMapping.setPartData(3, 0, 3, 0);
|
||||
expectedCharacterMapping.setPartData(4, 0, 4, 0);
|
||||
expectedCharacterMapping.setPartData(5, 0, 5, 0);
|
||||
expectedCharacterMapping.setPartData(6, 0, 6, 0);
|
||||
expectedCharacterMapping.setPartData(7, 0, 7, 0);
|
||||
expectedCharacterMapping.setPartData(8, 0, 8, 0);
|
||||
expectedCharacterMapping.setPartData(9, 0, 9, 0);
|
||||
expectedCharacterMapping.setPartData(10, 0, 10, 0);
|
||||
expectedCharacterMapping.setPartData(11, 0, 11, 0);
|
||||
expectedCharacterMapping.setPartData(12, 2, 0, 12);
|
||||
expectedCharacterMapping.setPartData(13, 3, 1, 12);
|
||||
expectedCharacterMapping.setPartData(14, 3, 2, 12);
|
||||
expectedCharacterMapping.setPartData(15, 3, 3, 12);
|
||||
expectedCharacterMapping.setPartData(16, 3, 4, 12);
|
||||
expectedCharacterMapping.setColumnInfo(1, 0, 0, 0);
|
||||
expectedCharacterMapping.setColumnInfo(2, 0, 1, 0);
|
||||
expectedCharacterMapping.setColumnInfo(3, 0, 2, 0);
|
||||
expectedCharacterMapping.setColumnInfo(4, 0, 3, 0);
|
||||
expectedCharacterMapping.setColumnInfo(5, 0, 4, 0);
|
||||
expectedCharacterMapping.setColumnInfo(6, 0, 5, 0);
|
||||
expectedCharacterMapping.setColumnInfo(7, 0, 6, 0);
|
||||
expectedCharacterMapping.setColumnInfo(8, 0, 7, 0);
|
||||
expectedCharacterMapping.setColumnInfo(9, 0, 8, 0);
|
||||
expectedCharacterMapping.setColumnInfo(10, 0, 9, 0);
|
||||
expectedCharacterMapping.setColumnInfo(11, 0, 10, 0);
|
||||
expectedCharacterMapping.setColumnInfo(12, 0, 11, 0);
|
||||
expectedCharacterMapping.setColumnInfo(13, 2, 0, 12);
|
||||
expectedCharacterMapping.setColumnInfo(14, 3, 1, 12);
|
||||
expectedCharacterMapping.setColumnInfo(15, 3, 2, 12);
|
||||
expectedCharacterMapping.setColumnInfo(16, 3, 3, 12);
|
||||
expectedCharacterMapping.setColumnInfo(17, 3, 4, 12);
|
||||
|
||||
const actual = renderViewLine(new RenderLineInput(
|
||||
true,
|
||||
@@ -792,14 +797,12 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
function decodeCharacterMapping(source: CharacterMapping) {
|
||||
const mapping: ICharMappingData[] = [];
|
||||
for (let charOffset = 0; charOffset < source.length; charOffset++) {
|
||||
const partData = source.charOffsetToPartData(charOffset);
|
||||
const partIndex = CharacterMapping.getPartIndex(partData);
|
||||
const charIndex = CharacterMapping.getCharIndex(partData);
|
||||
mapping.push({ charOffset, partIndex, charIndex });
|
||||
const domPosition = source.getDomPosition(charOffset + 1);
|
||||
mapping.push({ charOffset, partIndex: domPosition.partIndex, charIndex: domPosition.charIndex });
|
||||
}
|
||||
const absoluteOffsets: number[] = [];
|
||||
for (const absoluteOffset of source.getAbsoluteOffsets()) {
|
||||
absoluteOffsets.push(absoluteOffset);
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
absoluteOffsets[i] = source.getAbsoluteOffset(i + 1);
|
||||
}
|
||||
return { mapping, absoluteOffsets };
|
||||
}
|
||||
@@ -809,64 +812,37 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
const _expected = decodeCharacterMapping(expected);
|
||||
assert.deepStrictEqual(_actual, _expected);
|
||||
}
|
||||
|
||||
function assertCharacterMapping(actual: CharacterMapping, expectedCharPartOffsets: number[][], expectedPartLengths: number[]): void {
|
||||
|
||||
assertCharPartOffsets(actual, expectedCharPartOffsets);
|
||||
|
||||
let expectedCharAbsoluteOffset: number[] = [], currentPartAbsoluteOffset = 0;
|
||||
for (let partIndex = 0; partIndex < expectedCharPartOffsets.length; partIndex++) {
|
||||
const part = expectedCharPartOffsets[partIndex];
|
||||
|
||||
for (const charIndex of part) {
|
||||
expectedCharAbsoluteOffset.push(currentPartAbsoluteOffset + charIndex);
|
||||
}
|
||||
|
||||
currentPartAbsoluteOffset += expectedPartLengths[partIndex];
|
||||
}
|
||||
|
||||
let actualCharOffset: number[] = [];
|
||||
let tmp = actual.getAbsoluteOffsets();
|
||||
for (let i = 0; i < tmp.length; i++) {
|
||||
actualCharOffset[i] = tmp[i];
|
||||
}
|
||||
assert.deepStrictEqual(actualCharOffset, expectedCharAbsoluteOffset);
|
||||
}
|
||||
|
||||
function assertCharPartOffsets(actual: CharacterMapping, expected: number[][]): void {
|
||||
|
||||
let charOffset = 0;
|
||||
for (let partIndex = 0; partIndex < expected.length; partIndex++) {
|
||||
let part = expected[partIndex];
|
||||
for (const charIndex of part) {
|
||||
// here
|
||||
let _actualPartData = actual.charOffsetToPartData(charOffset);
|
||||
let actualPartIndex = CharacterMapping.getPartIndex(_actualPartData);
|
||||
let actualCharIndex = CharacterMapping.getCharIndex(_actualPartData);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
{ partIndex: actualPartIndex, charIndex: actualCharIndex },
|
||||
{ partIndex: partIndex, charIndex: charIndex },
|
||||
`character mapping for offset ${charOffset}`
|
||||
);
|
||||
|
||||
// here
|
||||
let actualOffset = actual.partDataToCharOffset(partIndex, part[part.length - 1] + 1, charIndex);
|
||||
|
||||
assert.strictEqual(
|
||||
actualOffset,
|
||||
charOffset,
|
||||
`character mapping for part ${partIndex}, ${charIndex}`
|
||||
);
|
||||
|
||||
charOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
assert.strictEqual(actual.length, charOffset);
|
||||
}
|
||||
});
|
||||
|
||||
type CharacterMappingInfo = [number, [number, number]];
|
||||
|
||||
function assertCharacterMapping3(actual: CharacterMapping, expectedInfo: CharacterMappingInfo[]): void {
|
||||
for (let i = 0; i < expectedInfo.length; i++) {
|
||||
const [absoluteOffset, [partIndex, charIndex]] = expectedInfo[i];
|
||||
|
||||
const actualDomPosition = actual.getDomPosition(i + 1);
|
||||
assert.deepStrictEqual(actualDomPosition, new DomPosition(partIndex, charIndex), `getDomPosition(${i + 1})`);
|
||||
|
||||
let partLength = charIndex + 1;
|
||||
for (let j = i + 1; j < expectedInfo.length; j++) {
|
||||
const [, [nextPartIndex, nextCharIndex]] = expectedInfo[j];
|
||||
if (nextPartIndex === partIndex) {
|
||||
partLength = nextCharIndex + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const actualColumn = actual.getColumn(new DomPosition(partIndex, charIndex), partLength);
|
||||
assert.strictEqual(actualColumn, i + 1, `actual.getColumn(${partIndex}, ${charIndex})`);
|
||||
|
||||
const actualAbsoluteOffset = actual.getAbsoluteOffset(i + 1);
|
||||
assert.strictEqual(actualAbsoluteOffset, absoluteOffset, `actual.getAbsoluteOffset(${i + 1})`);
|
||||
}
|
||||
|
||||
assert.strictEqual(actual.length, expectedInfo.length, `length mismatch`);
|
||||
}
|
||||
|
||||
suite('viewLineRenderer.renderLine 2', () => {
|
||||
|
||||
function testCreateLineParts(fontIsMonospace: boolean, lineContent: string, tokens: ViewLineToken[], fauxIndentLength: number, renderWhitespace: 'none' | 'boundary' | 'selection' | 'trailing' | 'all', selections: LineRange[] | null, expected: string): void {
|
||||
@@ -1739,7 +1715,7 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
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 class="ced-TextEditorDecorationType2-5e9b9b3f-3 ced-TextEditorDecorationType2-3"></span><span class="ced-TextEditorDecorationType2-5e9b9b3f-4 ced-TextEditorDecorationType2-4"></span>',
|
||||
'</span>'
|
||||
].join('');
|
||||
|
||||
@@ -2138,6 +2114,53 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
assert.deepStrictEqual(actual.html, expected);
|
||||
});
|
||||
|
||||
test('issue #124038: Multiple end-of-line text decorations get merged', () => {
|
||||
const actual = renderViewLine(new RenderLineInput(
|
||||
true,
|
||||
false,
|
||||
' if',
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
createViewLineTokens([createPart(4, 1), createPart(6, 2)]),
|
||||
[
|
||||
new LineDecoration(7, 7, 'ced-1-TextEditorDecorationType2-17c14d98-3 ced-1-TextEditorDecorationType2-3', InlineDecorationType.Before),
|
||||
new LineDecoration(7, 7, 'ced-1-TextEditorDecorationType2-17c14d98-4 ced-1-TextEditorDecorationType2-4', InlineDecorationType.After),
|
||||
new LineDecoration(7, 7, 'ced-ghost-text-1-4', InlineDecorationType.After),
|
||||
],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10000,
|
||||
'all',
|
||||
false,
|
||||
false,
|
||||
null
|
||||
));
|
||||
|
||||
const expected = [
|
||||
'<span>',
|
||||
'<span class="mtkw">····</span><span class="mtk2">if</span><span class="ced-1-TextEditorDecorationType2-17c14d98-3 ced-1-TextEditorDecorationType2-3"></span><span class="ced-1-TextEditorDecorationType2-17c14d98-4 ced-1-TextEditorDecorationType2-4"></span><span class="ced-ghost-text-1-4"></span>',
|
||||
'</span>'
|
||||
].join('');
|
||||
|
||||
assert.deepStrictEqual(actual.html, expected);
|
||||
assertCharacterMapping3(actual.characterMapping,
|
||||
[
|
||||
[0, [0, 0]],
|
||||
[1, [0, 1]],
|
||||
[2, [0, 2]],
|
||||
[3, [0, 3]],
|
||||
[4, [1, 0]],
|
||||
[5, [1, 1]],
|
||||
[6, [3, 0]],
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[], expectedPartLengths: number[]): (partIndex: number, partLength: number, offset: number, expected: number) => void {
|
||||
let renderLineOutput = renderViewLine(new RenderLineInput(
|
||||
@@ -2163,9 +2186,8 @@ suite('viewLineRenderer.renderLine 2', () => {
|
||||
));
|
||||
|
||||
return (partIndex: number, partLength: number, offset: number, expected: number) => {
|
||||
let charOffset = renderLineOutput.characterMapping.partDataToCharOffset(partIndex, partLength, offset);
|
||||
let actual = charOffset + 1;
|
||||
assert.strictEqual(actual, expected, 'getColumnOfLinePartOffset for ' + partIndex + ' @ ' + offset);
|
||||
const actualColumn = renderLineOutput.characterMapping.getColumn(new DomPosition(partIndex, offset), partLength);
|
||||
assert.strictEqual(actualColumn, expected, 'getColumn for ' + partIndex + ', ' + offset);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ suite('ViewModelDecorations', () => {
|
||||
model.changeDecorations((accessor) => {
|
||||
let createOpts = (id: string) => {
|
||||
return {
|
||||
description: 'test',
|
||||
className: id,
|
||||
inlineClassName: 'i-' + id,
|
||||
beforeContentClassName: 'b-' + id,
|
||||
@@ -165,6 +166,7 @@ suite('ViewModelDecorations', () => {
|
||||
accessor.addDecoration(
|
||||
new Range(1, 50, 1, 51),
|
||||
{
|
||||
description: 'test',
|
||||
beforeContentClassName: 'dec1'
|
||||
}
|
||||
);
|
||||
@@ -199,6 +201,7 @@ suite('ViewModelDecorations', () => {
|
||||
accessor.addDecoration(
|
||||
new Range(1, 1, 1, 1),
|
||||
{
|
||||
description: 'test',
|
||||
beforeContentClassName: 'before1',
|
||||
afterContentClassName: 'after1'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user