This commit is contained in:
nik
2025-10-03 22:27:28 +03:00
parent 829fad0e17
commit 871cf7e792
16520 changed files with 2967597 additions and 3 deletions

View File

@@ -0,0 +1,191 @@
/**
* A tagging type for string properties that are actually URIs.
*/
export type DocumentUri = string;
/**
* Position in a text document expressed as zero-based line and character offset.
* The offsets are based on a UTF-16 string representation. So a string of the form
* `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀`
* is 1 and the character offset of b is 3 since `𐐀` is represented using two code
* units in UTF-16.
*
* Positions are line end character agnostic. So you can not specify a position that
* denotes `\r|\n` or `\n|` where `|` represents the character offset.
*/
export interface Position {
/**
* Line position in a document (zero-based).
*
* If a line number is greater than the number of lines in a document, it
* defaults back to the number of lines in the document.
* If a line number is negative, it defaults to 0.
*
* The above two properties are implementation specific.
*/
line: number;
/**
* Character offset on a line in a document (zero-based).
*
* The meaning of this offset is determined by the negotiated
* `PositionEncodingKind`.
*
* If the character value is greater than the line length it defaults back
* to the line length. This property is implementation specific.
*/
character: number;
}
/**
* A range in a text document expressed as (zero-based) start and end positions.
*
* If you want to specify a range that contains a line including the line ending
* character(s) then use an end position denoting the start of the next line.
* For example:
* ```ts
* {
* start: { line: 5, character: 23 }
* end : { line 6, character : 0 }
* }
* ```
*/
export interface Range {
/**
* The range's start position.
*/
start: Position;
/**
* The range's end position.
*/
end: Position;
}
/**
* A text edit applicable to a text document.
*/
export interface TextEdit {
/**
* The range of the text document to be manipulated. To insert
* text into a document create a range where start === end.
*/
range: Range;
/**
* The string to be inserted. For delete operations use an
* empty string.
*/
newText: string;
}
/**
* An event describing a change to a text document. If range and rangeLength are omitted
* the new text is considered to be the full content of the document.
*/
export type TextDocumentContentChangeEvent = {
/**
* The range of the document that changed.
*/
range: Range;
/**
* The optional length of the range that got replaced.
*
* @deprecated use range instead.
*/
rangeLength?: number;
/**
* The new text for the provided range.
*/
text: string;
} | {
/**
* The new text of the whole document.
*/
text: string;
};
/**
* A simple text document. Not to be implemented. The document keeps the content
* as string.
*/
export interface TextDocument {
/**
* The associated URI for this document. Most documents have the __file__-scheme, indicating that they
* represent files on disk. However, some documents may have other schemes indicating that they are not
* available on disk.
*
* @readonly
*/
readonly uri: DocumentUri;
/**
* The identifier of the language associated with this document.
*
* @readonly
*/
readonly languageId: string;
/**
* The version number of this document (it will increase after each
* change, including undo/redo).
*
* @readonly
*/
readonly version: number;
/**
* Get the text of this document. A substring can be retrieved by
* providing a range.
*
* @param range (optional) An range within the document to return.
* If no range is passed, the full content is returned.
* Invalid range positions are adjusted as described in {@link Position.line}
* and {@link Position.character}.
* If the start range position is greater than the end range position,
* then the effect of getText is as if the two positions were swapped.
* @return The text of this document or a substring of the text if a
* range is provided.
*/
getText(range?: Range): string;
/**
* Converts a zero-based offset to a position.
*
* @param offset A zero-based offset.
* @return A valid {@link Position position}.
* @example The text document "ab\ncd" produces:
* * position { line: 0, character: 0 } for `offset` 0.
* * position { line: 0, character: 1 } for `offset` 1.
* * position { line: 0, character: 2 } for `offset` 2.
* * position { line: 1, character: 0 } for `offset` 3.
* * position { line: 1, character: 1 } for `offset` 4.
*/
positionAt(offset: number): Position;
/**
* Converts the position to a zero-based offset.
* Invalid positions are adjusted as described in {@link Position.line}
* and {@link Position.character}.
*
* @param position A position.
* @return A valid zero-based offset.
*/
offsetAt(position: Position): number;
/**
* The number of lines in this document.
*
* @readonly
*/
readonly lineCount: number;
}
export declare namespace 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: DocumentUri, languageId: string, version: number, content: string): TextDocument;
/**
* Updates a TextDocument by modifying 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.
* @param version the changes version for the document.
* @returns The updated TextDocument. Note: That's the same document instance passed in as first parameter.
*
*/
function update(document: TextDocument, changes: TextDocumentContentChangeEvent[], version: number): TextDocument;
function applyEdits(document: TextDocument, edits: TextEdit[]): string;
}

