text: /*---------------------------------------------------------------------------------------------
   *  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;
      }
  }
  