SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<style>
.container {
border-top: 1px solid #ccc;
padding-top: 5px;
clear: both;
margin-top: 30px;
}
.container .title {
margin-bottom: 10px;
}
.container button {
float: left;
}
.container textarea {
float: left;
width: 200px;
height: 100px;
margin-left: 50px;
}
.container .output {
float: left;
background: lightblue;
margin: 0;
margin-left: 50px;
}
.container .check {
float: left;
background: grey;
margin: 0;
margin-left: 50px;
}
.container .check.good {
background: lightgreen;
}
</style>
</head>
<body>
<h3>Detailed setup steps at https://github.com/Microsoft/vscode/wiki/IME-Test</h3>
<script src="../../../../loader.js"></script>
<script>
require.config({
baseUrl: '../../../../../../out'
});
require(['vs/editor/test/browser/controller/imeTester'], function(imeTester) {
// console.log('loaded', imeTester);
// imeTester.createTest();
});
</script>
</body>
</html>

View File

@@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TextAreaInput, ITextAreaInputHost } from 'vs/editor/browser/controller/textAreaInput';
import { ISimpleModel, TextAreaState, PagedScreenReaderStrategy } from 'vs/editor/browser/controller/textAreaState';
import { Range, IRange } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { createFastDomNode } from 'vs/base/browser/fastDomNode';
import * as browser from 'vs/base/browser/browser';
// To run this test, open imeTester.html
class SingleLineTestModel implements ISimpleModel {
private _line: string;
private _eol: string;
constructor(line: string) {
this._line = line;
this._eol = '\n';
}
_setText(text: string) {
this._line = text;
}
getLineMaxColumn(lineNumber: number): number {
return this._line.length + 1;
}
getValueInRange(range: IRange, eol: editorCommon.EndOfLinePreference): string {
return this._line.substring(range.startColumn - 1, range.endColumn - 1);
}
getModelLineContent(lineNumber: number): string {
return this._line;
}
getLineCount(): number {
return 1;
}
}
class TestView {
private _model: SingleLineTestModel;
constructor(model: SingleLineTestModel) {
this._model = model;
}
public paint(output: HTMLElement) {
let r = '';
for (let i = 1; i <= this._model.getLineCount(); i++) {
let content = this._model.getModelLineContent(i);
r += content + '<br/>';
}
output.innerHTML = r;
}
}
function doCreateTest(description: string, inputStr: string, expectedStr: string): HTMLElement {
let cursorOffset: number = 0;
let cursorLength: number = 0;
let container = document.createElement('div');
container.className = 'container';
let title = document.createElement('div');
title.className = 'title';
title.innerHTML = description + '. Type <strong>' + inputStr + '</strong>';
container.appendChild(title);
let startBtn = document.createElement('button');
startBtn.innerHTML = 'Start';
container.appendChild(startBtn);
let input = document.createElement('textarea');
input.setAttribute('rows', '10');
input.setAttribute('cols', '40');
container.appendChild(input);
let model = new SingleLineTestModel('some text');
const textAreaInputHost: ITextAreaInputHost = {
getPlainTextToCopy: (): string => '',
getHTMLToCopy: (): string => '',
getScreenReaderContent: (currentState: TextAreaState): TextAreaState => {
if (browser.isIPad) {
// Do not place anything in the textarea for the iPad
return TextAreaState.EMPTY;
}
const selection = new Range(1, 1 + cursorOffset, 1, 1 + cursorOffset + cursorLength);
return PagedScreenReaderStrategy.fromEditorSelection(currentState, model, selection);
},
deduceModelPosition: (viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position => {
return null;
}
};
let handler = new TextAreaInput(textAreaInputHost, createFastDomNode(input));
let output = document.createElement('pre');
output.className = 'output';
container.appendChild(output);
let check = document.createElement('pre');
check.className = 'check';
container.appendChild(check);
let br = document.createElement('br');
br.style.clear = 'both';
container.appendChild(br);
let view = new TestView(model);
let updatePosition = (off: number, len: number) => {
cursorOffset = off;
cursorLength = len;
handler.writeScreenReaderContent('selection changed');
handler.focusTextArea();
};
let updateModelAndPosition = (text: string, off: number, len: number) => {
model._setText(text);
updatePosition(off, len);
view.paint(output);
let expected = 'some ' + expectedStr + ' text';
if (text === expected) {
check.innerHTML = '[GOOD]';
check.className = 'check good';
} else {
check.innerHTML = '[BAD]';
check.className = 'check bad';
}
check.innerHTML += expected;
};
handler.onType((e) => {
console.log('type text: ' + e.text + ', replaceCharCnt: ' + e.replaceCharCnt);
let text = model.getModelLineContent(1);
let preText = text.substring(0, cursorOffset - e.replaceCharCnt);
let postText = text.substring(cursorOffset + cursorLength);
let midText = e.text;
updateModelAndPosition(preText + midText + postText, (preText + midText).length, 0);
});
view.paint(output);
startBtn.onclick = function () {
updateModelAndPosition('some text', 5, 0);
input.focus();
};
return container;
}
const TESTS = [
{ description: 'Japanese IME 1', in: 'sennsei [Enter]', out: 'せんせい' },
{ description: 'Japanese IME 2', in: 'konnichiha [Enter]', out: 'こんいちは' },
{ description: 'Japanese IME 3', in: 'mikann [Enter]', out: 'みかん' },
{ description: 'Korean IME 1', in: 'gksrmf [Space]', out: '한글 ' },
{ description: 'Chinese IME 1', in: '.,', out: '。,' },
{ description: 'Chinese IME 2', in: 'ni [Space] hao [Space]', out: '你好' },
{ description: 'Chinese IME 3', in: 'hazni [Space]', out: '哈祝你' },
{ description: 'Mac dead key 1', in: '`.', out: '`.' },
{ description: 'Mac hold key 1', in: 'e long press and 1', out: 'é' }
];
TESTS.forEach((t) => {
document.body.appendChild(doCreateTest(t.description, t.in, t.out));
});

View File

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<h2>Input Recorder</h2>
<p>Records input events and logs them in the console</p>
<button id="start">Start</button>
<button id="stop">Stop</button><br/><br/>
<textarea rows="20" cols="50" id="input"></textarea>
<script>
var interestingEvents = [
'keydown',
'keyup',
'keypress',
'compositionstart',
'compositionupdate',
'compositionend',
'input',
'cut',
'copy',
'paste',
];
var RECORDED_EVENTS = [];
var input = document.getElementById('input');
var blackListedProps = [
'currentTarget',
'path',
'srcElement',
'target',
'view'
];
blackListedProps = blackListedProps.concat([
'AT_TARGET',
'BLUR',
'BUBBLING_PHASE',
'CAPTURING_PHASE',
'CHANGE',
'CLICK',
'DBLCLICK',
'DOM_KEY_LOCATION_LEFT',
'DOM_KEY_LOCATION_NUMPAD',
'DOM_KEY_LOCATION_RIGHT',
'DOM_KEY_LOCATION_STANDARD',
'DRAGDROP',
'FOCUS',
'KEYDOWN',
'KEYPRESS',
'KEYUP',
'MOUSEDOWN',
'MOUSEDRAG',
'MOUSEMOVE',
'MOUSEOUT',
'MOUSEOVER',
'MOUSEUP',
'NONE',
'SELECT'
])
function toSerializable(e) {
var r = {};
for (var k in e) {
if (blackListedProps.indexOf(k) >= 0) {
continue;
}
if (typeof e[k] === 'function') {
continue;
}
r[k] = e[k];
}
console.log(r);
return r;
}
function recordEvent(eventType, e) {
RECORDED_EVENTS.push({
type: eventType,
textarea: {
value: input.value,
selectionStart: input.selectionStart,
selectionEnd: input.selectionEnd
},
event: toSerializable(e)
});
}
interestingEvents.forEach(function(eventType) {
input.addEventListener(eventType, function(e) {
recordEvent(eventType, e);
});
});
document.getElementById('start').onclick = function() {
input.value = 'some text';
input.setSelectionRange(5, 5);
input.focus();
RECORDED_EVENTS = [];
};
document.getElementById('stop').onclick = function() {
console.log(JSON.stringify(RECORDED_EVENTS));
};
</script>
</body>
</html>

View File

@@ -0,0 +1,643 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { ISimpleModel, TextAreaState, ITextAreaWrapper, PagedScreenReaderStrategy } from 'vs/editor/browser/controller/textAreaState';
import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { Disposable } from 'vs/base/common/lifecycle';
import { Model } from 'vs/editor/common/model/model';
import { Selection } from 'vs/editor/common/core/selection';
export class MockTextAreaWrapper extends Disposable implements ITextAreaWrapper {
public _value: string;
public _selectionStart: number;
public _selectionEnd: number;
constructor() {
super();
this._value = '';
this._selectionStart = 0;
this._selectionEnd = 0;
}
public getValue(): string {
return this._value;
}
public setValue(reason: string, value: string): void {
this._value = value;
this._selectionStart = this._value.length;
this._selectionEnd = this._value.length;
}
public getSelectionStart(): number {
return this._selectionStart;
}
public getSelectionEnd(): number {
return this._selectionEnd;
}
public setSelectionRange(reason: string, selectionStart: number, selectionEnd: number): void {
if (selectionStart < 0) {
selectionStart = 0;
}
if (selectionStart > this._value.length) {
selectionStart = this._value.length;
}
if (selectionEnd < 0) {
selectionEnd = 0;
}
if (selectionEnd > this._value.length) {
selectionEnd = this._value.length;
}
this._selectionStart = selectionStart;
this._selectionEnd = selectionEnd;
}
}
suite('TextAreaState', () => {
function assertTextAreaState(actual: TextAreaState, value: string, selectionStart: number, selectionEnd: number): void {
let desired = new TextAreaState(value, selectionStart, selectionEnd, null, null);
assert.ok(desired.equals(actual), desired.toString() + ' == ' + actual.toString());
}
test('fromTextArea', () => {
let textArea = new MockTextAreaWrapper();
textArea._value = 'Hello world!';
textArea._selectionStart = 1;
textArea._selectionEnd = 12;
let actual = TextAreaState.EMPTY.readFromTextArea(textArea);
assertTextAreaState(actual, 'Hello world!', 1, 12);
assert.equal(actual.value, 'Hello world!');
assert.equal(actual.selectionStart, 1);
actual = actual.collapseSelection();
assertTextAreaState(actual, 'Hello world!', 12, 12);
textArea.dispose();
});
test('applyToTextArea', () => {
let textArea = new MockTextAreaWrapper();
textArea._value = 'Hello world!';
textArea._selectionStart = 1;
textArea._selectionEnd = 12;
let state = new TextAreaState('Hi world!', 2, 2, null, null);
state.writeToTextArea('test', textArea, false);
assert.equal(textArea._value, 'Hi world!');
assert.equal(textArea._selectionStart, 9);
assert.equal(textArea._selectionEnd, 9);
state = new TextAreaState('Hi world!', 3, 3, null, null);
state.writeToTextArea('test', textArea, false);
assert.equal(textArea._value, 'Hi world!');
assert.equal(textArea._selectionStart, 9);
assert.equal(textArea._selectionEnd, 9);
state = new TextAreaState('Hi world!', 0, 2, null, null);
state.writeToTextArea('test', textArea, true);
assert.equal(textArea._value, 'Hi world!');
assert.equal(textArea._selectionStart, 0);
assert.equal(textArea._selectionEnd, 2);
textArea.dispose();
});
function testDeduceInput(prevState: TextAreaState, value: string, selectionStart: number, selectionEnd: number, expected: string, expectedCharReplaceCnt: number): void {
prevState = prevState || TextAreaState.EMPTY;
let textArea = new MockTextAreaWrapper();
textArea._value = value;
textArea._selectionStart = selectionStart;
textArea._selectionEnd = selectionEnd;
let newState = prevState.readFromTextArea(textArea);
let actual = TextAreaState.deduceInput(prevState, newState, true);
assert.equal(actual.text, expected);
assert.equal(actual.replaceCharCnt, expectedCharReplaceCnt);
textArea.dispose();
}
test('deduceInput - Japanese typing sennsei and accepting', () => {
// manual test:
// - choose keyboard layout: Japanese -> Hiragama
// - type sennsei
// - accept with Enter
// - expected: せんせい
// s
// PREVIOUS STATE: [ <>, selectionStart: 0, selectionEnd: 0, selectionToken: 0]
// CURRENT STATE: [ <>, selectionStart: 0, selectionEnd: 1, selectionToken: 0]
testDeduceInput(
TextAreaState.EMPTY,
'',
0, 1,
'', 0
);
// e
// PREVIOUS STATE: [ <>, selectionStart: 0, selectionEnd: 1, selectionToken: 0]
// CURRENT STATE: [ <せ>, selectionStart: 0, selectionEnd: 1, selectionToken: 0]
testDeduceInput(
new TextAreaState('', 0, 1, null, null),
'せ',
0, 1,
'せ', 1
);
// n
// PREVIOUS STATE: [ <せ>, selectionStart: 0, selectionEnd: 1, selectionToken: 0]
// CURRENT STATE: [ <せn>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
testDeduceInput(
new TextAreaState('せ', 0, 1, null, null),
'せn',
0, 2,
'せn', 1
);
// n
// PREVIOUS STATE: [ <せn>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
// CURRENT STATE: [ <せん>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
testDeduceInput(
new TextAreaState('せn', 0, 2, null, null),
'せん',
0, 2,
'せん', 2
);
// s
// PREVIOUS STATE: [ <せん>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
// CURRENT STATE: [ <せんs>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
testDeduceInput(
new TextAreaState('せん', 0, 2, null, null),
'せんs',
0, 3,
'せんs', 2
);
// e
// PREVIOUS STATE: [ <せんs>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
// CURRENT STATE: [ <せんせ>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんs', 0, 3, null, null),
'せんせ',
0, 3,
'せんせ', 3
);
// no-op? [was recorded]
// PREVIOUS STATE: [ <せんせ>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
// CURRENT STATE: [ <せんせ>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんせ', 0, 3, null, null),
'せんせ',
0, 3,
'せんせ', 3
);
// i
// PREVIOUS STATE: [ <せんせ>, selectionStart: 0, selectionEnd: 3, selectionToken: 0]
// CURRENT STATE: [ <せんせい>, selectionStart: 0, selectionEnd: 4, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんせ', 0, 3, null, null),
'せんせい',
0, 4,
'せんせい', 3
);
// ENTER (accept)
// PREVIOUS STATE: [ <せんせい>, selectionStart: 0, selectionEnd: 4, selectionToken: 0]
// CURRENT STATE: [ <せんせい>, selectionStart: 4, selectionEnd: 4, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんせい', 0, 4, null, null),
'せんせい',
4, 4,
'', 0
);
});
test('deduceInput - Japanese typing sennsei and choosing different suggestion', () => {
// manual test:
// - choose keyboard layout: Japanese -> Hiragama
// - type sennsei
// - arrow down (choose next suggestion)
// - accept with Enter
// - expected: せんせい
// sennsei
// PREVIOUS STATE: [ <せんせい>, selectionStart: 0, selectionEnd: 4, selectionToken: 0]
// CURRENT STATE: [ <せんせい>, selectionStart: 0, selectionEnd: 4, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんせい', 0, 4, null, null),
'せんせい',
0, 4,
'せんせい', 4
);
// arrow down
// CURRENT STATE: [ <先生>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
// PREVIOUS STATE: [ <せんせい>, selectionStart: 0, selectionEnd: 4, selectionToken: 0]
testDeduceInput(
new TextAreaState('せんせい', 0, 4, null, null),
'先生',
0, 2,
'先生', 4
);
// ENTER (accept)
// PREVIOUS STATE: [ <先生>, selectionStart: 0, selectionEnd: 2, selectionToken: 0]
// CURRENT STATE: [ <先生>, selectionStart: 2, selectionEnd: 2, selectionToken: 0]
testDeduceInput(
new TextAreaState('先生', 0, 2, null, null),
'先生',
2, 2,
'', 0
);
});
test('extractNewText - no previous state with selection', () => {
testDeduceInput(
null,
'a',
0, 1,
'a', 0
);
});
test('issue #2586: Replacing selected end-of-line with newline locks up the document', () => {
testDeduceInput(
new TextAreaState(']\n', 1, 2, null, null),
']\n',
2, 2,
'\n', 0
);
});
test('extractNewText - no previous state without selection', () => {
testDeduceInput(
null,
'a',
1, 1,
'a', 0
);
});
test('extractNewText - typing does not cause a selection', () => {
testDeduceInput(
TextAreaState.EMPTY,
'a',
0, 1,
'a', 0
);
});
test('extractNewText - had the textarea empty', () => {
testDeduceInput(
TextAreaState.EMPTY,
'a',
1, 1,
'a', 0
);
});
test('extractNewText - had the entire line selected', () => {
testDeduceInput(
new TextAreaState('Hello world!', 0, 12, null, null),
'H',
1, 1,
'H', 0
);
});
test('extractNewText - had previous text 1', () => {
testDeduceInput(
new TextAreaState('Hello world!', 12, 12, null, null),
'Hello world!a',
13, 13,
'a', 0
);
});
test('extractNewText - had previous text 2', () => {
testDeduceInput(
new TextAreaState('Hello world!', 0, 0, null, null),
'aHello world!',
1, 1,
'a', 0
);
});
test('extractNewText - had previous text 3', () => {
testDeduceInput(
new TextAreaState('Hello world!', 6, 11, null, null),
'Hello other!',
11, 11,
'other', 0
);
});
test('extractNewText - IME', () => {
testDeduceInput(
TextAreaState.EMPTY,
'これは',
3, 3,
'これは', 0
);
});
test('extractNewText - isInOverwriteMode', () => {
testDeduceInput(
new TextAreaState('Hello world!', 0, 0, null, null),
'Aello world!',
1, 1,
'A', 0
);
});
test('extractMacReplacedText - does nothing if there is selection', () => {
testDeduceInput(
new TextAreaState('Hello world!', 5, 5, null, null),
'Hellö world!',
4, 5,
'ö', 0
);
});
test('extractMacReplacedText - does nothing if there is more than one extra char', () => {
testDeduceInput(
new TextAreaState('Hello world!', 5, 5, null, null),
'Hellöö world!',
5, 5,
'öö', 1
);
});
test('extractMacReplacedText - does nothing if there is more than one changed char', () => {
testDeduceInput(
new TextAreaState('Hello world!', 5, 5, null, null),
'Helöö world!',
5, 5,
'öö', 2
);
});
test('extractMacReplacedText', () => {
testDeduceInput(
new TextAreaState('Hello world!', 5, 5, null, null),
'Hellö world!',
5, 5,
'ö', 1
);
});
test('issue #25101 - First key press ignored', () => {
testDeduceInput(
new TextAreaState('a', 0, 1, null, null),
'a',
1, 1,
'a', 0
);
});
test('issue #16520 - Cmd-d of single character followed by typing same character as has no effect', () => {
testDeduceInput(
new TextAreaState('x x', 0, 1, null, null),
'x x',
1, 1,
'x', 0
);
});
test('issue #4271 (example 1) - When inserting an emoji on OSX, it is placed two spaces left of the cursor', () => {
// The OSX emoji inserter inserts emojis at random positions in the text, unrelated to where the cursor is.
testDeduceInput(
new TextAreaState(
[
'some1 text',
'some2 text',
'some3 text',
'some4 text', // cursor is here in the middle of the two spaces
'some5 text',
'some6 text',
'some7 text'
].join('\n'),
42, 42,
null, null
),
[
'so📅me1 text',
'some2 text',
'some3 text',
'some4 text',
'some5 text',
'some6 text',
'some7 text'
].join('\n'),
4, 4,
'📅', 0
);
});
test('issue #4271 (example 2) - When inserting an emoji on OSX, it is placed two spaces left of the cursor', () => {
// The OSX emoji inserter inserts emojis at random positions in the text, unrelated to where the cursor is.
testDeduceInput(
new TextAreaState(
'some1 text',
6, 6,
null, null
),
'some💊1 text',
6, 6,
'💊', 0
);
});
test('issue #4271 (example 3) - When inserting an emoji on OSX, it is placed two spaces left of the cursor', () => {
// The OSX emoji inserter inserts emojis at random positions in the text, unrelated to where the cursor is.
testDeduceInput(
new TextAreaState(
'qwertyu\nasdfghj\nzxcvbnm',
12, 12,
null, null
),
'qwertyu\nasdfghj\nzxcvbnm🎈',
25, 25,
'🎈', 0
);
});
// an example of an emoji missed by the regex but which has the FE0F variant 16 hint
test('issue #4271 (example 4) - When inserting an emoji on OSX, it is placed two spaces left of the cursor', () => {
// The OSX emoji inserter inserts emojis at random positions in the text, unrelated to where the cursor is.
testDeduceInput(
new TextAreaState(
'some1 text',
6, 6,
null, null
),
'some⌨1 text',
6, 6,
'⌨️', 0
);
});
suite('PagedScreenReaderStrategy', () => {
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {
const model = Model.createFromString(lines.join('\n'));
const actual = PagedScreenReaderStrategy.fromEditorSelection(TextAreaState.EMPTY, model, selection);
assert.ok(actual.equals(expected));
model.dispose();
}
test('simple', () => {
testPagedScreenReaderStrategy(
[
'Hello world!'
],
new Selection(1, 13, 1, 13),
new TextAreaState('Hello world!', 12, 12, new Position(1, 13), new Position(1, 13))
);
testPagedScreenReaderStrategy(
[
'Hello world!'
],
new Selection(1, 1, 1, 1),
new TextAreaState('Hello world!', 0, 0, new Position(1, 1), new Position(1, 1))
);
testPagedScreenReaderStrategy(
[
'Hello world!'
],
new Selection(1, 1, 1, 6),
new TextAreaState('Hello world!', 0, 5, new Position(1, 1), new Position(1, 6))
);
});
test('multiline', () => {
testPagedScreenReaderStrategy(
[
'Hello world!',
'How are you?'
],
new Selection(1, 1, 1, 1),
new TextAreaState('Hello world!\nHow are you?', 0, 0, new Position(1, 1), new Position(1, 1))
);
testPagedScreenReaderStrategy(
[
'Hello world!',
'How are you?'
],
new Selection(2, 1, 2, 1),
new TextAreaState('Hello world!\nHow are you?', 13, 13, new Position(2, 1), new Position(2, 1))
);
});
test('page', () => {
testPagedScreenReaderStrategy(
[
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
],
new Selection(1, 1, 1, 1),
new TextAreaState('L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\n', 0, 0, new Position(1, 1), new Position(1, 1))
);
testPagedScreenReaderStrategy(
[
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
],
new Selection(11, 1, 11, 1),
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 0, 0, new Position(11, 1), new Position(11, 1))
);
testPagedScreenReaderStrategy(
[
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
],
new Selection(12, 1, 12, 1),
new TextAreaState('L11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\n', 4, 4, new Position(12, 1), new Position(12, 1))
);
testPagedScreenReaderStrategy(
[
'L1\nL2\nL3\nL4\nL5\nL6\nL7\nL8\nL9\nL10\nL11\nL12\nL13\nL14\nL15\nL16\nL17\nL18\nL19\nL20\nL21'
],
new Selection(21, 1, 21, 1),
new TextAreaState('L21', 0, 0, new Position(21, 1), new Position(21, 1))
);
});
});
});
class SimpleModel implements ISimpleModel {
private _lines: string[];
private _eol: string;
constructor(lines: string[], eol: string) {
this._lines = lines;
this._eol = eol;
}
public getLineMaxColumn(lineNumber: number): number {
return this._lines[lineNumber - 1].length + 1;
}
private _getEndOfLine(eol: EndOfLinePreference): string {
switch (eol) {
case EndOfLinePreference.LF:
return '\n';
case EndOfLinePreference.CRLF:
return '\r\n';
case EndOfLinePreference.TextDefined:
return this._eol;
}
throw new Error('Unknown EOL preference');
}
public getValueInRange(range: Range, eol: EndOfLinePreference): string {
if (Range.isEmpty(range)) {
return '';
}
if (range.startLineNumber === range.endLineNumber) {
return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);
}
var lineEnding = this._getEndOfLine(eol),
startLineIndex = range.startLineNumber - 1,
endLineIndex = range.endLineNumber - 1,
resultLines: string[] = [];
resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));
for (var i = startLineIndex + 1; i < endLineIndex; i++) {
resultLines.push(this._lines[i]);
}
resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));
return resultLines.join(lineEnding);
}
public getLineCount(): number {
return this._lines.length;
}
}

