/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { LinkedList } from '../../../base/common/linkedList.js'; import { Position } from '../../common/core/position.js'; import { Range } from '../../common/core/range.js'; export class BracketSelectionRangeProvider { provideSelectionRanges(model, positions) { return __awaiter(this, void 0, void 0, function* () { const result = []; for (const position of positions) { const bucket = []; result.push(bucket); const ranges = new Map(); yield new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges)); yield new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket)); } return result; }); } static _bracketsRightYield(resolve, round, model, pos, ranges) { const counts = new Map(); const t1 = Date.now(); while (true) { if (round >= BracketSelectionRangeProvider._maxRounds) { resolve(); break; } if (!pos) { resolve(); break; } let bracket = model.bracketPairs.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[0]; 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 list = ranges.get(key); if (!list) { list = new LinkedList(); ranges.set(key, list); } list.push(bracket.range); } } pos = bracket.range.getEndPosition(); } } static _bracketsLeftYield(resolve, round, model, pos, ranges, bucket) { const counts = new Map(); const t1 = Date.now(); while (true) { if (round >= BracketSelectionRangeProvider._maxRounds && ranges.size === 0) { resolve(); break; } if (!pos) { resolve(); break; } let bracket = model.bracketPairs.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[0]; 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 list = ranges.get(key); if (list) { let closing = list.shift(); if (list.size === 0) { ranges.delete(key); } const innerBracket = Range.fromPositions(bracket.range.getEndPosition(), closing.getStartPosition()); const outerBracket = Range.fromPositions(bracket.range.getStartPosition(), closing.getEndPosition()); bucket.push({ range: innerBracket }); bucket.push({ range: outerBracket }); BracketSelectionRangeProvider._addBracketLeading(model, outerBracket, bucket); } } } pos = bracket.range.getStartPosition(); } } static _addBracketLeading(model, bracket, bucket) { if (bracket.startLineNumber === bracket.endLineNumber) { return; } // xxxxxxxx { // // } const startLine = bracket.startLineNumber; const column = model.getLineFirstNonWhitespaceColumn(startLine); if (column !== 0 && column !== bracket.startColumn) { bucket.push({ range: Range.fromPositions(new Position(startLine, column), bracket.getEndPosition()) }); bucket.push({ range: Range.fromPositions(new Position(startLine, 1), bracket.getEndPosition()) }); } // xxxxxxxx // { // // } const aboveLine = startLine - 1; if (aboveLine > 0) { const column = model.getLineFirstNonWhitespaceColumn(aboveLine); if (column === bracket.startColumn && column !== model.getLineLastNonWhitespaceColumn(aboveLine)) { bucket.push({ range: Range.fromPositions(new Position(aboveLine, column), bracket.getEndPosition()) }); bucket.push({ range: Range.fromPositions(new Position(aboveLine, 1), bracket.getEndPosition()) }); } } } } BracketSelectionRangeProvider._maxDuration = 30; BracketSelectionRangeProvider._maxRounds = 2;