text: /* --------------------------------------------------------------------------------------------
   * Copyright (c) Microsoft Corporation. All rights reserved.
   * Licensed under the MIT License. See License.txt in the project root for license information.
   * ------------------------------------------------------------------------------------------ */
  'use strict';
  var FullTextDocument = /** @class */ (function () {
      function FullTextDocument(uri, languageId, version, content) {
          this._uri = uri;
          this._languageId = languageId;
          this._version = version;
          this._content = content;
          this._lineOffsets = undefined;
      }
      Object.defineProperty(FullTextDocument.prototype, "uri", {
          get: function () {
              return this._uri;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(FullTextDocument.prototype, "languageId", {
          get: function () {
              return this._languageId;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(FullTextDocument.prototype, "version", {
          get: function () {
              return this._version;
          },
          enumerable: true,
          configurable: true
      });
      FullTextDocument.prototype.getText = function (range) {
          if (range) {
              var start = this.offsetAt(range.start);
              var end = this.offsetAt(range.end);
              return this._content.substring(start, end);
          }
          return this._content;
      };
      FullTextDocument.prototype.update = function (changes, version) {
          for (var _i = 0, changes_1 = changes; _i < changes_1.length; _i++) {
              var change = changes_1[_i];
              if (FullTextDocument.isIncremental(change)) {
                  // makes sure start is before end
                  var range = getWellformedRange(change.range);
                  // update content
                  var startOffset = this.offsetAt(range.start);
                  var endOffset = this.offsetAt(range.end);
                  this._content = this._content.substring(0, startOffset) + change.text + this._content.substring(endOffset, this._content.length);
                  // update the offsets
                  var startLine = Math.max(range.start.line, 0);
                  var endLine = Math.max(range.end.line, 0);
                  var lineOffsets = this._lineOffsets;
                  var addedLineOffsets = computeLineOffsets(change.text, false, startOffset);
                  if (endLine - startLine === addedLineOffsets.length) {
                      for (var i = 0, len = addedLineOffsets.length; i < len; i++) {
                          lineOffsets[i + startLine + 1] = addedLineOffsets[i];
                      }
                  }
                  else {
                      if (addedLineOffsets.length < 10000) {
                          lineOffsets.splice.apply(lineOffsets, [startLine + 1, endLine - startLine].concat(addedLineOffsets));
                      }
                      else { // avoid too many arguments for splice
                          this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1));
                      }
                  }
                  var diff = change.text.length - (endOffset - startOffset);
                  if (diff !== 0) {
                      for (var i = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i < len; i++) {
                          lineOffsets[i] = lineOffsets[i] + diff;
                      }
                  }
              }
              else if (FullTextDocument.isFull(change)) {
                  this._content = change.text;
                  this._lineOffsets = undefined;
              }
              else {
                  throw new Error('Unknown change event received');
              }
          }
          this._version = version;
      };
      FullTextDocument.prototype.getLineOffsets = function () {
          if (this._lineOffsets === undefined) {
              this._lineOffsets = computeLineOffsets(this._content, true);
          }
          return this._lineOffsets;
      };
      FullTextDocument.prototype.positionAt = function (offset) {
          offset = Math.max(Math.min(offset, this._content.length), 0);
          var lineOffsets = this.getLineOffsets();
          var low = 0, high = lineOffsets.length;
          if (high === 0) {
              return { line: 0, character: offset };
          }
          while (low < high) {
              var mid = Math.floor((low + high) / 2);
              if (lineOffsets[mid] > offset) {
                  high = mid;
              }
              else {
                  low = mid + 1;
              }
          }
          // low is the least x for which the line offset is larger than the current offset
          // or array.length if no line offset is larger than the current offset
          var line = low - 1;
          return { line: line, character: offset - lineOffsets[line] };
      };
      FullTextDocument.prototype.offsetAt = function (position) {
          var lineOffsets = this.getLineOffsets();
          if (position.line >= lineOffsets.length) {
              return this._content.length;
          }
          else if (position.line < 0) {
              return 0;
          }
          var lineOffset = lineOffsets[position.line];
          var nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length;
          return Math.max(Math.min(lineOffset + position.character, nextLineOffset), lineOffset);
      };
      Object.defineProperty(FullTextDocument.prototype, "lineCount", {
          get: function () {
              return this.getLineOffsets().length;
          },
          enumerable: true,
          configurable: true
      });
      FullTextDocument.isIncremental = function (event) {
          var candidate = event;
          return candidate !== undefined && candidate !== null &&
              typeof candidate.text === 'string' && candidate.range !== undefined &&
              (candidate.rangeLength === undefined || typeof candidate.rangeLength === 'number');
      };
      FullTextDocument.isFull = function (event) {
          var candidate = event;
          return candidate !== undefined && candidate !== null &&
              typeof candidate.text === 'string' && candidate.range === undefined && candidate.rangeLength === undefined;
      };
      return FullTextDocument;
  }());
  export var TextDocument;
  (function (TextDocument) {
      /**
       * Creates a new text document.
       *
       * @param uri The document's uri.
       * @param languageId  The document's language Id.
       * @param version The document's initial version number.
       * @param content The document's content.
       */
      function create(uri, languageId, version, content) {
          return new FullTextDocument(uri, languageId, version, content);
      }
      TextDocument.create = create;
      /**
       * Updates a TextDocument by modifing its content.
       *
       * @param document the document to update. Only documents created by TextDocument.create are valid inputs.
       * @param changes the changes to apply to the document.
       * @returns The updated TextDocument. Note: That's the same document instance passed in as first parameter.
       *
       */
      function update(document, changes, version) {
          if (document instanceof FullTextDocument) {
              document.update(changes, version);
              return document;
          }
          else {
              throw new Error('TextDocument.update: document must be created by TextDocument.create');
          }
      }
      TextDocument.update = update;
      function applyEdits(document, edits) {
          var text = document.getText();
          var sortedEdits = mergeSort(edits.map(getWellformedEdit), function (a, b) {
              var diff = a.range.start.line - b.range.start.line;
              if (diff === 0) {
                  return a.range.start.character - b.range.start.character;
              }
              return diff;
          });
          var lastModifiedOffset = text.length;
          for (var i = sortedEdits.length - 1; i >= 0; i--) {
              var e = sortedEdits[i];
              var startOffset = document.offsetAt(e.range.start);
              var endOffset = document.offsetAt(e.range.end);
              if (endOffset <= lastModifiedOffset) {
                  text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
              }
              else {
                  throw new Error('Overlapping edit');
              }
              lastModifiedOffset = startOffset;
          }
          return text;
      }
      TextDocument.applyEdits = applyEdits;
  })(TextDocument || (TextDocument = {}));
  function mergeSort(data, compare) {
      if (data.length <= 1) {
          // sorted
          return data;
      }
      var p = (data.length / 2) | 0;
      var left = data.slice(0, p);
      var right = data.slice(p);
      mergeSort(left, compare);
      mergeSort(right, compare);
      var leftIdx = 0;
      var rightIdx = 0;
      var i = 0;
      while (leftIdx < left.length && rightIdx < right.length) {
          var ret = compare(left[leftIdx], right[rightIdx]);
          if (ret <= 0) {
              // smaller_equal -> take left to preserve order
              data[i++] = left[leftIdx++];
          }
          else {
              // greater -> take right
              data[i++] = right[rightIdx++];
          }
      }
      while (leftIdx < left.length) {
          data[i++] = left[leftIdx++];
      }
      while (rightIdx < right.length) {
          data[i++] = right[rightIdx++];
      }
      return data;
  }
  function computeLineOffsets(text, isAtLineStart, textOffset) {
      if (textOffset === void 0) { textOffset = 0; }
      var result = isAtLineStart ? [textOffset] : [];
      for (var i = 0; i < text.length; i++) {
          var ch = text.charCodeAt(i);
          if (ch === 13 /* CarriageReturn */ || ch === 10 /* LineFeed */) {
              if (ch === 13 /* CarriageReturn */ && i + 1 < text.length && text.charCodeAt(i + 1) === 10 /* LineFeed */) {
                  i++;
              }
              result.push(textOffset + i + 1);
          }
      }
      return result;
  }
  function getWellformedRange(range) {
      var start = range.start;
      var end = range.end;
      if (start.line > end.line || (start.line === end.line && start.character > end.character)) {
          return { start: end, end: start };
      }
      return range;
  }
  function getWellformedEdit(textEdit) {
      var range = getWellformedRange(textEdit.range);
      if (range !== textEdit.range) {
          return { newText: textEdit.newText, range: range };
      }
      return textEdit;
  }
  