<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 { SelectionRangeProvider } from 'vs/editor/common/modes';
import { ITextModel } from 'vs/editor/common/model';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';

export class BracketSelectionRangeProvider implements SelectionRangeProvider {

	provideSelectionRanges(model: ITextModel, position: Position): Promise<Range[]> {
		const bucket: Range[] = [];
		const ranges = new Map<string, Range[]>();
		return new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, model, position, ranges))
			.then(() => new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, model, position, ranges, bucket)))
			.then(() => bucket);
	}

	private static readonly _maxDuration = 90;

	private static _bracketsRightYield(resolve: () => void, model: ITextModel, pos: Position, ranges: Map<string, Range[]>): void {
		const counts = new Map<string, number>();
		const t1 = Date.now();
		while (true) {
			if (!pos) {
				resolve();
				break;
			}
			let bracket = model.findNextBracket(pos);
			if (!bracket) {
				resolve();
				break;
			}
			let d = Date.now() - t1;
			if (d > BracketSelectionRangeProvider._maxDuration) {
				setTimeout(() => BracketSelectionRangeProvider._bracketsRightYield(resolve, model, pos, ranges));
				break;
			}
			const key = bracket.close;
			if (bracket.isOpen) {
				// wait for closing
				let val = counts.has(key) ? counts.get(key) : 0;
				counts.set(key, val + 1);
			} else {
				// process closing
				let val = counts.has(key) ? counts.get(key) : 0;
				val -= 1;
				counts.set(key, Math.max(0, val));
				if (val < 0) {
					let arr = ranges.get(key);
					if (!arr) {
						arr = [];
						ranges.set(key, arr);
					}
					arr.push(bracket.range);
				}
			}
			pos = bracket.range.getEndPosition();
		}
	}

	private static _bracketsLeftYield(resolve: () => void, model: ITextModel, pos: Position, ranges: Map<string, Range[]>, bucket: Range[]): void {
		const counts = new Map<string, number>();
		const t1 = Date.now();
		while (true) {
			if (!pos) {
				resolve();
				break;
			}
			let bracket = model.findPrevBracket(pos);
			if (!bracket) {
				resolve();
				break;
			}
			let d = Date.now() - t1;
			if (d > BracketSelectionRangeProvider._maxDuration) {
				setTimeout(() => BracketSelectionRangeProvider._bracketsLeftYield(resolve, model, pos, ranges, bucket));
				break;
			}
			const key = bracket.close;
			if (!bracket.isOpen) {
				// wait for opening
				let val = counts.has(key) ? counts.get(key) : 0;
				counts.set(key, val + 1);
			} else {
				// opening
				let val = counts.has(key) ? counts.get(key) : 0;
				val -= 1;
				counts.set(key, Math.max(0, val));
				if (val < 0) {
					let arr = ranges.get(key);
					if (arr && arr.length > 0) {
						let closing = arr.shift();
						bucket.push(Range.fromPositions(bracket.range.getEndPosition(), closing!.getStartPosition()));
						bucket.push(Range.fromPositions(bracket.range.getStartPosition(), closing!.getEndPosition()));<commit_msg>take max 4 * 30ms<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 { SelectionRangeProvider } from 'vs/editor/common/modes';
import { ITextModel } from 'vs/editor/common/model';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';

export class BracketSelectionRangeProvider implements SelectionRangeProvider {

	provideSelectionRanges(model: ITextModel, position: Position): Promise<Range[]> {
		const bucket: Range[] = [];
		const ranges = new Map<string, Range[]>();
		return new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges))
			.then(() => new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket)))
			.then(() => bucket);
	}

	private static readonly _maxDuration = 30;
	private static readonly _maxRounds = 2;

	private static _bracketsRightYield(resolve: () => void, round: number, model: ITextModel, pos: Position, ranges: Map<string, Range[]>): void {
		const counts = new Map<string, number>();
		const t1 = Date.now();
		while (true) {
			if (round >= BracketSelectionRangeProvider._maxRounds) {
				resolve();
				break;
			}
			if (!pos) {
				resolve();
				break;
			}
			let bracket = model.findNextBracket(pos);
			if (!bracket) {
				resolve();
				break;
			}
			let d = Date.now() - t1;
			if (d > BracketSelectionRangeProvider._maxDuration) {
				setTimeout(() => BracketSelectionRangeProvider._bracketsRightYield(resolve, round + 1, model, pos, ranges));
				break;
			}
			const key = bracket.close;
			if (bracket.isOpen) {
				// wait for closing
				let val = counts.has(key) ? counts.get(key) : 0;
				counts.set(key, val + 1);
			} else {
				// process closing
				let val = counts.has(key) ? counts.get(key) : 0;
				val -= 1;
				counts.set(key, Math.max(0, val));
				if (val < 0) {
					let arr = ranges.get(key);
					if (!arr) {
						arr = [];
						ranges.set(key, arr);
					}
					arr.push(bracket.range);
				}
			}
			pos = bracket.range.getEndPosition();
		}
	}

	private static _bracketsLeftYield(resolve: () => void, round: number, model: ITextModel, pos: Position, ranges: Map<string, Range[]>, bucket: Range[]): void {
		const counts = new Map<string, number>();
		const t1 = Date.now();
		while (true) {
			if (round >= BracketSelectionRangeProvider._maxRounds && ranges.size === 0) {
				resolve();
				break;
			}
			if (!pos) {
				resolve();
				break;
			}
			let bracket = model.findPrevBracket(pos);
			if (!bracket) {
				resolve();
				break;
			}
			let d = Date.now() - t1;
			if (d > BracketSelectionRangeProvider._maxDuration) {
				setTimeout(() => BracketSelectionRangeProvider._bracketsLeftYield(resolve, round + 1, model, pos, ranges, bucket));
				break;
			}
			const key = bracket.close;
			if (!bracket.isOpen) {
				// wait for opening
				let val = counts.has(key) ? counts.get(key) : 0;
				counts.set(key, val + 1);
			} else {
				// opening
				let val = counts.has(key) ? counts.get(key) : 0;
				val -= 1;
				counts.set(key, Math.max(0, val));
				if (val < 0) {
					let arr = ranges.get(key);
					if (arr) {
						let closing = arr.shift();
						if (arr.length === 0) {
							ranges.delete(key);
						}
						bucket.push(Range.fromPositions(bracket.range.getEndPosition(), closing!.getStartPosition()));
						bucket.push(Range.fromPositions(bracket.range.getStartPosition(), closing!.getEndPosition()));
{'fraction_non_alphanumeric': 0.1921427583344861, 'fraction_numerical': 0.006501590814773828, 'mean_word_length': 2.7191358024691357, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 38, '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': '4769786', 'n_tokens_mistral': 2686, 'n_tokens_neox': 2168, 'n_words': 553}