View File

@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import * as dom from 'vs/base/browser/dom';
import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServiceImpl';
import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
import { TestTheme, TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
const themeServiceMock = new TestThemeService();
suite('Decoration Render Options', () => {
test('register and resolve decoration type', () => {
assert.equal(1, 1);
});
});

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
</style>
</head>
<body style="background:black">
<canvas id="my-canvas"></canvas>
<script src="../../../../loader.js"></script>
<script>
require.config({
baseUrl: '../../../../../../out'
});
require(['vs/editor/test/browser/view/minimapFontCreator'], function() {
});
</script>
</body>
</html>

View File

@@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Constants, MinimapCharRenderer } from 'vs/editor/common/view/minimapCharRenderer';
import { MinimapCharRendererFactory } from 'vs/editor/test/common/view/minimapCharRendererFactory';
import { getOrCreateMinimapCharRenderer } from 'vs/editor/common/view/runtimeMinimapCharRenderer';
import { RGBA8 } from 'vs/editor/common/core/rgba';
let canvas = <HTMLCanvasElement>document.getElementById('my-canvas');
let ctx = canvas.getContext('2d');
canvas.style.height = 100 + 'px';
canvas.height = 100;
canvas.width = Constants.CHAR_COUNT * Constants.SAMPLED_CHAR_WIDTH;
canvas.style.width = (Constants.CHAR_COUNT * Constants.SAMPLED_CHAR_WIDTH) + 'px';
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 16px monospace';
for (let chCode = Constants.START_CH_CODE; chCode <= Constants.END_CH_CODE; chCode++) {
ctx.fillText(String.fromCharCode(chCode), (chCode - Constants.START_CH_CODE) * Constants.SAMPLED_CHAR_WIDTH, Constants.SAMPLED_CHAR_HEIGHT);
}
let sampleData = ctx.getImageData(0, 4, Constants.SAMPLED_CHAR_WIDTH * Constants.CHAR_COUNT, Constants.SAMPLED_CHAR_HEIGHT);
let minimapCharRenderer = MinimapCharRendererFactory.create(sampleData.data);
renderImageData(sampleData, 10, 100);
renderMinimapCharRenderer(minimapCharRenderer, 400);
renderMinimapCharRenderer(getOrCreateMinimapCharRenderer(), 600);
function createFakeImageData(width: number, height: number): ImageData {
return {
width: width,
height: height,
data: new Uint8ClampedArray(width * height * Constants.RGBA_CHANNELS_CNT)
};
}
function renderMinimapCharRenderer(minimapCharRenderer: MinimapCharRenderer, y: number): void {
let background = new RGBA8(0, 0, 0, 255);
let color = new RGBA8(255, 255, 255, 255);
{
let x2 = createFakeImageData(Constants.x2_CHAR_WIDTH * Constants.CHAR_COUNT, Constants.x2_CHAR_HEIGHT);
// set the background color
for (let i = 0, len = x2.data.length / 4; i < len; i++) {
x2.data[4 * i + 0] = background.r;
x2.data[4 * i + 1] = background.g;
x2.data[4 * i + 2] = background.b;
x2.data[4 * i + 3] = 255;
}
let dx = 0;
for (let chCode = Constants.START_CH_CODE; chCode <= Constants.END_CH_CODE; chCode++) {
minimapCharRenderer.x2RenderChar(x2, dx, 0, chCode, color, background, false);
dx += Constants.x2_CHAR_WIDTH;
}
renderImageData(x2, 10, y);
}
{
let x1 = createFakeImageData(Constants.x1_CHAR_WIDTH * Constants.CHAR_COUNT, Constants.x1_CHAR_HEIGHT);
// set the background color
for (let i = 0, len = x1.data.length / 4; i < len; i++) {
x1.data[4 * i + 0] = background.r;
x1.data[4 * i + 1] = background.g;
x1.data[4 * i + 2] = background.b;
x1.data[4 * i + 3] = 255;
}
let dx = 0;
for (let chCode = Constants.START_CH_CODE; chCode <= Constants.END_CH_CODE; chCode++) {
minimapCharRenderer.x1RenderChar(x1, dx, 0, chCode, color, background, false);
dx += Constants.x1_CHAR_WIDTH;
}
renderImageData(x1, 10, y + 100);
}
}
(function () {
let r = 'let x2Data = [', offset = 0;
for (let charIndex = 0; charIndex < Constants.CHAR_COUNT; charIndex++) {
let charCode = charIndex + Constants.START_CH_CODE;
r += '\n\n// ' + String.fromCharCode(charCode);
for (let i = 0; i < Constants.x2_CHAR_HEIGHT * Constants.x2_CHAR_WIDTH; i++) {
if (i % 2 === 0) {
r += '\n';
}
r += minimapCharRenderer.x2charData[offset] + ',';
offset++;
}
}
r += '\n\n]';
console.log(r);
})();
(function () {
let r = 'let x1Data = [', offset = 0;
for (let charIndex = 0; charIndex < Constants.CHAR_COUNT; charIndex++) {
let charCode = charIndex + Constants.START_CH_CODE;
r += '\n\n// ' + String.fromCharCode(charCode);
for (let i = 0; i < Constants.x1_CHAR_HEIGHT * Constants.x1_CHAR_WIDTH; i++) {
r += '\n';
r += minimapCharRenderer.x1charData[offset] + ',';
offset++;
}
}
r += '\n\n]';
console.log(r);
})();
function renderImageData(imageData: ImageData, left: number, top: number): void {
let output = '';
var offset = 0;
var PX_SIZE = 15;
for (var i = 0; i < imageData.height; i++) {
for (var j = 0; j < imageData.width; j++) {
var R = imageData.data[offset];
var G = imageData.data[offset + 1];
var B = imageData.data[offset + 2];
var A = imageData.data[offset + 3];
offset += 4;
output += `<div style="position:absolute;top:${PX_SIZE * i}px;left:${PX_SIZE * j}px;width:${PX_SIZE}px;height:${PX_SIZE}px;background:rgba(${R},${G},${B},${A / 256})"></div>`;
}
}
var domNode = document.createElement('div');
domNode.style.position = 'absolute';
domNode.style.top = top + 'px';
domNode.style.left = left + 'px';
domNode.style.width = (imageData.width * PX_SIZE) + 'px';
domNode.style.height = (imageData.height * PX_SIZE) + 'px';
domNode.style.border = '1px solid #ccc';
domNode.style.background = '#000000';
domNode.innerHTML = output;
document.body.appendChild(domNode);
}

