123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- export const MAX_FOLDING_REGIONS = 0xFFFF;
- export const MAX_LINE_NUMBER = 0xFFFFFF;
- const MASK_INDENT = 0xFF000000;
- export class FoldingRegions {
- constructor(startIndexes, endIndexes, types) {
- if (startIndexes.length !== endIndexes.length || startIndexes.length > MAX_FOLDING_REGIONS) {
- throw new Error('invalid startIndexes or endIndexes size');
- }
- this._startIndexes = startIndexes;
- this._endIndexes = endIndexes;
- this._collapseStates = new Uint32Array(Math.ceil(startIndexes.length / 32));
- this._types = types;
- this._parentsComputed = false;
- }
- ensureParentIndices() {
- if (!this._parentsComputed) {
- this._parentsComputed = true;
- let parentIndexes = [];
- let isInsideLast = (startLineNumber, endLineNumber) => {
- let index = parentIndexes[parentIndexes.length - 1];
- return this.getStartLineNumber(index) <= startLineNumber && this.getEndLineNumber(index) >= endLineNumber;
- };
- for (let i = 0, len = this._startIndexes.length; i < len; i++) {
- let startLineNumber = this._startIndexes[i];
- let endLineNumber = this._endIndexes[i];
- if (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) {
- throw new Error('startLineNumber or endLineNumber must not exceed ' + MAX_LINE_NUMBER);
- }
- while (parentIndexes.length > 0 && !isInsideLast(startLineNumber, endLineNumber)) {
- parentIndexes.pop();
- }
- let parentIndex = parentIndexes.length > 0 ? parentIndexes[parentIndexes.length - 1] : -1;
- parentIndexes.push(i);
- this._startIndexes[i] = startLineNumber + ((parentIndex & 0xFF) << 24);
- this._endIndexes[i] = endLineNumber + ((parentIndex & 0xFF00) << 16);
- }
- }
- }
- get length() {
- return this._startIndexes.length;
- }
- getStartLineNumber(index) {
- return this._startIndexes[index] & MAX_LINE_NUMBER;
- }
- getEndLineNumber(index) {
- return this._endIndexes[index] & MAX_LINE_NUMBER;
- }
- getType(index) {
- return this._types ? this._types[index] : undefined;
- }
- hasTypes() {
- return !!this._types;
- }
- isCollapsed(index) {
- let arrayIndex = (index / 32) | 0;
- let bit = index % 32;
- return (this._collapseStates[arrayIndex] & (1 << bit)) !== 0;
- }
- setCollapsed(index, newState) {
- let arrayIndex = (index / 32) | 0;
- let bit = index % 32;
- let value = this._collapseStates[arrayIndex];
- if (newState) {
- this._collapseStates[arrayIndex] = value | (1 << bit);
- }
- else {
- this._collapseStates[arrayIndex] = value & ~(1 << bit);
- }
- }
- setCollapsedAllOfType(type, newState) {
- let hasChanged = false;
- if (this._types) {
- for (let i = 0; i < this._types.length; i++) {
- if (this._types[i] === type) {
- this.setCollapsed(i, newState);
- hasChanged = true;
- }
- }
- }
- return hasChanged;
- }
- toRegion(index) {
- return new FoldingRegion(this, index);
- }
- getParentIndex(index) {
- this.ensureParentIndices();
- let parent = ((this._startIndexes[index] & MASK_INDENT) >>> 24) + ((this._endIndexes[index] & MASK_INDENT) >>> 16);
- if (parent === MAX_FOLDING_REGIONS) {
- return -1;
- }
- return parent;
- }
- contains(index, line) {
- return this.getStartLineNumber(index) <= line && this.getEndLineNumber(index) >= line;
- }
- findIndex(line) {
- let low = 0, high = this._startIndexes.length;
- if (high === 0) {
- return -1; // no children
- }
- while (low < high) {
- let mid = Math.floor((low + high) / 2);
- if (line < this.getStartLineNumber(mid)) {
- high = mid;
- }
- else {
- low = mid + 1;
- }
- }
- return low - 1;
- }
- findRange(line) {
- let index = this.findIndex(line);
- if (index >= 0) {
- let endLineNumber = this.getEndLineNumber(index);
- if (endLineNumber >= line) {
- return index;
- }
- index = this.getParentIndex(index);
- while (index !== -1) {
- if (this.contains(index, line)) {
- return index;
- }
- index = this.getParentIndex(index);
- }
- }
- return -1;
- }
- toString() {
- let res = [];
- for (let i = 0; i < this.length; i++) {
- res[i] = `[${this.isCollapsed(i) ? '+' : '-'}] ${this.getStartLineNumber(i)}/${this.getEndLineNumber(i)}`;
- }
- return res.join(', ');
- }
- }
- export class FoldingRegion {
- constructor(ranges, index) {
- this.ranges = ranges;
- this.index = index;
- }
- get startLineNumber() {
- return this.ranges.getStartLineNumber(this.index);
- }
- get endLineNumber() {
- return this.ranges.getEndLineNumber(this.index);
- }
- get regionIndex() {
- return this.index;
- }
- get parentIndex() {
- return this.ranges.getParentIndex(this.index);
- }
- get isCollapsed() {
- return this.ranges.isCollapsed(this.index);
- }
- containedBy(range) {
- return range.startLineNumber <= this.startLineNumber && range.endLineNumber >= this.endLineNumber;
- }
- containsLine(lineNumber) {
- return this.startLineNumber <= lineNumber && lineNumber <= this.endLineNumber;
- }
- }
|