Merge from vscode 64980ea1f3f532c82bb6c28d27bba9ef2c5b4463 (#7206)

* Merge from vscode 64980ea1f3f532c82bb6c28d27bba9ef2c5b4463

* fix config changes

* fix strictnull checks
This commit is contained in:
Anthony Dresser
2019-09-15 22:38:26 -07:00
committed by GitHub
parent fa6c52699e
commit ea0f9e6ce9
1226 changed files with 21541 additions and 17633 deletions

View File

@@ -14,10 +14,6 @@ suite('RangeMap', () => {
rangeMap = new RangeMap();
});
teardown(() => {
rangeMap.dispose();
});
test('intersection', () => {
assert.deepEqual(Range.intersect({ start: 0, end: 0 }, { start: 0, end: 0 }), { start: 0, end: 0 });
assert.deepEqual(Range.intersect({ start: 0, end: 0 }, { start: 5, end: 5 }), { start: 0, end: 0 });
@@ -346,4 +342,4 @@ suite('RangeMap', () => {
assert.equal(rangeMap.positionAt(4), -1);
});
});
});
});

View File

@@ -8,6 +8,7 @@ import { ITreeNode, ITreeRenderer, IAsyncDataSource } from 'vs/base/browser/ui/t
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { hasClass } from 'vs/base/browser/dom';
import { timeout } from 'vs/base/common/async';
interface Element {
id: string;
@@ -26,104 +27,89 @@ function find(elements: Element[] | undefined, id: string): Element {
throw new Error('element not found');
}
class Renderer implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
}
class IdentityProvider implements IIdentityProvider<Element> {
getId(element: Element) {
return element.id;
}
}
class VirtualDelegate implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
}
class DataSource implements IAsyncDataSource<Element, Element> {
hasChildren(element: Element): boolean {
return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise<Element[]> {
return Promise.resolve(element.children || []);
}
}
class Model {
constructor(readonly root: Element) { }
get(id: string): Element {
return find(this.root.children, id);
}
}
suite('AsyncDataTree', function () {
test('Collapse state should be preserved across refresh calls', async () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const delegate = new class implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
};
const renderer = new class implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
};
const dataSource = new class implements IAsyncDataSource<Element, Element> {
hasChildren(element: Element): boolean {
return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise<Element[]> {
return Promise.resolve(element.children || []);
}
};
const identityProvider = new class implements IIdentityProvider<Element> {
getId(element: Element) {
return element.id;
}
};
const root: Element = {
const model = new Model({
id: 'root',
children: [{
id: 'a'
}]
};
});
const _: (id: string) => Element = find.bind(null, root.children);
const tree = new AsyncDataTree<Element, Element>(container, delegate, [renderer], dataSource, { identityProvider });
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], new DataSource(), { identityProvider: new IdentityProvider() });
tree.layout(200);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 0);
await tree.setInput(root);
await tree.setInput(model.root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
_('a').children = [
model.get('a').children = [
{ id: 'aa' },
{ id: 'ab' },
{ id: 'ac' }
];
await tree.updateChildren(root);
await tree.updateChildren(model.root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
await tree.expand(_('a'));
await tree.expand(model.get('a'));
assert.equal(container.querySelectorAll('.monaco-list-row').length, 4);
_('a').children = [];
await tree.updateChildren(root);
model.get('a').children = [];
await tree.updateChildren(model.root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
});
test('issue #68648', async () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const delegate = new class implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
};
const renderer = new class implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
};
const getChildrenCalls: string[] = [];
const dataSource = new class implements IAsyncDataSource<Element, Element> {
@@ -136,25 +122,17 @@ suite('AsyncDataTree', function () {
}
};
const identityProvider = new class implements IIdentityProvider<Element> {
getId(element: Element) {
return element.id;
}
};
const root: Element = {
const model = new Model({
id: 'root',
children: [{
id: 'a'
}]
};
});
const _: (id: string) => Element = find.bind(null, root.children);
const tree = new AsyncDataTree<Element, Element>(container, delegate, [renderer], dataSource, { identityProvider });
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, { identityProvider: new IdentityProvider() });
tree.layout(200);
await tree.setInput(root);
await tree.setInput(model.root);
assert.deepStrictEqual(getChildrenCalls, ['root']);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
@@ -162,8 +140,8 @@ suite('AsyncDataTree', function () {
assert(!hasClass(twistie, 'collapsed'));
assert(tree.getNode().children[0].collapsed);
_('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
await tree.updateChildren(root);
model.get('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
await tree.updateChildren(model.root);
assert.deepStrictEqual(getChildrenCalls, ['root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
@@ -171,8 +149,8 @@ suite('AsyncDataTree', function () {
assert(hasClass(twistie, 'collapsed'));
assert(tree.getNode().children[0].collapsed);
_('a').children = [];
await tree.updateChildren(root);
model.get('a').children = [];
await tree.updateChildren(model.root);
assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
@@ -180,8 +158,8 @@ suite('AsyncDataTree', function () {
assert(!hasClass(twistie, 'collapsed'));
assert(tree.getNode().children[0].collapsed);
_('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
await tree.updateChildren(root);
model.get('a').children = [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }];
await tree.updateChildren(model.root);
assert.deepStrictEqual(getChildrenCalls, ['root', 'root', 'root', 'root']);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
@@ -192,26 +170,6 @@ suite('AsyncDataTree', function () {
test('issue #67722 - once resolved, refreshed collapsed nodes should only get children when expanded', async () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const delegate = new class implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
};
const renderer = new class implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
};
const getChildrenCalls: string[] = [];
const dataSource = new class implements IAsyncDataSource<Element, Element> {
@@ -224,131 +182,66 @@ suite('AsyncDataTree', function () {
}
};
const identityProvider = new class implements IIdentityProvider<Element> {
getId(element: Element) {
return element.id;
}
};
const root: Element = {
const model = new Model({
id: 'root',
children: [{
id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }]
}]
};
});
const _: (id: string) => Element = find.bind(null, root.children);
const tree = new AsyncDataTree<Element, Element>(container, delegate, [renderer], dataSource, { identityProvider });
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, { identityProvider: new IdentityProvider() });
tree.layout(200);
await tree.setInput(root);
assert(tree.getNode(_('a')).collapsed);
await tree.setInput(model.root);
assert(tree.getNode(model.get('a')).collapsed);
assert.deepStrictEqual(getChildrenCalls, ['root']);
await tree.expand(_('a'));
assert(!tree.getNode(_('a')).collapsed);
await tree.expand(model.get('a'));
assert(!tree.getNode(model.get('a')).collapsed);
assert.deepStrictEqual(getChildrenCalls, ['root', 'a']);
tree.collapse(_('a'));
assert(tree.getNode(_('a')).collapsed);
tree.collapse(model.get('a'));
assert(tree.getNode(model.get('a')).collapsed);
assert.deepStrictEqual(getChildrenCalls, ['root', 'a']);
await tree.updateChildren();
assert(tree.getNode(_('a')).collapsed);
assert(tree.getNode(model.get('a')).collapsed);
assert.deepStrictEqual(getChildrenCalls, ['root', 'a', 'root'], 'a should not be refreshed, since it\' collapsed');
});
test('resolved collapsed nodes which lose children should lose twistie as well', async () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const delegate = new class implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
};
const renderer = new class implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
};
const dataSource = new class implements IAsyncDataSource<Element, Element> {
hasChildren(element: Element): boolean {
return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise<Element[]> {
return Promise.resolve(element.children || []);
}
};
const identityProvider = new class implements IIdentityProvider<Element> {
getId(element: Element) {
return element.id;
}
};
const root: Element = {
const model = new Model({
id: 'root',
children: [{
id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }]
}]
};
});
const _: (id: string) => Element = find.bind(null, root.children);
const tree = new AsyncDataTree<Element, Element>(container, delegate, [renderer], dataSource, { identityProvider });
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], new DataSource(), { identityProvider: new IdentityProvider() });
tree.layout(200);
await tree.setInput(root);
await tree.expand(_('a'));
await tree.setInput(model.root);
await tree.expand(model.get('a'));
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(!tree.getNode(_('a')).collapsed);
assert(!tree.getNode(model.get('a')).collapsed);
tree.collapse(_('a'));
_('a').children = [];
await tree.updateChildren(root);
tree.collapse(model.get('a'));
model.get('a').children = [];
await tree.updateChildren(model.root);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
assert(tree.getNode(_('a')).collapsed);
assert(tree.getNode(model.get('a')).collapsed);
});
test('support default collapse state per element', async () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const delegate = new class implements IListVirtualDelegate<Element> {
getHeight() { return 20; }
getTemplateId(element: Element): string { return 'default'; }
};
const renderer = new class implements ITreeRenderer<Element, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(element: ITreeNode<Element, void>, index: number, templateData: HTMLElement): void {
templateData.textContent = element.element.id;
}
disposeTemplate(templateData: HTMLElement): void {
// noop
}
};
const getChildrenCalls: string[] = [];
const dataSource = new class implements IAsyncDataSource<Element, Element> {
@@ -361,22 +254,139 @@ suite('AsyncDataTree', function () {
}
};
const root: Element = {
const model = new Model({
id: 'root',
children: [{
id: 'a', children: [{ id: 'aa' }, { id: 'ab' }, { id: 'ac' }]
}]
};
});
const _: (id: string) => Element = find.bind(null, root.children);
const tree = new AsyncDataTree<Element, Element>(container, delegate, [renderer], dataSource, {
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, {
collapseByDefault: el => el.id !== 'a'
});
tree.layout(200);
await tree.setInput(root);
assert(!tree.getNode(_('a')).collapsed);
await tree.setInput(model.root);
assert(!tree.getNode(model.get('a')).collapsed);
assert.deepStrictEqual(getChildrenCalls, ['root', 'a']);
});
});
test('issue #80098 - concurrent refresh and expand', async () => {
const container = document.createElement('div');
const calls: Function[] = [];
const dataSource = new class implements IAsyncDataSource<Element, Element> {
hasChildren(element: Element): boolean {
return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise<Element[]> {
return new Promise(c => calls.push(() => c(element.children)));
}
};
const model = new Model({
id: 'root',
children: [{
id: 'a', children: [{
id: 'aa'
}]
}]
});
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, { identityProvider: new IdentityProvider() });
tree.layout(200);
const pSetInput = tree.setInput(model.root);
calls.pop()!(); // resolve getChildren(root)
await pSetInput;
const pUpdateChildrenA = tree.updateChildren(model.get('a'));
const pExpandA = tree.expand(model.get('a'));
assert.equal(calls.length, 1, 'expand(a) still hasn\'t called getChildren(a)');
calls.pop()!();
assert.equal(calls.length, 0, 'no pending getChildren calls');
await pUpdateChildrenA;
assert.equal(calls.length, 0, 'expand(a) should not have forced a second refresh');
const result = await pExpandA;
assert.equal(result, true, 'expand(a) should be done');
});
test('issue #80098 - first expand should call getChildren', async () => {
const container = document.createElement('div');
const calls: Function[] = [];
const dataSource = new class implements IAsyncDataSource<Element, Element> {
hasChildren(element: Element): boolean {
return !!element.children && element.children.length > 0;
}
getChildren(element: Element): Promise<Element[]> {
return new Promise(c => calls.push(() => c(element.children)));
}
};
const model = new Model({
id: 'root',
children: [{
id: 'a', children: [{
id: 'aa'
}]
}]
});
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, { identityProvider: new IdentityProvider() });
tree.layout(200);
const pSetInput = tree.setInput(model.root);
calls.pop()!(); // resolve getChildren(root)
await pSetInput;
const pExpandA = tree.expand(model.get('a'));
assert.equal(calls.length, 1, 'expand(a) should\'ve called getChildren(a)');
let race = await Promise.race([pExpandA.then(() => 'expand'), timeout(1).then(() => 'timeout')]);
assert.equal(race, 'timeout', 'expand(a) should not be yet done');
calls.pop()!();
assert.equal(calls.length, 0, 'no pending getChildren calls');
race = await Promise.race([pExpandA.then(() => 'expand'), timeout(1).then(() => 'timeout')]);
assert.equal(race, 'expand', 'expand(a) should now be done');
});
test('issue #78388 - tree should react to hasChildren toggles', async () => {
const container = document.createElement('div');
const model = new Model({
id: 'root',
children: [{
id: 'a'
}]
});
const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], new DataSource(), { identityProvider: new IdentityProvider() });
tree.layout(200);
await tree.setInput(model.root);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
let twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
model.get('a').children = [{ id: 'aa' }];
await tree.updateChildren(model.get('a'), false);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(hasClass(twistie, 'collapsible'));
assert(hasClass(twistie, 'collapsed'));
model.get('a').children = [];
await tree.updateChildren(model.get('a'), false);
assert.equal(container.querySelectorAll('.monaco-list-row').length, 1);
twistie = container.querySelector('.monaco-list-row:first-child .monaco-tl-twistie') as HTMLElement;
assert(!hasClass(twistie, 'collapsible'));
assert(!hasClass(twistie, 'collapsed'));
});
});

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { compress, ICompressedTreeElement, ICompressedTreeNode, decompress, CompressedTreeModel } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { compress, ICompressedTreeElement, ICompressedTreeNode, decompress, CompressedObjectTreeModel } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { Iterator } from 'vs/base/common/iterator';
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
import { ISpliceable } from 'vs/base/common/sequence';
@@ -305,7 +305,7 @@ suite('CompressedObjectTree', function () {
test('ctor', () => {
const list: ITreeNode<ICompressedTreeNode<number>>[] = [];
const model = new CompressedTreeModel<number>(toSpliceable(list));
const model = new CompressedObjectTreeModel<number>('test', toSpliceable(list));
assert(model);
assert.equal(list.length, 0);
assert.equal(model.size, 0);
@@ -313,7 +313,7 @@ suite('CompressedObjectTree', function () {
test('flat', () => {
const list: ITreeNode<ICompressedTreeNode<number>>[] = [];
const model = new CompressedTreeModel<number>(toSpliceable(list));
const model = new CompressedObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{ element: 0 },
@@ -340,7 +340,7 @@ suite('CompressedObjectTree', function () {
test('nested', () => {
const list: ITreeNode<ICompressedTreeNode<number>>[] = [];
const model = new CompressedTreeModel<number>(toSpliceable(list));
const model = new CompressedObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{
@@ -376,7 +376,7 @@ suite('CompressedObjectTree', function () {
test('compressed', () => {
const list: ITreeNode<ICompressedTreeNode<number>>[] = [];
const model = new CompressedTreeModel<number>(toSpliceable(list));
const model = new CompressedObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{
@@ -427,4 +427,4 @@ suite('CompressedObjectTree', function () {
assert.equal(model.size, 8);
});
});
});
});

View File

@@ -63,7 +63,7 @@ suite('DataTree', function () {
}
};
tree = new DataTree<E, E>(container, delegate, [renderer], dataSource, {
tree = new DataTree<E, E>('test', container, delegate, [renderer], dataSource, {
identityProvider
});
tree.layout(200);
@@ -145,4 +145,4 @@ suite('DataTree', function () {
assert.deepEqual(tree.getSelection(), [root.children![1]]);
assert.deepEqual(tree.getFocus(), [root.children![2]]);
});
});
});

View File

@@ -7,7 +7,7 @@ import * as assert from 'assert';
import { ITreeNode, ITreeFilter, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
import { ISpliceable } from 'vs/base/common/sequence';
import { Iterator } from 'vs/base/common/iterator';
import { IndexTreeModel } from 'vs/base/browser/ui/tree/indexTreeModel';
import { IndexTreeModel, IIndexTreeNode } from 'vs/base/browser/ui/tree/indexTreeModel';
function toSpliceable<T>(arr: T[]): ISpliceable<T> {
return {
@@ -25,14 +25,14 @@ suite('IndexTreeModel', function () {
test('ctor', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
assert(model);
assert.equal(list.length, 0);
});
test('insert', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{ element: 0 },
@@ -54,7 +54,7 @@ suite('IndexTreeModel', function () {
test('deep insert', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -91,7 +91,7 @@ suite('IndexTreeModel', function () {
test('deep insert collapsed', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -119,7 +119,7 @@ suite('IndexTreeModel', function () {
test('delete', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{ element: 0 },
@@ -144,7 +144,7 @@ suite('IndexTreeModel', function () {
test('nested delete', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -178,7 +178,7 @@ suite('IndexTreeModel', function () {
test('deep delete', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -206,7 +206,7 @@ suite('IndexTreeModel', function () {
test('hidden delete', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -231,7 +231,7 @@ suite('IndexTreeModel', function () {
test('collapse', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -262,7 +262,7 @@ suite('IndexTreeModel', function () {
test('expand', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -302,7 +302,7 @@ suite('IndexTreeModel', function () {
test('collapse should recursively adjust visible count', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -333,6 +333,67 @@ suite('IndexTreeModel', function () {
assert.deepEqual(toArray(list), [1, 11, 2]);
});
test('setCollapsible', () => {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
element: 0, children: Iterator.fromArray([
{ element: 10 }
])
}
]));
assert.deepEqual(list.length, 2);
model.setCollapsible([0], false);
assert.deepEqual(list.length, 2);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, false);
assert.deepEqual(list[0].collapsed, false);
assert.deepEqual(list[1].element, 10);
assert.deepEqual(list[1].collapsible, false);
assert.deepEqual(list[1].collapsed, false);
model.setCollapsed([0], true);
assert.deepEqual(list.length, 1);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, false);
assert.deepEqual(list[0].collapsed, true);
model.setCollapsed([0], false);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, false);
assert.deepEqual(list[0].collapsed, false);
assert.deepEqual(list[1].element, 10);
assert.deepEqual(list[1].collapsible, false);
assert.deepEqual(list[1].collapsed, false);
model.setCollapsible([0], true);
assert.deepEqual(list.length, 2);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, true);
assert.deepEqual(list[0].collapsed, false);
assert.deepEqual(list[1].element, 10);
assert.deepEqual(list[1].collapsible, false);
assert.deepEqual(list[1].collapsed, false);
model.setCollapsed([0], true);
assert.deepEqual(list.length, 1);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, true);
assert.deepEqual(list[0].collapsed, true);
model.setCollapsed([0], false);
assert.deepEqual(list[0].element, 0);
assert.deepEqual(list[0].collapsible, true);
assert.deepEqual(list[0].collapsed, false);
assert.deepEqual(list[1].element, 10);
assert.deepEqual(list[1].collapsible, false);
assert.deepEqual(list[1].collapsed, false);
});
test('simple filter', function () {
const list: ITreeNode<number>[] = [];
const filter = new class implements ITreeFilter<number> {
@@ -341,7 +402,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<number>(toSpliceable(list), -1, { filter });
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1, { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -375,7 +436,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<number>(toSpliceable(list), -1, { filter });
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1, { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -398,7 +459,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<number>(toSpliceable(list), -1, { filter });
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1, { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -437,7 +498,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<string>(toSpliceable(list), 'root', { filter });
const model = new IndexTreeModel<string>('test', toSpliceable(list), 'root', { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -483,7 +544,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<string>(toSpliceable(list), 'root', { filter });
const model = new IndexTreeModel<string>('test', toSpliceable(list), 'root', { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -529,7 +590,7 @@ suite('IndexTreeModel', function () {
}
};
const model = new IndexTreeModel<string>(toSpliceable(list), 'root', { filter });
const model = new IndexTreeModel<string>('test', toSpliceable(list), 'root', { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -576,8 +637,8 @@ suite('IndexTreeModel', function () {
suite('getNodeLocation', function () {
test('simple', function () {
const list: ITreeNode<number>[] = [];
const model = new IndexTreeModel<number>(toSpliceable(list), -1);
const list: IIndexTreeNode<number>[] = [];
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1);
model.splice([0], 0, Iterator.fromArray([
{
@@ -600,14 +661,14 @@ suite('IndexTreeModel', function () {
});
test('with filter', function () {
const list: ITreeNode<number>[] = [];
const list: IIndexTreeNode<number>[] = [];
const filter = new class implements ITreeFilter<number> {
filter(element: number): TreeVisibility {
return element % 2 === 0 ? TreeVisibility.Visible : TreeVisibility.Hidden;
}
};
const model = new IndexTreeModel<number>(toSpliceable(list), -1, { filter });
const model = new IndexTreeModel<number>('test', toSpliceable(list), -1, { filter });
model.splice([0], 0, Iterator.fromArray([
{
@@ -629,4 +690,4 @@ suite('IndexTreeModel', function () {
assert.deepEqual(model.getNodeLocation(list[3]), [0, 5]);
});
});
});
});

View File

@@ -6,8 +6,9 @@
import * as assert from 'assert';
import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
import { ObjectTree, CompressibleObjectTree, ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree';
import { Iterator } from 'vs/base/common/iterator';
import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
suite('ObjectTree', function () {
suite('TreeNavigator', function () {
@@ -35,7 +36,7 @@ suite('ObjectTree', function () {
disposeTemplate(): void { }
};
tree = new ObjectTree<number>(container, delegate, [renderer], { filter: { filter: (el) => filter(el) } });
tree = new ObjectTree<number>('test', container, delegate, [renderer], { filter: { filter: (el) => filter(el) } });
tree.layout(200);
});
@@ -81,8 +82,6 @@ suite('ObjectTree', function () {
assert.equal(navigator.previous(), null);
assert.equal(navigator.next(), 0);
assert.equal(navigator.next(), 10);
assert.equal(navigator.parent(), 0);
assert.equal(navigator.parent(), null);
assert.equal(navigator.first(), 0);
assert.equal(navigator.last(), 2);
});
@@ -112,7 +111,6 @@ suite('ObjectTree', function () {
assert.equal(navigator.previous(), 0);
assert.equal(navigator.previous(), null);
assert.equal(navigator.next(), 0);
assert.equal(navigator.parent(), null);
assert.equal(navigator.first(), 0);
assert.equal(navigator.last(), 2);
});
@@ -147,8 +145,6 @@ suite('ObjectTree', function () {
assert.equal(navigator.previous(), null);
assert.equal(navigator.next(), 0);
assert.equal(navigator.next(), 10);
assert.equal(navigator.parent(), 0);
assert.equal(navigator.parent(), null);
assert.equal(navigator.first(), 0);
assert.equal(navigator.last(), 2);
});
@@ -180,8 +176,6 @@ suite('ObjectTree', function () {
assert.equal(navigator.previous(), null);
assert.equal(navigator.next(), 0);
assert.equal(navigator.next(), 10);
assert.equal(navigator.parent(), 0);
assert.equal(navigator.parent(), null);
assert.equal(navigator.first(), 0);
assert.equal(navigator.last(), 2);
});
@@ -214,7 +208,7 @@ suite('ObjectTree', function () {
}
};
const tree = new ObjectTree<number>(container, delegate, [renderer], { identityProvider });
const tree = new ObjectTree<number>('test', container, delegate, [renderer], { identityProvider });
tree.layout(200);
tree.setChildren(null, [{ element: 0 }, { element: 1 }, { element: 2 }, { element: 3 }]);
@@ -224,4 +218,161 @@ suite('ObjectTree', function () {
tree.setChildren(null, [{ element: 100 }, { element: 101 }, { element: 102 }, { element: 103 }]);
assert.deepStrictEqual(tree.getFocus(), [101]);
});
});
});
function toArray(list: NodeList): Node[] {
const result: Node[] = [];
list.forEach(node => result.push(node));
return result;
}
suite('CompressibleObjectTree', function () {
class Delegate implements IListVirtualDelegate<number> {
getHeight() { return 20; }
getTemplateId(): string { return 'default'; }
}
class Renderer implements ICompressibleTreeRenderer<number, void, HTMLElement> {
readonly templateId = 'default';
renderTemplate(container: HTMLElement): HTMLElement {
return container;
}
renderElement(node: ITreeNode<number, void>, _: number, templateData: HTMLElement): void {
templateData.textContent = `${node.element}`;
}
renderCompressedElements(node: ITreeNode<ICompressedTreeNode<number>, void>, _: number, templateData: HTMLElement): void {
templateData.textContent = `${node.element.elements.join('/')}`;
}
disposeTemplate(): void { }
}
test('empty', function () {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const tree = new CompressibleObjectTree<number>('test', container, new Delegate(), [new Renderer()]);
tree.layout(200);
const rows = toArray(container.querySelectorAll('.monaco-tl-contents'));
assert.equal(rows.length, 0);
});
test('simple', function () {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const tree = new CompressibleObjectTree<number>('test', container, new Delegate(), [new Renderer()]);
tree.layout(200);
tree.setChildren(null, [
{
element: 0, children: [
{ element: 10 },
{ element: 11 },
{ element: 12 },
]
},
{ element: 1 },
{ element: 2 }
]);
const rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['0', '10', '11', '12', '1', '2']);
});
test('compressed', () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const tree = new CompressibleObjectTree<number>('test', container, new Delegate(), [new Renderer()]);
tree.layout(200);
tree.setChildren(null, Iterator.fromArray([
{
element: 1, children: Iterator.fromArray([{
element: 11, children: Iterator.fromArray([{
element: 111, children: Iterator.fromArray([
{ element: 1111 },
{ element: 1112 },
{ element: 1113 },
])
}])
}])
}
]));
let rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']);
tree.setChildren(11, Iterator.fromArray([
{ element: 111 },
{ element: 112 },
{ element: 113 },
]));
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11', '111', '112', '113']);
tree.setChildren(113, Iterator.fromArray([
{ element: 1131 }
]));
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11', '111', '112', '113/1131']);
tree.setChildren(1131, Iterator.fromArray([
{ element: 1132 }
]));
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11', '111', '112', '113/1131/1132']);
tree.setChildren(1131, Iterator.fromArray([
{ element: 1132 },
{ element: 1133 },
]));
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11', '111', '112', '113/1131', '1132', '1133']);
});
test('enableCompression', () => {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';
const tree = new CompressibleObjectTree<number>('test', container, new Delegate(), [new Renderer()]);
tree.layout(200);
assert.equal(tree.isCompressionEnabled(), true);
tree.setChildren(null, Iterator.fromArray([
{
element: 1, children: Iterator.fromArray([{
element: 11, children: Iterator.fromArray([{
element: 111, children: Iterator.fromArray([
{ element: 1111 },
{ element: 1112 },
{ element: 1113 },
])
}])
}])
}
]));
let rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']);
tree.setCompressionEnabled(false);
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1', '11', '111', '1111', '1112', '1113']);
tree.setCompressionEnabled(true);
rows = toArray(container.querySelectorAll('.monaco-tl-contents')).map(row => row.textContent);
assert.deepEqual(rows, ['1/11/111', '1111', '1112', '1113']);
});
});

View File

@@ -25,7 +25,7 @@ suite('ObjectTreeModel', function () {
test('ctor', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list));
const model = new ObjectTreeModel<number>('test', toSpliceable(list));
assert(model);
assert.equal(list.length, 0);
assert.equal(model.size, 0);
@@ -33,7 +33,7 @@ suite('ObjectTreeModel', function () {
test('flat', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list));
const model = new ObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{ element: 0 },
@@ -60,7 +60,7 @@ suite('ObjectTreeModel', function () {
test('nested', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list));
const model = new ObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{
@@ -96,7 +96,7 @@ suite('ObjectTreeModel', function () {
test('setChildren on collapsed node', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list));
const model = new ObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, Iterator.fromArray([
{ element: 0, collapsed: true }
@@ -117,7 +117,7 @@ suite('ObjectTreeModel', function () {
test('setChildren on expanded, unrevealed node', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list));
const model = new ObjectTreeModel<number>('test', toSpliceable(list));
model.setChildren(null, [
{
@@ -143,7 +143,7 @@ suite('ObjectTreeModel', function () {
test('collapse state is preserved with strict identity', () => {
const list: ITreeNode<string>[] = [];
const model = new ObjectTreeModel<string>(toSpliceable(list), { collapseByDefault: true });
const model = new ObjectTreeModel<string>('test', toSpliceable(list), { collapseByDefault: true });
const data = [{ element: 'father', children: [{ element: 'child' }] }];
model.setChildren(null, data);
@@ -173,7 +173,7 @@ suite('ObjectTreeModel', function () {
let compare: (a: string, b: string) => number = (a, b) => a < b ? -1 : 1;
const list: ITreeNode<string>[] = [];
const model = new ObjectTreeModel<string>(toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } });
const model = new ObjectTreeModel<string>('test', toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } });
const data = [
{ element: 'cars', children: [{ element: 'sedan' }, { element: 'convertible' }, { element: 'compact' }] },
{ element: 'airplanes', children: [{ element: 'passenger' }, { element: 'jet' }] },
@@ -188,7 +188,7 @@ suite('ObjectTreeModel', function () {
let compare: (a: string, b: string) => number = () => 0;
const list: ITreeNode<string>[] = [];
const model = new ObjectTreeModel<string>(toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } });
const model = new ObjectTreeModel<string>('test', toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } });
const data = [
{ element: 'cars', children: [{ element: 'sedan' }, { element: 'convertible' }, { element: 'compact' }] },
{ element: 'airplanes', children: [{ element: 'passenger' }, { element: 'jet' }] },
@@ -223,7 +223,7 @@ suite('ObjectTreeModel', function () {
test('expandTo', () => {
const list: ITreeNode<number>[] = [];
const model = new ObjectTreeModel<number>(toSpliceable(list), { collapseByDefault: true });
const model = new ObjectTreeModel<number>('test', toSpliceable(list), { collapseByDefault: true });
model.setChildren(null, [
{
@@ -241,4 +241,4 @@ suite('ObjectTreeModel', function () {
model.expandTo(1000);
assert.deepEqual(toArray(list), [0, 10, 100, 1000, 11, 12, 1, 2]);
});
});
});

View File

@@ -392,6 +392,10 @@ suite('Filters', () => {
test('patternPos isn\'t working correctly #79815', function () {
assertMatches(':p'.substr(1), 'prop', '^prop', fuzzyScore, { patternPos: 0 });
assertMatches(':p', 'prop', '^prop', fuzzyScore, { patternPos: 1 });
assertMatches(':p', 'prop', undefined, fuzzyScore, { patternPos: 2 });
assertMatches(':p', 'proP', 'pro^P', fuzzyScore, { patternPos: 1, wordPos: 1 });
assertMatches(':p', 'aprop', 'a^prop', fuzzyScore, { patternPos: 1, firstMatchCanBeWeak: true });
assertMatches(':p', 'aprop', undefined, fuzzyScore, { patternPos: 1, firstMatchCanBeWeak: false });
});
function assertTopScore(filter: typeof fuzzyScore, pattern: string, expected: number, ...words: string[]) {

View File

@@ -812,10 +812,10 @@ suite('Glob', () => {
'{**/bar/**,**/baz/**}': true,
'**/bulb/**': false
}, ['foo', 'bar', 'baz'], [
['bar/foo', '**/foo/**'],
['foo/bar', '{**/bar/**,**/baz/**}'],
['bar/nope', null!]
]);
['bar/foo', '**/foo/**'],
['foo/bar', '{**/bar/**,**/baz/**}'],
['bar/nope', null!]
]);
const siblings = ['baz', 'baz.zip', 'nope'];
const hasSibling = (name: string) => siblings.indexOf(name) !== -1;
@@ -823,15 +823,15 @@ suite('Glob', () => {
'**/foo/**': { when: '$(basename).zip' },
'**/bar/**': true
}, ['bar'], [
['bar/foo', null!],
['bar/foo/baz', null!],
['bar/foo/nope', null!],
['foo/bar', '**/bar/**'],
], [
null!,
hasSibling,
hasSibling
]);
['bar/foo', null!],
['bar/foo/baz', null!],
['bar/foo/nope', null!],
['foo/bar', '**/bar/**'],
], [
null!,
hasSibling,
hasSibling
]);
});
function testOptimizationForBasenames(pattern: string | glob.IExpression, basenameTerms: string[], matches: [string, string | boolean][], siblingsFns: ((name: string) => boolean)[] = []) {
@@ -917,11 +917,11 @@ suite('Glob', () => {
// '{**/bar/bar/**,**/baz/bar/**}': true,
'**/bulb/bar/**': false
}, ['*/foo/bar'], [
[nativeSep('bar/foo/bar'), '**/foo/bar/**'],
// Not supported
// [nativeSep('foo/bar/bar'), '{**/bar/bar/**,**/baz/bar/**}'],
[nativeSep('/foo/bar/nope'), null!]
]);
[nativeSep('bar/foo/bar'), '**/foo/bar/**'],
// Not supported
// [nativeSep('foo/bar/bar'), '{**/bar/bar/**,**/baz/bar/**}'],
[nativeSep('/foo/bar/nope'), null!]
]);
const siblings = ['baz', 'baz.zip', 'nope'];
let hasSibling = (name: string) => siblings.indexOf(name) !== -1;
@@ -929,15 +929,15 @@ suite('Glob', () => {
'**/foo/123/**': { when: '$(basename).zip' },
'**/bar/123/**': true
}, ['*/bar/123'], [
[nativeSep('bar/foo/123'), null!],
[nativeSep('bar/foo/123/baz'), null!],
[nativeSep('bar/foo/123/nope'), null!],
[nativeSep('foo/bar/123'), '**/bar/123/**'],
], [
null!,
hasSibling,
hasSibling
]);
[nativeSep('bar/foo/123'), null!],
[nativeSep('bar/foo/123/baz'), null!],
[nativeSep('bar/foo/123/nope'), null!],
[nativeSep('foo/bar/123'), '**/bar/123/**'],
], [
null!,
hasSibling,
hasSibling
]);
});
function testOptimizationForPaths(pattern: string | glob.IExpression, pathTerms: string[], matches: [string, string | boolean][], siblingsFns: ((name: string) => boolean)[] = []) {

View File

@@ -18,6 +18,8 @@ suite('Keytar', () => {
const name = `VSCode Test ${Math.floor(Math.random() * 1e9)}`;
try {
await keytar.setPassword(name, 'foo', 'bar');
assert.equal(await keytar.findPassword(name), 'bar');
assert.equal((await keytar.findCredentials(name)).length, 1);
assert.equal(await keytar.getPassword(name, 'foo'), 'bar');
await keytar.deletePassword(name, 'foo');
assert.equal(await keytar.getPassword(name, 'foo'), undefined);