View File

@@ -0,0 +1,753 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { RenderedLinesCollection, ILine } from 'vs/editor/browser/view/viewLayer';
class TestLine implements ILine {
_pinged = false;
constructor(public id: string) {
}
onContentChanged(): void {
this._pinged = true;
}
onTokensChanged(): void {
this._pinged = true;
}
}
interface ILinesCollectionState {
startLineNumber: number;
lines: string[];
pinged: boolean[];
}
function assertState(col: RenderedLinesCollection<TestLine>, state: ILinesCollectionState): void {
let actualState: ILinesCollectionState = {
startLineNumber: col.getStartLineNumber(),
lines: [],
pinged: []
};
for (let lineNumber = col.getStartLineNumber(); lineNumber <= col.getEndLineNumber(); lineNumber++) {
actualState.lines.push(col.getLine(lineNumber).id);
actualState.pinged.push(col.getLine(lineNumber)._pinged);
}
assert.deepEqual(actualState, state);
}
suite('RenderedLinesCollection onLinesDeleted', () => {
function testOnModelLinesDeleted(deleteFromLineNumber: number, deleteToLineNumber: number, expectedDeleted: string[], expectedState: ILinesCollectionState): void {
let col = new RenderedLinesCollection<TestLine>(() => new TestLine('new'));
col._set(6, [
new TestLine('old6'),
new TestLine('old7'),
new TestLine('old8'),
new TestLine('old9')
]);
let actualDeleted1 = col.onLinesDeleted(deleteFromLineNumber, deleteToLineNumber);
let actualDeleted: string[] = [];
if (actualDeleted1) {
actualDeleted = actualDeleted1.map(line => line.id);
}
assert.deepEqual(actualDeleted, expectedDeleted);
assertState(col, expectedState);
}
test('A1', () => {
testOnModelLinesDeleted(3, 3, [], {
startLineNumber: 5,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A2', () => {
testOnModelLinesDeleted(3, 4, [], {
startLineNumber: 4,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A3', () => {
testOnModelLinesDeleted(3, 5, [], {
startLineNumber: 3,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A4', () => {
testOnModelLinesDeleted(3, 6, ['old6'], {
startLineNumber: 3,
lines: ['old7', 'old8', 'old9'],
pinged: [false, false, false]
});
});
test('A5', () => {
testOnModelLinesDeleted(3, 7, ['old6', 'old7'], {
startLineNumber: 3,
lines: ['old8', 'old9'],
pinged: [false, false]
});
});
test('A6', () => {
testOnModelLinesDeleted(3, 8, ['old6', 'old7', 'old8'], {
startLineNumber: 3,
lines: ['old9'],
pinged: [false]
});
});
test('A7', () => {
testOnModelLinesDeleted(3, 9, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 3,
lines: [],
pinged: []
});
});
test('A8', () => {
testOnModelLinesDeleted(3, 10, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 3,
lines: [],
pinged: []
});
});
test('B1', () => {
testOnModelLinesDeleted(5, 5, [], {
startLineNumber: 5,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B2', () => {
testOnModelLinesDeleted(5, 6, ['old6'], {
startLineNumber: 5,
lines: ['old7', 'old8', 'old9'],
pinged: [false, false, false]
});
});
test('B3', () => {
testOnModelLinesDeleted(5, 7, ['old6', 'old7'], {
startLineNumber: 5,
lines: ['old8', 'old9'],
pinged: [false, false]
});
});
test('B4', () => {
testOnModelLinesDeleted(5, 8, ['old6', 'old7', 'old8'], {
startLineNumber: 5,
lines: ['old9'],
pinged: [false]
});
});
test('B5', () => {
testOnModelLinesDeleted(5, 9, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 5,
lines: [],
pinged: []
});
});
test('B6', () => {
testOnModelLinesDeleted(5, 10, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 5,
lines: [],
pinged: []
});
});
test('C1', () => {
testOnModelLinesDeleted(6, 6, ['old6'], {
startLineNumber: 6,
lines: ['old7', 'old8', 'old9'],
pinged: [false, false, false]
});
});
test('C2', () => {
testOnModelLinesDeleted(6, 7, ['old6', 'old7'], {
startLineNumber: 6,
lines: ['old8', 'old9'],
pinged: [false, false]
});
});
test('C3', () => {
testOnModelLinesDeleted(6, 8, ['old6', 'old7', 'old8'], {
startLineNumber: 6,
lines: ['old9'],
pinged: [false]
});
});
test('C4', () => {
testOnModelLinesDeleted(6, 9, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: [],
pinged: []
});
});
test('C5', () => {
testOnModelLinesDeleted(6, 10, ['old6', 'old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: [],
pinged: []
});
});
test('D1', () => {
testOnModelLinesDeleted(7, 7, ['old7'], {
startLineNumber: 6,
lines: ['old6', 'old8', 'old9'],
pinged: [false, false, false]
});
});
test('D2', () => {
testOnModelLinesDeleted(7, 8, ['old7', 'old8'], {
startLineNumber: 6,
lines: ['old6', 'old9'],
pinged: [false, false]
});
});
test('D3', () => {
testOnModelLinesDeleted(7, 9, ['old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: ['old6'],
pinged: [false]
});
});
test('D4', () => {
testOnModelLinesDeleted(7, 10, ['old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: ['old6'],
pinged: [false]
});
});
test('E1', () => {
testOnModelLinesDeleted(8, 8, ['old8'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old9'],
pinged: [false, false, false]
});
});
test('E2', () => {
testOnModelLinesDeleted(8, 9, ['old8', 'old9'], {
startLineNumber: 6,
lines: ['old6', 'old7'],
pinged: [false, false]
});
});
test('E3', () => {
testOnModelLinesDeleted(8, 10, ['old8', 'old9'], {
startLineNumber: 6,
lines: ['old6', 'old7'],
pinged: [false, false]
});
});
test('F1', () => {
testOnModelLinesDeleted(9, 9, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8'],
pinged: [false, false, false]
});
});
test('F2', () => {
testOnModelLinesDeleted(9, 10, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8'],
pinged: [false, false, false]
});
});
test('G1', () => {
testOnModelLinesDeleted(10, 10, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('G2', () => {
testOnModelLinesDeleted(10, 11, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('H1', () => {
testOnModelLinesDeleted(11, 13, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
});
suite('RenderedLinesCollection onLineChanged', () => {
function testOnModelLineChanged(changedLineNumber: number, expectedPinged: boolean, expectedState: ILinesCollectionState): void {
let col = new RenderedLinesCollection<TestLine>(() => new TestLine('new'));
col._set(6, [
new TestLine('old6'),
new TestLine('old7'),
new TestLine('old8'),
new TestLine('old9')
]);
let actualPinged = col.onLinesChanged(changedLineNumber, changedLineNumber);
assert.deepEqual(actualPinged, expectedPinged);
assertState(col, expectedState);
}
test('3', () => {
testOnModelLineChanged(3, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('4', () => {
testOnModelLineChanged(4, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('5', () => {
testOnModelLineChanged(5, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('6', () => {
testOnModelLineChanged(6, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [true, false, false, false]
});
});
test('7', () => {
testOnModelLineChanged(7, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, true, false, false]
});
});
test('8', () => {
testOnModelLineChanged(8, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, true, false]
});
});
test('9', () => {
testOnModelLineChanged(9, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, true]
});
});
test('10', () => {
testOnModelLineChanged(10, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('11', () => {
testOnModelLineChanged(11, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
});
suite('RenderedLinesCollection onLinesInserted', () => {
function testOnModelLinesInserted(insertFromLineNumber: number, insertToLineNumber: number, expectedDeleted: string[], expectedState: ILinesCollectionState): void {
let col = new RenderedLinesCollection<TestLine>(() => new TestLine('new'));
col._set(6, [
new TestLine('old6'),
new TestLine('old7'),
new TestLine('old8'),
new TestLine('old9')
]);
let actualDeleted1 = col.onLinesInserted(insertFromLineNumber, insertToLineNumber);
let actualDeleted: string[] = [];
if (actualDeleted1) {
actualDeleted = actualDeleted1.map(line => line.id);
}
assert.deepEqual(actualDeleted, expectedDeleted);
assertState(col, expectedState);
}
test('A1', () => {
testOnModelLinesInserted(3, 3, [], {
startLineNumber: 7,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A2', () => {
testOnModelLinesInserted(3, 4, [], {
startLineNumber: 8,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A3', () => {
testOnModelLinesInserted(3, 5, [], {
startLineNumber: 9,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A4', () => {
testOnModelLinesInserted(3, 6, [], {
startLineNumber: 10,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A5', () => {
testOnModelLinesInserted(3, 7, [], {
startLineNumber: 11,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A6', () => {
testOnModelLinesInserted(3, 8, [], {
startLineNumber: 12,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A7', () => {
testOnModelLinesInserted(3, 9, [], {
startLineNumber: 13,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('A8', () => {
testOnModelLinesInserted(3, 10, [], {
startLineNumber: 14,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B1', () => {
testOnModelLinesInserted(5, 5, [], {
startLineNumber: 7,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B2', () => {
testOnModelLinesInserted(5, 6, [], {
startLineNumber: 8,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B3', () => {
testOnModelLinesInserted(5, 7, [], {
startLineNumber: 9,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B4', () => {
testOnModelLinesInserted(5, 8, [], {
startLineNumber: 10,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B5', () => {
testOnModelLinesInserted(5, 9, [], {
startLineNumber: 11,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B6', () => {
testOnModelLinesInserted(5, 10, [], {
startLineNumber: 12,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C1', () => {
testOnModelLinesInserted(6, 6, [], {
startLineNumber: 7,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C2', () => {
testOnModelLinesInserted(6, 7, [], {
startLineNumber: 8,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C3', () => {
testOnModelLinesInserted(6, 8, [], {
startLineNumber: 9,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C4', () => {
testOnModelLinesInserted(6, 9, [], {
startLineNumber: 10,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C5', () => {
testOnModelLinesInserted(6, 10, [], {
startLineNumber: 11,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('D1', () => {
testOnModelLinesInserted(7, 7, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'new', 'old7', 'old8'],
pinged: [false, false, false, false]
});
});
test('D2', () => {
testOnModelLinesInserted(7, 8, ['old8', 'old9'], {
startLineNumber: 6,
lines: ['old6', 'new', 'new', 'old7'],
pinged: [false, false, false, false]
});
});
test('D3', () => {
testOnModelLinesInserted(7, 9, ['old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: ['old6'],
pinged: [false]
});
});
test('D4', () => {
testOnModelLinesInserted(7, 10, ['old7', 'old8', 'old9'], {
startLineNumber: 6,
lines: ['old6'],
pinged: [false]
});
});
test('E1', () => {
testOnModelLinesInserted(8, 8, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'new', 'old8'],
pinged: [false, false, false, false]
});
});
test('E2', () => {
testOnModelLinesInserted(8, 9, ['old8', 'old9'], {
startLineNumber: 6,
lines: ['old6', 'old7'],
pinged: [false, false]
});
});
test('E3', () => {
testOnModelLinesInserted(8, 10, ['old8', 'old9'], {
startLineNumber: 6,
lines: ['old6', 'old7'],
pinged: [false, false]
});
});
test('F1', () => {
testOnModelLinesInserted(9, 9, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8'],
pinged: [false, false, false]
});
});
test('F2', () => {
testOnModelLinesInserted(9, 10, ['old9'], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8'],
pinged: [false, false, false]
});
});
test('G1', () => {
testOnModelLinesInserted(10, 10, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('G2', () => {
testOnModelLinesInserted(10, 11, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('H1', () => {
testOnModelLinesInserted(11, 13, [], {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
});
suite('RenderedLinesCollection onTokensChanged', () => {
function testOnModelTokensChanged(changedFromLineNumber: number, changedToLineNumber: number, expectedPinged: boolean, expectedState: ILinesCollectionState): void {
let col = new RenderedLinesCollection<TestLine>(() => new TestLine('new'));
col._set(6, [
new TestLine('old6'),
new TestLine('old7'),
new TestLine('old8'),
new TestLine('old9')
]);
let actualPinged = col.onTokensChanged([{ fromLineNumber: changedFromLineNumber, toLineNumber: changedToLineNumber }]);
assert.deepEqual(actualPinged, expectedPinged);
assertState(col, expectedState);
}
test('A', () => {
testOnModelTokensChanged(3, 3, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('B', () => {
testOnModelTokensChanged(3, 5, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('C', () => {
testOnModelTokensChanged(3, 6, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [true, false, false, false]
});
});
test('D', () => {
testOnModelTokensChanged(6, 6, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [true, false, false, false]
});
});
test('E', () => {
testOnModelTokensChanged(5, 10, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [true, true, true, true]
});
});
test('F', () => {
testOnModelTokensChanged(8, 9, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, true, true]
});
});
test('G', () => {
testOnModelTokensChanged(8, 11, true, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, true, true]
});
});
test('H', () => {
testOnModelTokensChanged(10, 10, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
test('I', () => {
testOnModelTokensChanged(10, 11, false, {
startLineNumber: 6,
lines: ['old6', 'old7', 'old8', 'old9'],
pinged: [false, false, false, false]
});
});
});