<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { ISpliceable } from 'vs/base/common/sequence';
import { Iterator, ISequence } from 'vs/base/common/iterator';
import { Emitter, Event } from 'vs/base/common/event';

export interface ITreeElement<T> {
	readonly element: T;
	readonly children?: Iterator<ITreeElement<T>> | ITreeElement<T>[];
	readonly collapsible?: boolean;
	readonly collapsed?: boolean;
}

export interface ITreeNode<T, TFilterData = void> {
	readonly parent: ITreeNode<T, TFilterData> | undefined;
	readonly element: T;
	readonly children: ITreeNode<T, TFilterData>[];
	readonly depth: number;
	readonly collapsible: boolean;
	readonly collapsed: boolean;
	readonly revealedCount: number;
	readonly filterData: TFilterData | undefined;
}

interface IMutableTreeNode<T, TFilterData> extends ITreeNode<T, TFilterData> {
	readonly parent: IMutableTreeNode<T, TFilterData> | undefined;
	readonly children: IMutableTreeNode<T, TFilterData>[];
	collapsible: boolean;
	collapsed: boolean;
	revealedCount: number;
	filterData: TFilterData | undefined;
	visible: boolean;
}

export const enum Visibility {
	Hidden,
	Visible,
	Recurse // TODO@joao come up with a better name
}

export interface IFilterResult<TFilterData> {
	visibility: Visibility;
	data: TFilterData;
}

function isFilterResult<T>(obj: any): obj is IFilterResult<T> {
	return typeof obj === 'object' && 'visibility' in obj && 'data' in obj;
}

export interface ITreeFilter<T, TFilterData = void> {
	filter(element: T): boolean | Visibility | IFilterResult<TFilterData>;
}

function treeNodeToElement<T>(node: IMutableTreeNode<T, any>): ITreeElement<T> {
	const { element, collapsed } = node;
	const children = Iterator.map(Iterator.fromArray(node.children), treeNodeToElement);

	return { element, children, collapsed };
}

function getVisibleState(visibility: Visibility): boolean | undefined {
	switch (visibility) {
		case Visibility.Hidden: return false;
		case Visibility.Visible: return true;
		case Visibility.Recurse: return undefined;
	}
}

export interface ITreeModelOptions<T, TFilterData = void> {
	filter?: ITreeFilter<T, TFilterData>;
}

export class TreeModel<T, TFilterData = void> {

	static getNodeLocation<T>(node: ITreeNode<T, any>): number[] {
		const location = [];

		while (node.parent) {
			location.push(node.parent.children.indexOf(node));
			node = node.parent;
		}

		return location.reverse();
	}

	private root: IMutableTreeNode<T, TFilterData> = {
		parent: undefined,
		element: undefined,
		children: [],
		depth: 0,
		collapsible: false,
		collapsed: false,
		revealedCount: 0,
		visible: true,<commit_msg>tree: perf<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { ISpliceable } from 'vs/base/common/sequence';
import { Iterator, ISequence } from 'vs/base/common/iterator';
import { Emitter, Event } from 'vs/base/common/event';

export interface ITreeElement<T> {
	readonly element: T;
	readonly children?: Iterator<ITreeElement<T>> | ITreeElement<T>[];
	readonly collapsible?: boolean;
	readonly collapsed?: boolean;
}

export interface ITreeNode<T, TFilterData = void> {
	readonly parent: ITreeNode<T, TFilterData> | undefined;
	readonly element: T;
	readonly children: ITreeNode<T, TFilterData>[];
	readonly depth: number;
	readonly collapsible: boolean;
	readonly collapsed: boolean;
	readonly revealedCount: number;
	readonly filterData: TFilterData | undefined;
}

interface IMutableTreeNode<T, TFilterData> extends ITreeNode<T, TFilterData> {
	readonly parent: IMutableTreeNode<T, TFilterData> | undefined;
	readonly children: IMutableTreeNode<T, TFilterData>[];
	collapsible: boolean;
	collapsed: boolean;
	revealedCount: number;
	filterData: TFilterData | undefined;
	visible: boolean;
}

export const enum Visibility {
	Hidden,
	Visible,
	Recurse // TODO@joao come up with a better name
}

export interface IFilterResult<TFilterData> {
	visibility: Visibility;
	data: TFilterData;
}

function isFilterResult<T>(obj: any): obj is IFilterResult<T> {
	return typeof obj === 'object' && 'visibility' in obj && 'data' in obj;
}

export interface ITreeFilter<T, TFilterData = void> {
	filter(element: T): boolean | Visibility | IFilterResult<TFilterData>;
}

function treeNodeToElement<T>(node: IMutableTreeNode<T, any>): ITreeElement<T> {
	const { element, collapsed } = node;
	const children = Iterator.map(Iterator.fromArray(node.children), treeNodeToElement);

	return { element, children, collapsed };
}

function getVisibleState(visibility: Visibility): boolean | undefined {
	switch (visibility) {
		case Visibility.Hidden: return false;
		case Visibility.Visible: return true;
		case Visibility.Recurse: return undefined;
	}
}

export interface ITreeModelOptions<T, TFilterData = void> {
	filter?: ITreeFilter<T, TFilterData>;
}

export class TreeModel<T, TFilterData = void> {

	// TODO@joao perf!
	static getNodeLocation<T>(node: ITreeNode<T, any>): number[] {
		const location = [];

		while (node.parent) {
			location.push(node.parent.children.indexOf(node));
			node = node.parent;
		}

		return location.reverse();
	}

	private root: IMutableTreeNode<T, TFilterData> = {
		parent: undefined,
		element: undefined,
		children: [],
		depth: 0,
		collapsible: false,
		collapsed: false,
		revealedCount: 0,
		visible: true,
{'fraction_non_alphanumeric': 0.17087214225232852, 'fraction_numerical': 0.0006773920406435225, 'mean_word_length': 3.793831168831169, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3004008', 'n_tokens_mistral': 1826, 'n_tokens_neox': 1719, 'n_words': 482}