View File

@@ -0,0 +1,264 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
class FullTextDocument {
constructor(uri, languageId, version, content) {
this._uri = uri;
this._languageId = languageId;
this._version = version;
this._content = content;
this._lineOffsets = undefined;
}
get uri() {
return this._uri;
}
get languageId() {
return this._languageId;
}
get version() {
return this._version;
}
getText(range) {
if (range) {
const start = this.offsetAt(range.start);
const end = this.offsetAt(range.end);
return this._content.substring(start, end);
}
return this._content;
}
update(changes, version) {
for (const change of changes) {
if (FullTextDocument.isIncremental(change)) {
// makes sure start is before end
const range = getWellformedRange(change.range);
// update content
const startOffset = this.offsetAt(range.start);
const endOffset = this.offsetAt(range.end);
this._content = this._content.substring(0, startOffset) + change.text + this._content.substring(endOffset, this._content.length);
// update the offsets
const startLine = Math.max(range.start.line, 0);
const endLine = Math.max(range.end.line, 0);
let lineOffsets = this._lineOffsets;
const addedLineOffsets = computeLineOffsets(change.text, false, startOffset);
if (endLine - startLine === addedLineOffsets.length) {
for (let i = 0, len = addedLineOffsets.length; i < len; i++) {
lineOffsets[i + startLine + 1] = addedLineOffsets[i];
}
}
else {
if (addedLineOffsets.length < 10000) {
lineOffsets.splice(startLine + 1, endLine - startLine, ...addedLineOffsets);
}
else { // avoid too many arguments for splice
this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1));
}
}
const diff = change.text.length - (endOffset - startOffset);
if (diff !== 0) {
for (let 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;
}
getLineOffsets() {
if (this._lineOffsets === undefined) {
this._lineOffsets = computeLineOffsets(this._content, true);
}
return this._lineOffsets;
}
positionAt(offset) {
offset = Math.max(Math.min(offset, this._content.length), 0);
const lineOffsets = this.getLineOffsets();
let low = 0, high = lineOffsets.length;
if (high === 0) {
return { line: 0, character: offset };
}
while (low < high) {
const 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
const line = low - 1;
offset = this.ensureBeforeEOL(offset, lineOffsets[line]);
return { line, character: offset - lineOffsets[line] };
}
offsetAt(position) {
const lineOffsets = this.getLineOffsets();
if (position.line >= lineOffsets.length) {
return this._content.length;
}
else if (position.line < 0) {
return 0;
}
const lineOffset = lineOffsets[position.line];
if (position.character <= 0) {
return lineOffset;
}
const nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length;
const offset = Math.min(lineOffset + position.character, nextLineOffset);
return this.ensureBeforeEOL(offset, lineOffset);
}
ensureBeforeEOL(offset, lineOffset) {
while (offset > lineOffset && isEOL(this._content.charCodeAt(offset - 1))) {
offset--;
}
return offset;
}
get lineCount() {
return this.getLineOffsets().length;
}
static isIncremental(event) {
const candidate = event;
return candidate !== undefined && candidate !== null &&
typeof candidate.text === 'string' && candidate.range !== undefined &&
(candidate.rangeLength === undefined || typeof candidate.rangeLength === 'number');
}
static isFull(event) {
const candidate = event;
return candidate !== undefined && candidate !== null &&
typeof candidate.text === 'string' && candidate.range === undefined && candidate.rangeLength === undefined;
}
}
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 modifying 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.
* @param version the changes version for 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) {
const text = document.getText();
const sortedEdits = mergeSort(edits.map(getWellformedEdit), (a, b) => {
const diff = a.range.start.line - b.range.start.line;
if (diff === 0) {
return a.range.start.character - b.range.start.character;
}
return diff;
});
let lastModifiedOffset = 0;
const spans = [];
for (const e of sortedEdits) {
const startOffset = document.offsetAt(e.range.start);
if (startOffset < lastModifiedOffset) {
throw new Error('Overlapping edit');
}
else if (startOffset > lastModifiedOffset) {
spans.push(text.substring(lastModifiedOffset, startOffset));
}
if (e.newText.length) {
spans.push(e.newText);
}
lastModifiedOffset = document.offsetAt(e.range.end);
}
spans.push(text.substr(lastModifiedOffset));
return spans.join('');
}
TextDocument.applyEdits = applyEdits;
})(TextDocument || (TextDocument = {}));
function mergeSort(data, compare) {
if (data.length <= 1) {
// sorted
return data;
}
const p = (data.length / 2) | 0;
const left = data.slice(0, p);
const right = data.slice(p);
mergeSort(left, compare);
mergeSort(right, compare);
let leftIdx = 0;
let rightIdx = 0;
let i = 0;
while (leftIdx < left.length && rightIdx < right.length) {
const 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 = 0) {
const result = isAtLineStart ? [textOffset] : [];
for (let i = 0; i < text.length; i++) {
const ch = text.charCodeAt(i);
if (isEOL(ch)) {
if (ch === 13 /* CharCode.CarriageReturn */ && i + 1 < text.length && text.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
i++;
}
result.push(textOffset + i + 1);
}
}
return result;
}
function isEOL(char) {
return char === 13 /* CharCode.CarriageReturn */ || char === 10 /* CharCode.LineFeed */;
}
function getWellformedRange(range) {
const start = range.start;
const 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) {
const range = getWellformedRange(textEdit.range);
if (range !== textEdit.range) {
return { newText: textEdit.newText, range };
}
return textEdit;
}

View File

@@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@@ -0,0 +1,191 @@
/**
* A tagging type for string properties that are actually URIs.
*/
export type DocumentUri = string;
/**
* Position in a text document expressed as zero-based line and character offset.
* The offsets are based on a UTF-16 string representation. So a string of the form
* `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀`
* is 1 and the character offset of b is 3 since `𐐀` is represented using two code
* units in UTF-16.
*
* Positions are line end character agnostic. So you can not specify a position that
* denotes `\r|\n` or `\n|` where `|` represents the character offset.
*/
export interface Position {
/**
* Line position in a document (zero-based).
*
* If a line number is greater than the number of lines in a document, it
* defaults back to the number of lines in the document.
* If a line number is negative, it defaults to 0.
*
* The above two properties are implementation specific.
*/
line: number;
/**
* Character offset on a line in a document (zero-based).
*
* The meaning of this offset is determined by the negotiated
* `PositionEncodingKind`.
*
* If the character value is greater than the line length it defaults back
* to the line length. This property is implementation specific.
*/
character: number;
}
/**
* A range in a text document expressed as (zero-based) start and end positions.
*
* If you want to specify a range that contains a line including the line ending
* character(s) then use an end position denoting the start of the next line.
* For example:
* ```ts
* {
* start: { line: 5, character: 23 }
* end : { line 6, character : 0 }
* }
* ```
*/
export interface Range {
/**
* The range's start position.
*/
start: Position;
/**
* The range's end position.
*/
end: Position;
}
/**
* A text edit applicable to a text document.
*/
export interface TextEdit {
/**
* The range of the text document to be manipulated. To insert
* text into a document create a range where start === end.
*/
range: Range;
/**
* The string to be inserted. For delete operations use an
* empty string.
*/
newText: string;
}
/**
* An event describing a change to a text document. If range and rangeLength are omitted
* the new text is considered to be the full content of the document.
*/
export type TextDocumentContentChangeEvent = {
/**
* The range of the document that changed.
*/
range: Range;
/**
* The optional length of the range that got replaced.
*
* @deprecated use range instead.
*/
rangeLength?: number;
/**
* The new text for the provided range.
*/
text: string;
} | {
/**
* The new text of the whole document.
*/
text: string;
};
/**
* A simple text document. Not to be implemented. The document keeps the content
* as string.
*/
export interface TextDocument {
/**
* The associated URI for this document. Most documents have the __file__-scheme, indicating that they
* represent files on disk. However, some documents may have other schemes indicating that they are not
* available on disk.
*
* @readonly
*/
readonly uri: DocumentUri;
/**
* The identifier of the language associated with this document.
*
* @readonly
*/
readonly languageId: string;
/**
* The version number of this document (it will increase after each
* change, including undo/redo).
*
* @readonly
*/
readonly version: number;
/**
* Get the text of this document. A substring can be retrieved by
* providing a range.
*
* @param range (optional) An range within the document to return.
* If no range is passed, the full content is returned.
* Invalid range positions are adjusted as described in {@link Position.line}
* and {@link Position.character}.
* If the start range position is greater than the end range position,
* then the effect of getText is as if the two positions were swapped.
* @return The text of this document or a substring of the text if a
* range is provided.
*/
getText(range?: Range): string;
/**
* Converts a zero-based offset to a position.
*
* @param offset A zero-based offset.
* @return A valid {@link Position position}.
* @example The text document "ab\ncd" produces:
* * position { line: 0, character: 0 } for `offset` 0.
* * position { line: 0, character: 1 } for `offset` 1.
* * position { line: 0, character: 2 } for `offset` 2.
* * position { line: 1, character: 0 } for `offset` 3.
* * position { line: 1, character: 1 } for `offset` 4.
*/
positionAt(offset: number): Position;
/**
* Converts the position to a zero-based offset.
* Invalid positions are adjusted as described in {@link Position.line}
* and {@link Position.character}.
*
* @param position A position.
* @return A valid zero-based offset.
*/
offsetAt(position: Position): number;
/**
* The number of lines in this document.
*
* @readonly
*/
readonly lineCount: number;
}
export declare namespace 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: DocumentUri, languageId: string, version: number, content: string): TextDocument;
/**
* Updates a TextDocument by modifying 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.
* @param version the changes version for the document.
* @returns The updated TextDocument. Note: That's the same document instance passed in as first parameter.
*
*/
function update(document: TextDocument, changes: TextDocumentContentChangeEvent[], version: number): TextDocument;
function applyEdits(document: TextDocument, edits: TextEdit[]): string;
}

