Merge from vscode a348d103d1256a06a2c9b3f9b406298a9fef6898 (#15681)

* Merge from vscode a348d103d1256a06a2c9b3f9b406298a9fef6898

* Fixes and cleanup

* Distro

* Fix hygiene yarn

* delete no yarn lock changes file

* Fix hygiene

* Fix layer check

* Fix CI

* Skip lib checks

* Remove tests deleted in vs code

* Fix tests

* Distro

* Fix tests and add removed extension point

* Skip failing notebook tests for now

* Disable broken tests and cleanup build folder

* Update yarn.lock and fix smoke tests

* Bump sqlite

* fix contributed actions and file spacing

* Fix user data path

* Update yarn.locks

Co-authored-by: ADS Merger <karlb@microsoft.com>
This commit is contained in:
Charles Gagnon
2021-06-17 08:17:11 -07:00
committed by GitHub
parent fdcb97c7f7
commit 3cb2f552a6
2582 changed files with 124827 additions and 87099 deletions

View File

@@ -1047,6 +1047,21 @@ suite('Editor Controller - Cursor', () => {
});
});
test('issue #118062: Column selection cannot select first position of a line', () => {
withTestCodeEditor([
'hello world',
].join('\n'), {}, (editor, viewModel) => {
moveTo(editor, viewModel, 1, 2, false);
assertCursor(viewModel, new Position(1, 2));
CoreNavigationCommands.CursorColumnSelectLeft.runCoreEditorCommand(viewModel, {});
assertCursor(viewModel, [
new Selection(1, 2, 1, 1)
]);
});
});
test('column select with keyboard', () => {
withTestCodeEditor([
'var gulp = require("gulp");',
@@ -2079,16 +2094,16 @@ suite('Editor Controller - Regression tests', () => {
// Typing sennsei in Japanese - Hiragana
viewModel.type('', 'keyboard');
viewModel.replacePreviousChar('せ', 1);
viewModel.replacePreviousChar('せn', 1);
viewModel.replacePreviousChar('せん', 2);
viewModel.replacePreviousChar('せんs', 2);
viewModel.replacePreviousChar('せんせ', 3);
viewModel.replacePreviousChar('せんせ', 3);
viewModel.replacePreviousChar('せんせい', 3);
viewModel.replacePreviousChar('せんせい', 4);
viewModel.replacePreviousChar('せんせい', 4);
viewModel.replacePreviousChar('せんせい', 4);
viewModel.compositionType('せ', 1, 0, 0);
viewModel.compositionType('せn', 1, 0, 0);
viewModel.compositionType('せん', 2, 0, 0);
viewModel.compositionType('せんs', 2, 0, 0);
viewModel.compositionType('せんせ', 3, 0, 0);
viewModel.compositionType('せんせ', 3, 0, 0);
viewModel.compositionType('せんせい', 3, 0, 0);
viewModel.compositionType('せんせい', 4, 0, 0);
viewModel.compositionType('せんせい', 4, 0, 0);
viewModel.compositionType('せんせい', 4, 0, 0);
assert.strictEqual(model.getLineContent(1), 'せんせい');
assertCursor(viewModel, new Position(1, 5));
@@ -5311,6 +5326,41 @@ suite('autoClosingPairs', () => {
mode.dispose();
});
test('issue #118270 - auto closing deletes only those characters that it inserted', () => {
let mode = new AutoClosingMode();
usingCursor({
text: [
'',
'y=();'
],
languageIdentifier: mode.getLanguageIdentifier()
}, (editor, model, viewModel) => {
assertCursor(viewModel, new Position(1, 1));
viewModel.type('x=(', 'keyboard');
assert.strictEqual(model.getLineContent(1), 'x=()');
viewModel.type('asd', 'keyboard');
assert.strictEqual(model.getLineContent(1), 'x=(asd)');
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
assert.strictEqual(model.getLineContent(1), 'x=()');
// delete closing char!
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
assert.strictEqual(model.getLineContent(1), 'x=');
// do not delete closing char!
viewModel.setSelections('test', [new Selection(2, 4, 2, 4)]);
CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null);
assert.strictEqual(model.getLineContent(2), 'y=);');
});
mode.dispose();
});
test('issue #78527 - does not close quote on odd count', () => {
let mode = new AutoClosingMode();
usingCursor({
@@ -5449,7 +5499,7 @@ suite('autoClosingPairs', () => {
// Typing ` + e on the mac US intl kb layout
viewModel.startComposition();
viewModel.type('`', 'keyboard');
viewModel.replacePreviousChar('è', 1, 'keyboard');
viewModel.compositionType('è', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), 'è');
@@ -5470,8 +5520,8 @@ suite('autoClosingPairs', () => {
// Typing ` + e on the mac US intl kb layout
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '\'test\'');
@@ -5550,8 +5600,8 @@ suite('autoClosingPairs', () => {
viewModel.startComposition();
viewModel.type('`', 'keyboard');
moveDown(editor, viewModel, true);
viewModel.replacePreviousChar('`', 1, 'keyboard');
viewModel.replacePreviousChar('`', 1, 'keyboard');
viewModel.compositionType('`', 1, 0, 0, 'keyboard');
viewModel.compositionType('`', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '`hello\nworld');
@@ -5575,14 +5625,14 @@ suite('autoClosingPairs', () => {
// Typing ' + space
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '\'\'');
// Typing one more ' + space
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '\'\'');
@@ -5591,7 +5641,7 @@ suite('autoClosingPairs', () => {
viewModel.setSelections('test', [new Selection(1, 5, 1, 5)]);
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '\'abc\'');
@@ -5601,7 +5651,7 @@ suite('autoClosingPairs', () => {
viewModel.setSelections('test', [new Selection(1, 10, 1, 10)]);
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '\'abc\'def \'\'');
@@ -5611,7 +5661,7 @@ suite('autoClosingPairs', () => {
viewModel.setSelections('test', [new Selection(1, 1, 1, 1)]);
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
// No auto closing if it's after a word.
@@ -5619,7 +5669,7 @@ suite('autoClosingPairs', () => {
viewModel.setSelections('test', [new Selection(1, 4, 1, 4)]);
viewModel.startComposition();
viewModel.type('\'', 'keyboard');
viewModel.replacePreviousChar('\'', 1, 'keyboard');
viewModel.compositionType('\'', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), 'abc\'');
@@ -5640,7 +5690,7 @@ suite('autoClosingPairs', () => {
// Typing a + backspace
viewModel.startComposition();
viewModel.type('a', 'keyboard');
viewModel.replacePreviousChar('', 1, 'keyboard');
viewModel.compositionType('', 1, 0, 0, 'keyboard');
viewModel.endComposition('keyboard');
assert.strictEqual(model.getValue(), '{}');
});

View File

@@ -151,9 +151,9 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string
};
handler.onType((e) => {
console.log('type text: ' + e.text + ', replaceCharCnt: ' + e.replaceCharCnt);
console.log('type text: ' + e.text + ', replaceCharCnt: ' + e.replacePrevCharCnt);
let text = model.getModelLineContent(1);
let preText = text.substring(0, cursorOffset - e.replaceCharCnt);
let preText = text.substring(0, cursorOffset - e.replacePrevCharCnt);
let postText = text.substring(cursorOffset + cursorLength);
let midText = e.text;

View File

@@ -134,8 +134,12 @@ suite('TextAreaState', () => {
let newState = TextAreaState.readFromTextArea(textArea);
let actual = TextAreaState.deduceInput(prevState, newState, couldBeEmojiInput);
assert.strictEqual(actual.text, expected);
assert.strictEqual(actual.replaceCharCnt, expectedCharReplaceCnt);
assert.deepStrictEqual(actual, {
text: expected,
replacePrevCharCnt: expectedCharReplaceCnt,
replaceNextCharCnt: 0,
positionDelta: 0,
});
textArea.dispose();
}
@@ -503,6 +507,82 @@ suite('TextAreaState', () => {
);
});
function testDeduceAndroidCompositionInput(
prevState: TextAreaState | null,
value: string, selectionStart: number, selectionEnd: number,
expected: string, expectedReplacePrevCharCnt: number, expectedReplaceNextCharCnt: number, expectedPositionDelta: number): void {
prevState = prevState || TextAreaState.EMPTY;
let textArea = new MockTextAreaWrapper();
textArea._value = value;
textArea._selectionStart = selectionStart;
textArea._selectionEnd = selectionEnd;
let newState = TextAreaState.readFromTextArea(textArea);
let actual = TextAreaState.deduceAndroidCompositionInput(prevState, newState);
assert.deepStrictEqual(actual, {
text: expected,
replacePrevCharCnt: expectedReplacePrevCharCnt,
replaceNextCharCnt: expectedReplaceNextCharCnt,
positionDelta: expectedPositionDelta,
});
textArea.dispose();
}
test('Android composition input 1', () => {
testDeduceAndroidCompositionInput(
new TextAreaState(
'Microsoft',
4, 4,
null, null
),
'Microsoft',
4, 4,
'', 0, 0, 0,
);
});
test('Android composition input 2', () => {
testDeduceAndroidCompositionInput(
new TextAreaState(
'Microsoft',
4, 4,
null, null
),
'Microsoft',
0, 9,
'', 0, 0, 5,
);
});
test('Android composition input 3', () => {
testDeduceAndroidCompositionInput(
new TextAreaState(
'Microsoft',
0, 9,
null, null
),
'Microsoft\'s',
11, 11,
'\'s', 0, 0, 0,
);
});
test('Android backspace', () => {
testDeduceAndroidCompositionInput(
new TextAreaState(
'undefinedVariable',
2, 2,
null, null
),
'udefinedVariable',
1, 1,
'', 1, 0, 0,
);
});
suite('PagedScreenReaderStrategy', () => {
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {

View File

@@ -32,11 +32,11 @@ class TestGlobalStyleSheet extends GlobalStyleSheet {
super(null!);
}
public insertRule(rule: string, index?: number): void {
public override insertRule(rule: string, index?: number): void {
this.rules.unshift(rule);
}
public removeRulesContainingSelector(ruleName: string): void {
public override removeRulesContainingSelector(ruleName: string): void {
for (let i = 0; i < this.rules.length; i++) {
if (this.rules[i].indexOf(ruleName) >= 0) {
this.rules.splice(i, 1);
@@ -52,18 +52,18 @@ class TestGlobalStyleSheet extends GlobalStyleSheet {
suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suite
let options: IDecorationRenderOptions = {
gutterIconPath: URI.parse('https://github.com/microsoft/vscode/blob/master/resources/linux/code.png'),
gutterIconPath: URI.parse('https://github.com/microsoft/vscode/blob/main/resources/linux/code.png'),
gutterIconSize: 'contain',
backgroundColor: 'red',
borderColor: 'yellow'
};
test('register and resolve decoration type', () => {
let s = new TestCodeEditorServiceImpl(themeServiceMock);
let s = new TestCodeEditorServiceImpl(null, themeServiceMock);
s.registerDecorationType('example', options);
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
});
test('remove decoration type', () => {
let s = new TestCodeEditorServiceImpl(themeServiceMock);
let s = new TestCodeEditorServiceImpl(null, themeServiceMock);
s.registerDecorationType('example', options);
assert.notStrictEqual(s.resolveDecorationOptions('example', false), undefined);
s.removeDecorationType('example');
@@ -76,10 +76,10 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
test('css properties', () => {
const styleSheet = new TestGlobalStyleSheet();
const s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet);
const s = new TestCodeEditorServiceImpl(styleSheet, themeServiceMock);
s.registerDecorationType('example', options);
const sheet = readStyleSheet(styleSheet);
assert(sheet.indexOf(`{background:url('https://github.com/microsoft/vscode/blob/master/resources/linux/code.png') center center no-repeat;background-size:contain;}`) >= 0);
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);
});
@@ -93,7 +93,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
const themeService = new TestThemeService(new TestColorTheme({
editorBackground: '#FF0000'
}));
const s = new TestCodeEditorServiceImpl(themeService, styleSheet);
const s = new TestCodeEditorServiceImpl(styleSheet, themeService);
s.registerDecorationType('example', options);
assert.strictEqual(readStyleSheet(styleSheet), '.monaco-editor .ced-example-0 {background-color:#ff0000;border-color:transparent;box-sizing: border-box;}');
@@ -126,7 +126,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
editorBackground: '#FF0000',
infoForeground: '#444444'
}));
const s = new TestCodeEditorServiceImpl(themeService, styleSheet);
const s = new TestCodeEditorServiceImpl(styleSheet, themeService);
s.registerDecorationType('example', options);
const expected = [
'.vs-dark.monaco-editor .ced-example-4::after, .hc-black.monaco-editor .ced-example-4::after {color:#444444 !important;}',
@@ -142,7 +142,7 @@ suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suit
test('css properties, gutterIconPaths', () => {
const styleSheet = new TestGlobalStyleSheet();
const s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet);
const s = new TestCodeEditorServiceImpl(styleSheet, themeServiceMock);
// URI, only minimal encoding
s.registerDecorationType('example', { gutterIconPath: URI.parse('data:image/svg+xml;base64,PHN2ZyB4b+') });

View File

@@ -32,47 +32,47 @@ 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.equal(editorService.lastInput!.options!.selection, undefined);
assert.strictEqual(editorService.lastInput!.options!.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.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
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!.resource.fragment, '');
await openerService.open(URI.parse('another:///somepath#L23'));
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1);
await openerService.open(URI.parse('another:///somepath#L23,45'));
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
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!.resource.fragment, '');
});
test('delegate to editorService, scheme:///fff#123,123', async function () {
const openerService = new OpenerService(editorService, NullCommandService);
await openerService.open(URI.parse('file:///somepath#23'));
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
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!.resource.fragment, '');
await openerService.open(URI.parse('file:///somepath#23,45'));
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
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!.resource.fragment, '');
});
test('delegate to commandsService, command:someid', async function () {
@@ -83,10 +83,37 @@ suite('OpenerService', function () {
assert.strictEqual(lastCommand, undefined);
await openerService.open(URI.parse('command:' + id));
assert.strictEqual(lastCommand, undefined);
});
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 are protected by validators', async function () {
const openerService = new OpenerService(editorService, commandService);
@@ -94,8 +121,8 @@ suite('OpenerService', function () {
const httpResult = await openerService.open(URI.parse('https://www.microsoft.com'));
const httpsResult = await openerService.open(URI.parse('https://www.microsoft.com'));
assert.equal(httpResult, false);
assert.equal(httpsResult, false);
assert.strictEqual(httpResult, false);
assert.strictEqual(httpsResult, false);
});
test('delegate to commandsService, command:someid', async function () {
@@ -139,9 +166,23 @@ suite('OpenerService', function () {
});
await openerService.open(URI.parse('http://microsoft.com'));
assert.equal(openCount, 1);
assert.strictEqual(openCount, 1);
await openerService.open(URI.parse('https://microsoft.com'));
assert.equal(openCount, 2);
assert.strictEqual(openCount, 2);
});
test('links aren\'t manipulated before being passed to validator: PR #118226', async function () {
const openerService = new OpenerService(editorService, commandService);
openerService.registerValidator({
shouldOpen: (resource) => {
// We don't want it to convert strings into URIs
assert.strictEqual(resource instanceof URI, false);
return Promise.resolve(false);
}
});
await openerService.open('https://wwww.microsoft.com');
await openerService.open('https://www.microsoft.com??params=CountryCode%3DUSA%26Name%3Dvscode"');
});
test('links validated by multiple validators', async function () {
@@ -172,13 +213,13 @@ suite('OpenerService', function () {
});
await openerService.open(URI.parse('http://microsoft.com'));
assert.equal(openCount, 1);
assert.equal(v1, 1);
assert.equal(v2, 1);
assert.strictEqual(openCount, 1);
assert.strictEqual(v1, 1);
assert.strictEqual(v2, 1);
await openerService.open(URI.parse('https://microsoft.com'));
assert.equal(openCount, 2);
assert.equal(v1, 2);
assert.equal(v2, 2);
assert.strictEqual(openCount, 2);
assert.strictEqual(v1, 2);
assert.strictEqual(v2, 2);
});
test('links invalidated by first validator do not continue validating', async function () {
@@ -209,13 +250,13 @@ suite('OpenerService', function () {
});
await openerService.open(URI.parse('http://microsoft.com'));
assert.equal(openCount, 0);
assert.equal(v1, 1);
assert.equal(v2, 0);
assert.strictEqual(openCount, 0);
assert.strictEqual(v1, 1);
assert.strictEqual(v2, 0);
await openerService.open(URI.parse('https://microsoft.com'));
assert.equal(openCount, 0);
assert.equal(v1, 2);
assert.equal(v2, 0);
assert.strictEqual(openCount, 0);
assert.strictEqual(v1, 2);
assert.strictEqual(v2, 0);
});
test('matchesScheme', function () {

View File

@@ -23,6 +23,8 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
@@ -34,13 +36,20 @@ export interface ITestCodeEditor extends IActiveCodeEditor {
export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor {
//#region testing overrides
protected _createConfiguration(options: Readonly<IEditorConstructionOptions>): IConfiguration {
protected override _createConfiguration(options: Readonly<IEditorConstructionOptions>): IConfiguration {
return new TestConfiguration(options);
}
protected _createView(viewModel: ViewModel): [View, boolean] {
protected override _createView(viewModel: ViewModel): [View, boolean] {
// Never create a view
return [null! as View, false];
}
private _hasTextFocus = false;
public setHasTextFocus(hasTextFocus: boolean): void {
this._hasTextFocus = hasTextFocus;
}
public override hasTextFocus(): boolean {
return this._hasTextFocus;
}
//#endregion
//#region Testing utils
@@ -55,7 +64,7 @@ export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor {
}
class TestCodeEditorWithAutoModelDisposal extends TestCodeEditor {
public dispose() {
public override dispose() {
super.dispose();
if (this._modelData) {
this._modelData.model.dispose();
@@ -79,6 +88,11 @@ export interface TestCodeEditorCreationOptions extends editorOptions.IEditorOpti
*/
model?: ITextModel;
serviceCollection?: ServiceCollection;
/**
* If the editor has text focus.
* Defaults to true.
*/
hasTextFocus?: boolean;
}
export function withTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel) => void): void {
@@ -99,7 +113,7 @@ export function withTestCodeEditor(text: string | string[] | null, options: Test
editor.dispose();
}
export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel) => Promise<void>): Promise<void> {
export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel, instantiationService: IInstantiationService) => Promise<void>): Promise<void> {
// create a model if necessary and remember it in order to dispose it.
if (!options.model) {
if (typeof text === 'string') {
@@ -109,15 +123,20 @@ export async function withAsyncTestCodeEditor(text: string | string[] | null, op
}
}
const editor = createTestCodeEditor(options);
const [instantiationService, editor] = doCreateTestCodeEditor(options);
const viewModel = editor.getViewModel()!;
viewModel.setHasFocus(true);
await callback(<ITestCodeEditor>editor, editor.getViewModel()!);
await callback(<ITestCodeEditor>editor, editor.getViewModel()!, instantiationService);
editor.dispose();
}
export function createTestCodeEditor(options: TestCodeEditorCreationOptions): ITestCodeEditor {
const [, editor] = doCreateTestCodeEditor(options);
return editor;
}
function doCreateTestCodeEditor(options: TestCodeEditorCreationOptions): [IInstantiationService, ITestCodeEditor] {
const model = options.model;
delete options.model;
@@ -142,6 +161,9 @@ export function createTestCodeEditor(options: TestCodeEditorCreationOptions): IT
if (!services.has(IThemeService)) {
services.set(IThemeService, new TestThemeService());
}
if (!services.has(ITelemetryService)) {
services.set(ITelemetryService, NullTelemetryService);
}
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
contributions: []
@@ -152,6 +174,10 @@ export function createTestCodeEditor(options: TestCodeEditorCreationOptions): IT
options,
codeEditorWidgetOptions
);
if (typeof options.hasTextFocus === 'undefined') {
options.hasTextFocus = true;
}
editor.setHasTextFocus(options.hasTextFocus);
editor.setModel(model);
return <ITestCodeEditor>editor;
return [instantiationService, <ITestCodeEditor>editor];
}

View File

@@ -35,10 +35,10 @@ export function testCommand(
cursor.executeCommand(commandFactory(cursor.getSelection()), 'tests');
assert.deepEqual(model.getLinesContent(), expectedLines);
assert.deepStrictEqual(model.getLinesContent(), expectedLines);
let actualSelection = cursor.getSelection();
assert.deepEqual(actualSelection.toString(), expectedSelection.toString());
assert.deepStrictEqual(actualSelection.toString(), expectedSelection.toString());
});
model.dispose();

View File

@@ -53,7 +53,7 @@ suite('Common Editor Config', () => {
});
class TestWrappingConfiguration extends TestConfiguration {
protected _getEnvConfiguration(): IEnvConfiguration {
protected override _getEnvConfiguration(): IEnvConfiguration {
return {
extraEditorClassName: '',
outerWidth: 1000,

View File

@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { writeUInt16LE } from 'vs/base/common/buffer';
import { decodeUTF16LE } from 'vs/editor/common/core/stringBuilder';
suite('decodeUTF16LE', () => {
test('issue #118041: unicode character undo bug 1', () => {
const buff = new Uint8Array(2);
writeUInt16LE(buff, ''.charCodeAt(0), 0);
const actual = decodeUTF16LE(buff, 0, 1);
assert.deepStrictEqual(actual, '');
});
test('issue #118041: unicode character undo bug 2', () => {
const buff = new Uint8Array(4);
writeUInt16LE(buff, 'a'.charCodeAt(0), 0);
writeUInt16LE(buff, 'a'.charCodeAt(1), 2);
const actual = decodeUTF16LE(buff, 0, 2);
assert.deepStrictEqual(actual, 'a');
});
test('issue #118041: unicode character undo bug 3', () => {
const buff = new Uint8Array(6);
writeUInt16LE(buff, 'ab'.charCodeAt(0), 0);
writeUInt16LE(buff, 'ab'.charCodeAt(1), 2);
writeUInt16LE(buff, 'ab'.charCodeAt(2), 4);
const actual = decodeUTF16LE(buff, 0, 3);
assert.deepStrictEqual(actual, 'ab');
});
});

View File

@@ -886,4 +886,34 @@ suite('Editor Diff - DiffComputer', () => {
];
assertDiff(original, modified, expected, false, false, false);
});
test('issue #119051: gives preference to fewer diff hunks', () => {
const original = [
'1',
'',
'',
'2',
'',
];
const modified = [
'1',
'',
'1.5',
'',
'',
'2',
'',
'3',
'',
];
const expected = [
createLineChange(
2, 0, 3, 4
),
createLineChange(
5, 0, 8, 9
)
];
assertDiff(original, modified, expected, false, false, false);
});
});

View File

@@ -28,5 +28,4 @@ export class MockMode extends Disposable implements IMode {
export class StaticLanguageSelector implements ILanguageSelection {
readonly onDidChange: Event<LanguageIdentifier> = Event.None;
constructor(public readonly languageIdentifier: LanguageIdentifier) { }
public dispose(): void { }
}

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { EndOfLineSequence } from 'vs/editor/common/model';
import { SingleModelEditStackData } from 'vs/editor/common/model/editStack';
import { Selection } from 'vs/editor/common/core/selection';
import { TextChange } from 'vs/editor/common/model/textChange';
suite('EditStack', () => {
test('issue #118041: unicode character undo bug', () => {
const stackData = new SingleModelEditStackData(
1,
2,
EndOfLineSequence.LF,
EndOfLineSequence.LF,
[new Selection(10, 2, 10, 2)],
[new Selection(10, 1, 10, 1)],
[new TextChange(428, '', 428, '')]
);
const buff = stackData.serialize();
const actual = SingleModelEditStackData.deserialize(buff);
assert.deepStrictEqual(actual, stackData);
});
});

View File

@@ -20,7 +20,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
let inverseEdits = model.applyEdits(edits, true);
// Assert edits produced expected result
assert.deepEqual(model.getValue(EndOfLinePreference.LF), expectedStr);
assert.deepStrictEqual(model.getValue(EndOfLinePreference.LF), expectedStr);
assertMirrorModels();
@@ -28,7 +28,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
let inverseInverseEdits = model.applyEdits(inverseEdits, true);
// Assert the inverse edits brought back model to original state
assert.deepEqual(model.getValue(EndOfLinePreference.LF), originalStr);
assert.deepStrictEqual(model.getValue(EndOfLinePreference.LF), originalStr);
if (!inputEditsAreInvalid) {
const simplifyEdit = (edit: IIdentifiedSingleEditOperation) => {
@@ -41,7 +41,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent
};
};
// Assert the inverse of the inverse edits are the original edits
assert.deepEqual(inverseInverseEdits.map(simplifyEdit), edits.map(simplifyEdit));
assert.deepStrictEqual(inverseInverseEdits.map(simplifyEdit), edits.map(simplifyEdit));
}
assertMirrorModels();
@@ -59,16 +59,16 @@ function assertOneDirectionLineMapping(model: TextModel, direction: AssertDocume
let line = 1, column = 1, previousIsCarriageReturn = false;
for (let offset = 0; offset <= allText.length; offset++) {
// The position coordinate system cannot express the position between \r and \n
let position = new Position(line, column + (previousIsCarriageReturn ? -1 : 0));
let position: Position = new Position(line, column + (previousIsCarriageReturn ? -1 : 0));
if (direction === AssertDocumentLineMappingDirection.OffsetToPosition) {
let actualPosition = model.getPositionAt(offset);
assert.equal(actualPosition.toString(), position.toString(), msg + ' - getPositionAt mismatch for offset ' + offset);
assert.strictEqual(actualPosition.toString(), position.toString(), msg + ' - getPositionAt mismatch for offset ' + offset);
} else {
// The position coordinate system cannot express the position between \r and \n
let expectedOffset = offset + (previousIsCarriageReturn ? -1 : 0);
let expectedOffset: number = offset + (previousIsCarriageReturn ? -1 : 0);
let actualOffset = model.getOffsetAt(position);
assert.equal(actualOffset, expectedOffset, msg + ' - getOffsetAt mismatch for position ' + position.toString());
assert.strictEqual(actualOffset, expectedOffset, msg + ' - getOffsetAt mismatch for position ' + position.toString());
}
if (allText.charAt(offset) === '\n') {
@@ -112,8 +112,8 @@ export function assertSyncedModels(text: string, callback: (model: TextModel, as
let assertMirrorModels = () => {
assertLineMapping(model, 'model');
assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK');
assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK');
assert.strictEqual(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK');
assert.strictEqual(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK');
};
callback(model, assertMirrorModels);

View File

@@ -119,6 +119,19 @@ suite('TextChangeCompressor', () => {
);
});
// test('issue #118041', () => {
// assertCompression(
// '',
// [
// { offset: 0, length: 1, text: '' },
// ],
// [
// { offset: 1, length: 0, text: 'Z' },
// { offset: 3, length: 3, text: 'Y' },
// ]
// );
// })
test('gen1', () => {
assertCompression(
'kxm',
@@ -267,3 +280,16 @@ suite('TextChangeCompressor', () => {
}
}
});
suite('TextChange', () => {
test('issue #118041: unicode character undo bug', () => {
const textChange = new TextChange(428, '', 428, '');
const buff = new Uint8Array(textChange.writeSize());
textChange.write(buff, 0);
const actual: TextChange[] = [];
TextChange.read(buff, 0, actual);
assert.deepStrictEqual(actual[0], textChange);
});
});

View File

@@ -1062,4 +1062,11 @@ suite('TextModel.createSnapshot', () => {
model.dispose();
});
test('issue #119632: invalid range', () => {
const model = createTextModel('hello world!');
const actual = model._validateRangeRelaxedNoAllocations(new Range(<any>undefined, 0, <any>undefined, 1));
assert.deepStrictEqual(actual, new Range(1, 1, 1, 1));
model.dispose();
});
});

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { TokenizationResult2 } from 'vs/editor/common/core/token';
@@ -337,6 +337,97 @@ suite('TextModelWithTokens', () => {
registration.dispose();
});
test('issue #95843: Highlighting of closing braces is indicating wrong brace when cursor is behind opening brace', () => {
const mode1 = new LanguageIdentifier('testMode1', 3);
const mode2 = new LanguageIdentifier('testMode2', 4);
const otherMetadata1 = (
(mode1.id << MetadataConsts.LANGUAGEID_OFFSET)
| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)
) >>> 0;
const otherMetadata2 = (
(mode2.id << MetadataConsts.LANGUAGEID_OFFSET)
| (StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET)
) >>> 0;
const tokenizationSupport: ITokenizationSupport = {
getInitialState: () => NULL_STATE,
tokenize: undefined!,
tokenize2: (line, hasEOL, state) => {
switch (line) {
case 'function f() {': {
const tokens = new Uint32Array([
0, otherMetadata1,
8, otherMetadata1,
9, otherMetadata1,
10, otherMetadata1,
11, otherMetadata1,
12, otherMetadata1,
13, otherMetadata1,
]);
return new TokenizationResult2(tokens, state);
}
case ' return <p>{true}</p>;': {
const tokens = new Uint32Array([
0, otherMetadata1,
2, otherMetadata1,
8, otherMetadata1,
9, otherMetadata2,
10, otherMetadata2,
11, otherMetadata2,
12, otherMetadata2,
13, otherMetadata1,
17, otherMetadata2,
18, otherMetadata2,
20, otherMetadata2,
21, otherMetadata2,
22, otherMetadata2,
]);
return new TokenizationResult2(tokens, state);
}
case '}': {
const tokens = new Uint32Array([
0, otherMetadata1
]);
return new TokenizationResult2(tokens, state);
}
}
throw new Error(`Unexpected`);
}
};
const disposableStore = new DisposableStore();
disposableStore.add(TokenizationRegistry.register(mode1.language, tokenizationSupport));
disposableStore.add(LanguageConfigurationRegistry.register(mode1, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
}));
disposableStore.add(LanguageConfigurationRegistry.register(mode2, {
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
}));
const model = disposableStore.add(createTextModel([
'function f() {',
' return <p>{true}</p>;',
'}',
].join('\n'), undefined, mode1));
model.forceTokenization(1);
model.forceTokenization(2);
model.forceTokenization(3);
assert.deepStrictEqual(model.matchBracket(new Position(2, 14)), [new Range(2, 13, 2, 14), new Range(2, 18, 2, 19)]);
disposableStore.dispose();
});
test('issue #88075: TypeScript brace matching is incorrect in `${}` strings', () => {
const mode = new LanguageIdentifier('testMode', 3);
const otherMetadata = (

View File

@@ -8,13 +8,13 @@ import { MultilineTokens2, SparseEncodedTokens, TokensStore2 } from 'vs/editor/c
import { Range } from 'vs/editor/common/core/range';
import { TextModel } from 'vs/editor/common/model/textModel';
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
import { MetadataConsts, TokenMetadata, FontStyle } from 'vs/editor/common/modes';
import { MetadataConsts, TokenMetadata, FontStyle, ColorId } from 'vs/editor/common/modes';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
suite('TokensStore', () => {
const SEMANTIC_COLOR = 5;
const SEMANTIC_COLOR: ColorId = 5;
function parseTokensState(state: string[]): { text: string; tokens: MultilineTokens2; } {
let text: string[] = [];

View File

@@ -243,60 +243,60 @@ suite('Token theme resolving', () => {
});
test('defaults are inherited', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.NotSet, 'ff0000', null)
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _C, _B))
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('same rules get merged', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', 1, FontStyle.Bold, null, null),
new ParsedTokenThemeRule('var', 0, FontStyle.NotSet, 'ff0000', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B))
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('rules are inherited 1', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.Bold, 'ff0000', null),
new ParsedTokenThemeRule('var.identifier', -1, FontStyle.NotSet, '00ff00', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('ff0000');
const _D = colorMap.getId('00ff00');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _C, _B), {
'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _D, _B))
})
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('rules are inherited 2', () => {
let actual = TokenTheme.createFromParsedTokenTheme([
const actual = TokenTheme.createFromParsedTokenTheme([
new ParsedTokenThemeRule('', -1, FontStyle.NotSet, 'F8F8F2', '272822'),
new ParsedTokenThemeRule('var', -1, FontStyle.Bold, 'ff0000', null),
new ParsedTokenThemeRule('var.identifier', -1, FontStyle.NotSet, '00ff00', null),
@@ -306,7 +306,7 @@ suite('Token theme resolving', () => {
new ParsedTokenThemeRule('constant.numeric.oct', 7, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null),
new ParsedTokenThemeRule('constant.numeric.dec', 8, FontStyle.None, '300000', null),
], []);
let colorMap = new ColorMap();
const colorMap = new ColorMap();
const _A = colorMap.getId('F8F8F2');
const _B = colorMap.getId('272822');
const _C = colorMap.getId('100000');
@@ -315,7 +315,7 @@ suite('Token theme resolving', () => {
const _F = colorMap.getId('ff0000');
const _G = colorMap.getId('00ff00');
assert.deepStrictEqual(actual.getColorMap(), colorMap.getColorMap());
let root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
const root = new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.None, _A, _B), {
'var': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _F, _B), {
'identifier': new ExternalThemeTrieElement(new ThemeTrieElementRule(FontStyle.Bold, _G, _B))
}),
@@ -327,7 +327,7 @@ suite('Token theme resolving', () => {
})
})
});
assert.deepEqual(actual.getThemeTrieElement(), root);
assert.deepStrictEqual(actual.getThemeTrieElement(), root);
});
test('custom colors are first in color map', () => {

View File

@@ -18,10 +18,10 @@ suite('TextResourceConfigurationService - Update', () => {
let configurationValue: IConfigurationValue<any> = {};
let updateArgs: any[];
let configurationService = new class extends TestConfigurationService {
inspect() {
override inspect() {
return configurationValue;
}
updateValue() {
override updateValue() {
updateArgs = [...arguments];
return Promise.resolve();
}
@@ -40,13 +40,13 @@ suite('TextResourceConfigurationService - Update', () => {
test('updateValue writes without target and overrides when no language is defined', async () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes with target and without overrides when no language is defined', async () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b', ConfigurationTarget.USER_LOCAL);
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes into given memory target without overrides', async () => {
@@ -59,7 +59,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b', ConfigurationTarget.MEMORY);
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.MEMORY]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.MEMORY]);
});
test('updateValue writes into given workspace target without overrides', async () => {
@@ -72,7 +72,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b', ConfigurationTarget.WORKSPACE);
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE]);
});
test('updateValue writes into given user target without overrides', async () => {
@@ -85,7 +85,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b', ConfigurationTarget.USER);
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER]);
});
test('updateValue writes into given workspace folder target with overrides', async () => {
@@ -98,7 +98,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b', ConfigurationTarget.WORKSPACE_FOLDER);
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE_FOLDER]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE_FOLDER]);
});
test('updateValue writes into derived workspace folder target without overrides', async () => {
@@ -111,7 +111,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE_FOLDER]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE_FOLDER]);
});
test('updateValue writes into derived workspace folder target with overrides', async () => {
@@ -125,7 +125,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE_FOLDER]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE_FOLDER]);
});
test('updateValue writes into derived workspace target without overrides', async () => {
@@ -138,7 +138,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.WORKSPACE]);
});
test('updateValue writes into derived workspace target with overrides', async () => {
@@ -151,7 +151,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE]);
});
test('updateValue writes into derived workspace target with overrides and value defined in folder', async () => {
@@ -165,7 +165,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.WORKSPACE]);
});
test('updateValue writes into derived user remote target without overrides', async () => {
@@ -178,7 +178,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_REMOTE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_REMOTE]);
});
test('updateValue writes into derived user remote target with overrides', async () => {
@@ -191,7 +191,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
});
test('updateValue writes into derived user remote target with overrides and value defined in workspace', async () => {
@@ -205,7 +205,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
});
test('updateValue writes into derived user remote target with overrides and value defined in workspace folder', async () => {
@@ -220,7 +220,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_REMOTE]);
});
test('updateValue writes into derived user target without overrides', async () => {
@@ -232,7 +232,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes into derived user target with overrides', async () => {
@@ -244,7 +244,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', '2');
assert.deepEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes into derived user target with overrides and value is defined in remote', async () => {
@@ -257,7 +257,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', '2');
assert.deepEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes into derived user target with overrides and value is defined in workspace', async () => {
@@ -270,7 +270,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', '2');
assert.deepEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue writes into derived user target with overrides and value is defined in workspace folder', async () => {
@@ -284,7 +284,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', '2');
assert.deepEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', '2', { resource, overrideIdentifier: language }, ConfigurationTarget.USER_LOCAL]);
});
test('updateValue when not changed', async () => {
@@ -295,7 +295,7 @@ suite('TextResourceConfigurationService - Update', () => {
const resource = URI.file('someFile');
await testObject.updateValue(resource, 'a', 'b');
assert.deepEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
assert.deepStrictEqual(updateArgs, ['a', 'b', { resource }, ConfigurationTarget.USER_LOCAL]);
});
});

View File

@@ -1643,8 +1643,8 @@ suite('viewLineRenderer.renderLine 2', () => {
0,
createViewLineTokens([createPart(0, 3)]),
[
new LineDecoration(1, 2, 'before', InlineDecorationType.Before),
new LineDecoration(0, 1, 'after', InlineDecorationType.After),
new LineDecoration(1, 1, 'before', InlineDecorationType.Before),
new LineDecoration(1, 1, 'after', InlineDecorationType.After),
],
2,
0,
@@ -1668,6 +1668,47 @@ suite('viewLineRenderer.renderLine 2', () => {
assert.deepStrictEqual(actual.html, expected);
});
test('issue #118759: enable multiple text editor decorations in empty lines', () => {
let actual = renderViewLine(new RenderLineInput(
true,
true,
'',
false,
true,
false,
0,
createViewLineTokens([createPart(0, 3)]),
[
new LineDecoration(1, 1, 'after1', InlineDecorationType.After),
new LineDecoration(1, 1, 'after2', InlineDecorationType.After),
new LineDecoration(1, 1, 'before1', InlineDecorationType.Before),
new LineDecoration(1, 1, 'before2', InlineDecorationType.Before),
],
2,
0,
10,
10,
10,
10000,
'none',
false,
false,
null
));
let expected = [
'<span>',
'<span class="before1"></span>',
'<span class="before2"></span>',
'<span class="after1"></span>',
'<span class="after2"></span>',
'</span>'
].join('');
assert.deepStrictEqual(actual.html, expected);
});
test('issue #38935: GitLens end-of-line blame no longer rendering', () => {
let actual = renderViewLine(new RenderLineInput(
@@ -2065,6 +2106,38 @@ suite('viewLineRenderer.renderLine 2', () => {
assert.deepStrictEqual(actual.html, expected);
});
test('issue #119416: Delete Control Character (U+007F / &#127;) displayed as space', () => {
const actual = renderViewLine(new RenderLineInput(
false,
false,
'[' + String.fromCharCode(127) + '] [' + String.fromCharCode(0) + ']',
false,
true,
false,
0,
createViewLineTokens([createPart(7, 3)]),
[],
4,
0,
10,
10,
10,
10000,
'none',
true,
true,
null
));
const expected = [
'<span>',
'<span class="mtk3">[\u2421]\u00a0[\u2400]</span>',
'</span>'
].join('');
assert.deepStrictEqual(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(

View File

@@ -66,7 +66,7 @@ suite('ViewModel', () => {
viewLineCount.push(viewModel.getLineCount());
viewModel.addViewEventHandler(new class extends ViewEventHandler {
handleEvents(events: ViewEvent[]): void {
override handleEvents(events: ViewEvent[]): void {
// Access the view model
viewLineCount.push(viewModel.getLineCount());
}

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import { StandardTokenType } from 'vs/editor/common/modes';
import * as fs from 'fs';
// import { getPathFromAmdModule } from 'vs/base/common/amd';
// import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
// import { parse } from 'vs/editor/common/modes/tokenization/typescript';
import { toStandardTokenType } from 'vs/editor/common/modes/supports/tokenization';