View File

@@ -0,0 +1,305 @@
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextDocument = void 0;
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: false,
configurable: true
});
Object.defineProperty(FullTextDocument.prototype, "languageId", {
get: function () {
return this._languageId;
},
enumerable: false,
configurable: true
});
Object.defineProperty(FullTextDocument.prototype, "version", {
get: function () {
return this._version;
},
enumerable: false,
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, __spreadArray([startLine + 1, endLine - startLine], addedLineOffsets, false));
}
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;
offset = this.ensureBeforeEOL(offset, lineOffsets[line]);
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];
if (position.character <= 0) {
return lineOffset;
}
var nextLineOffset = (position.line + 1 < lineOffsets.length) ? lineOffsets[position.line + 1] : this._content.length;
var offset = Math.min(lineOffset + position.character, nextLineOffset);
return this.ensureBeforeEOL(offset, lineOffset);
};
FullTextDocument.prototype.ensureBeforeEOL = function (offset, lineOffset) {
while (offset > lineOffset && isEOL(this._content.charCodeAt(offset - 1))) {
offset--;
}
return offset;
};
Object.defineProperty(FullTextDocument.prototype, "lineCount", {
get: function () {
return this.getLineOffsets().length;
},
enumerable: false,
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;
}());
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 modifying 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.
* @param version the changes version for 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 = 0;
var spans = [];
for (var _i = 0, sortedEdits_1 = sortedEdits; _i < sortedEdits_1.length; _i++) {
var e = sortedEdits_1[_i];
var startOffset = document.offsetAt(e.range.start);
if (startOffset < lastModifiedOffset) {
throw new Error('Overlapping edit');
}
else if (startOffset > lastModifiedOffset) {
spans.push(text.substring(lastModifiedOffset, startOffset));
}
if (e.newText.length) {
spans.push(e.newText);
}
lastModifiedOffset = document.offsetAt(e.range.end);
}
spans.push(text.substr(lastModifiedOffset));
return spans.join('');
}
TextDocument.applyEdits = applyEdits;
})(TextDocument || (exports.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 (isEOL(ch)) {
if (ch === 13 /* CharCode.CarriageReturn */ && i + 1 < text.length && text.charCodeAt(i + 1) === 10 /* CharCode.LineFeed */) {
i++;
}
result.push(textOffset + i + 1);
}
}
return result;
}
function isEOL(char) {
return char === 13 /* CharCode.CarriageReturn */ || char === 10 /* CharCode.LineFeed */;
}
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;
}
});