"use strict";
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextReplacement = exports.TextEdit = void 0;
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
const arrays_1 = require("../../../../base/common/arrays");
const assert_1 = require("../../../../base/common/assert");
const errors_1 = require("../../../../base/common/errors");
const strings_1 = require("../../../../base/common/strings");
const position_1 = require("../position");
const range_1 = require("../range");
const textLength_1 = require("../text/textLength");
const abstractText_1 = require("../text/abstractText");
class TextEdit {
    static fromStringEdit(edit, initialState) {
        const edits = edit.replacements.map(e => TextReplacement.fromStringReplacement(e, initialState));
        return new TextEdit(edits);
    }
    static replace(originalRange, newText) {
        return new TextEdit([new TextReplacement(originalRange, newText)]);
    }
    static delete(range) {
        return new TextEdit([new TextReplacement(range, '')]);
    }
    static insert(position, newText) {
        return new TextEdit([new TextReplacement(range_1.Range.fromPositions(position, position), newText)]);
    }
    static fromParallelReplacementsUnsorted(replacements) {
        const r = replacements.slice().sort((0, arrays_1.compareBy)(i => i.range, range_1.Range.compareRangesUsingStarts));
        return new TextEdit(r);
    }
    constructor(replacements) {
        this.replacements = replacements;
        (0, assert_1.assertFn)(() => (0, assert_1.checkAdjacentItems)(replacements, (a, b) => a.range.getEndPosition().isBeforeOrEqual(b.range.getStartPosition())));
    }
    /**
     * Joins touching edits and removes empty edits.
     */
    normalize() {
        const replacements = [];
        for (const r of this.replacements) {
            if (replacements.length > 0 && replacements[replacements.length - 1].range.getEndPosition().equals(r.range.getStartPosition())) {
                const last = replacements[replacements.length - 1];
                replacements[replacements.length - 1] = new TextReplacement(last.range.plusRange(r.range), last.text + r.text);
            }
            else if (!r.isEmpty) {
                replacements.push(r);
            }
        }
        return new TextEdit(replacements);
    }
    mapPosition(position) {
        let lineDelta = 0;
        let curLine = 0;
        let columnDeltaInCurLine = 0;
        for (const replacement of this.replacements) {
            const start = replacement.range.getStartPosition();
            if (position.isBeforeOrEqual(start)) {
                break;
            }
            const end = replacement.range.getEndPosition();
            const len = textLength_1.TextLength.ofText(replacement.text);
            if (position.isBefore(end)) {
                const startPos = new position_1.Position(start.lineNumber + lineDelta, start.column + (start.lineNumber + lineDelta === curLine ? columnDeltaInCurLine : 0));
                const endPos = len.addToPosition(startPos);
                return rangeFromPositions(startPos, endPos);
            }
            if (start.lineNumber + lineDelta !== curLine) {
                columnDeltaInCurLine = 0;
            }
            lineDelta += len.lineCount - (replacement.range.endLineNumber - replacement.range.startLineNumber);
            if (len.lineCount === 0) {
                if (end.lineNumber !== start.lineNumber) {
                    columnDeltaInCurLine += len.columnCount - (end.column - 1);
                }
                else {
                    columnDeltaInCurLine += len.columnCount - (end.column - start.column);
                }
            }
            else {
                columnDeltaInCurLine = len.columnCount;
            }
            curLine = end.lineNumber + lineDelta;
        }
        return new position_1.Position(position.lineNumber + lineDelta, position.column + (position.lineNumber + lineDelta === curLine ? columnDeltaInCurLine : 0));
    }
    mapRange(range) {
        function getStart(p) {
            return p instanceof position_1.Position ? p : p.getStartPosition();
        }
        function getEnd(p) {
            return p instanceof position_1.Position ? p : p.getEndPosition();
        }
        const start = getStart(this.mapPosition(range.getStartPosition()));
        const end = getEnd(this.mapPosition(range.getEndPosition()));
        return rangeFromPositions(start, end);
    }
    // TODO: `doc` is not needed for this!
    inverseMapPosition(positionAfterEdit, doc) {
        const reversed = this.inverse(doc);
        return reversed.mapPosition(positionAfterEdit);
    }
    inverseMapRange(range, doc) {
        const reversed = this.inverse(doc);
        return reversed.mapRange(range);
    }
    apply(text) {
        let result = '';
        let lastEditEnd = new position_1.Position(1, 1);
        for (const replacement of this.replacements) {
            const editRange = replacement.range;
            const editStart = editRange.getStartPosition();
            const editEnd = editRange.getEndPosition();
            const r = rangeFromPositions(lastEditEnd, editStart);
            if (!r.isEmpty()) {
                result += text.getValueOfRange(r);
            }
            result += replacement.text;
            lastEditEnd = editEnd;
        }
        const r = rangeFromPositions(lastEditEnd, text.endPositionExclusive);
        if (!r.isEmpty()) {
            result += text.getValueOfRange(r);
        }
        return result;
    }
    applyToString(str) {
        const strText = new abstractText_1.StringText(str);
        return this.apply(strText);
    }
    inverse(doc) {
        const ranges = this.getNewRanges();
        return new TextEdit(this.replacements.map((e, idx) => new TextReplacement(ranges[idx], doc.getValueOfRange(e.range))));
    }
    getNewRanges() {
        const newRanges = [];
        let previousEditEndLineNumber = 0;
        let lineOffset = 0;
        let columnOffset = 0;
        for (const replacement of this.replacements) {
            const textLength = textLength_1.TextLength.ofText(replacement.text);
            const newRangeStart = position_1.Position.lift({
                lineNumber: replacement.range.startLineNumber + lineOffset,
                column: replacement.range.startColumn + (replacement.range.startLineNumber === previousEditEndLineNumber ? columnOffset : 0)
            });
            const newRange = textLength.createRange(newRangeStart);
            newRanges.push(newRange);
            lineOffset = newRange.endLineNumber - replacement.range.endLineNumber;
            columnOffset = newRange.endColumn - replacement.range.endColumn;
            previousEditEndLineNumber = replacement.range.endLineNumber;
        }
        return newRanges;
    }
    toReplacement(text) {
        if (this.replacements.length === 0) {
            throw new errors_1.BugIndicatingError();
        }
        if (this.replacements.length === 1) {
            return this.replacements[0];
        }
        const startPos = this.replacements[0].range.getStartPosition();
        const endPos = this.replacements[this.replacements.length - 1].range.getEndPosition();
        let newText = '';
        for (let i = 0; i < this.replacements.length; i++) {
            const curEdit = this.replacements[i];
            newText += curEdit.text;
            if (i < this.replacements.length - 1) {
                const nextEdit = this.replacements[i + 1];
                const gapRange = range_1.Range.fromPositions(curEdit.range.getEndPosition(), nextEdit.range.getStartPosition());
                const gapText = text.getValueOfRange(gapRange);
                newText += gapText;
            }
        }
        return new TextReplacement(range_1.Range.fromPositions(startPos, endPos), newText);
    }
    equals(other) {
        return (0, arrays_1.equals)(this.replacements, other.replacements, (a, b) => a.equals(b));
    }
    /**
     * Combines two edits into one with the same effect.
     * WARNING: This is written by AI, but well tested. I do not understand the implementation myself.
     *
     * Invariant:
     * ```
     * other.applyToString(this.applyToString(s0)) = this.compose(other).applyToString(s0)
     * ```
     */
    compose(other) {
        const edits1 = this.normalize();
        const edits2 = other.normalize();
        if (edits1.replacements.length === 0) {
            return edits2;
        }
        if (edits2.replacements.length === 0) {
            return edits1;
        }
        const resultReplacements = [];
        let edit1Idx = 0;
        let lastEdit1EndS0Line = 1;
        let lastEdit1EndS0Col = 1;
        let headSrcRangeStartLine = 0;
        let headSrcRangeStartCol = 0;
        let headSrcRangeEndLine = 0;
        let headSrcRangeEndCol = 0;
        let headText = null;
        let headLengthLine = 0;
        let headLengthCol = 0;
        let headHasValue = false;
        let headIsInfinite = false;
        let currentPosInS1Line = 1;
        let currentPosInS1Col = 1;
        function ensureHead() {
            if (headHasValue) {
                return;
            }
            if (edit1Idx < edits1.replacements.length) {
                const nextEdit = edits1.replacements[edit1Idx];
                const nextEditStart = nextEdit.range.getStartPosition();
                const gapIsEmpty = (lastEdit1EndS0Line === nextEditStart.lineNumber) && (lastEdit1EndS0Col === nextEditStart.column);
                if (!gapIsEmpty) {
                    headSrcRangeStartLine = lastEdit1EndS0Line;
                    headSrcRangeStartCol = lastEdit1EndS0Col;
                    headSrcRangeEndLine = nextEditStart.lineNumber;
                    headSrcRangeEndCol = nextEditStart.column;
                    headText = null;
                    if (lastEdit1EndS0Line === nextEditStart.lineNumber) {
                        headLengthLine = 0;
                        headLengthCol = nextEditStart.column - lastEdit1EndS0Col;
                    }
                    else {
                        headLengthLine = nextEditStart.lineNumber - lastEdit1EndS0Line;
                        headLengthCol = nextEditStart.column - 1;
                    }
                    headHasValue = true;
                    lastEdit1EndS0Line = nextEditStart.lineNumber;
                    lastEdit1EndS0Col = nextEditStart.column;
                }
                else {
                    const nextEditEnd = nextEdit.range.getEndPosition();
                    headSrcRangeStartLine = nextEditStart.lineNumber;
                    headSrcRangeStartCol = nextEditStart.column;
                    headSrcRangeEndLine = nextEditEnd.lineNumber;
                    headSrcRangeEndCol = nextEditEnd.column;
                    headText = nextEdit.text;
                    let line = 0;
                    let column = 0;
                    const text = nextEdit.text;
                    for (let i = 0; i < text.length; i++) {
                        if (text.charCodeAt(i) === 10) {
                            line++;
                            column = 0;
                        }
                        else {
                            column++;
                        }
                    }
                    headLengthLine = line;
                    headLengthCol = column;
                    headHasValue = true;
                    lastEdit1EndS0Line = nextEditEnd.lineNumber;
                    lastEdit1EndS0Col = nextEditEnd.column;
                    edit1Idx++;
                }
            }
            else {
                headIsInfinite = true;
                headSrcRangeStartLine = lastEdit1EndS0Line;
                headSrcRangeStartCol = lastEdit1EndS0Col;
                headHasValue = true;
            }
        }
        function splitText(text, lenLine, lenCol) {
            if (lenLine === 0 && lenCol === 0) {
                return ['', text];
            }
            let line = 0;
            let offset = 0;
            while (line < lenLine) {
                const idx = text.indexOf('\n', offset);
                if (idx === -1) {
                    throw new errors_1.BugIndicatingError('Text length mismatch');
                }
                offset = idx + 1;
                line++;
            }
            offset += lenCol;
            return [text.substring(0, offset), text.substring(offset)];
        }
        for (const r2 of edits2.replacements) {
            const r2Start = r2.range.getStartPosition();
            const r2End = r2.range.getEndPosition();
            while (true) {
                if (currentPosInS1Line === r2Start.lineNumber && currentPosInS1Col === r2Start.column) {
                    break;
                }
                ensureHead();
                if (headIsInfinite) {
                    let distLine, distCol;
                    if (currentPosInS1Line === r2Start.lineNumber) {
                        distLine = 0;
                        distCol = r2Start.column - currentPosInS1Col;
                    }
                    else {
                        distLine = r2Start.lineNumber - currentPosInS1Line;
                        distCol = r2Start.column - 1;
                    }
                    currentPosInS1Line = r2Start.lineNumber;
                    currentPosInS1Col = r2Start.column;
                    if (distLine === 0) {
                        headSrcRangeStartCol += distCol;
                    }
                    else {
                        headSrcRangeStartLine += distLine;
                        headSrcRangeStartCol = distCol + 1;
                    }
                    break;
                }
                let headEndInS1Line, headEndInS1Col;
                if (headLengthLine === 0) {
                    headEndInS1Line = currentPosInS1Line;
                    headEndInS1Col = currentPosInS1Col + headLengthCol;
                }
                else {
                    headEndInS1Line = currentPosInS1Line + headLengthLine;
                    headEndInS1Col = headLengthCol + 1;
                }
                let r2StartIsBeforeHeadEnd = false;
                if (r2Start.lineNumber < headEndInS1Line) {
                    r2StartIsBeforeHeadEnd = true;
                }
                else if (r2Start.lineNumber === headEndInS1Line) {
                    r2StartIsBeforeHeadEnd = r2Start.column < headEndInS1Col;
                }
                if (r2StartIsBeforeHeadEnd) {
                    let splitLenLine, splitLenCol;
                    if (currentPosInS1Line === r2Start.lineNumber) {
                        splitLenLine = 0;
                        splitLenCol = r2Start.column - currentPosInS1Col;
                    }
                    else {
                        splitLenLine = r2Start.lineNumber - currentPosInS1Line;
                        splitLenCol = r2Start.column - 1;
                    }
                    let remainingLenLine, remainingLenCol;
                    if (splitLenLine === headLengthLine) {
                        remainingLenLine = 0;
                        remainingLenCol = headLengthCol - splitLenCol;
                    }
                    else {
                        remainingLenLine = headLengthLine - splitLenLine;
                        remainingLenCol = headLengthCol;
                    }
                    if (headText !== null) {
                        const [t1, t2] = splitText(headText, splitLenLine, splitLenCol);
                        resultReplacements.push(new TextReplacement(new range_1.Range(headSrcRangeStartLine, headSrcRangeStartCol, headSrcRangeEndLine, headSrcRangeEndCol), t1));
                        headText = t2;
                        headLengthLine = remainingLenLine;
                        headLengthCol = remainingLenCol;
                        headSrcRangeStartLine = headSrcRangeEndLine;
                        headSrcRangeStartCol = headSrcRangeEndCol;
                    }
                    else {
                        let splitPosLine, splitPosCol;
                        if (splitLenLine === 0) {
                            splitPosLine = headSrcRangeStartLine;
                            splitPosCol = headSrcRangeStartCol + splitLenCol;
                        }
                        else {
                            splitPosLine = headSrcRangeStartLine + splitLenLine;
                            splitPosCol = splitLenCol + 1;
                        }
                        headSrcRangeStartLine = splitPosLine;
                        headSrcRangeStartCol = splitPosCol;
                        headLengthLine = remainingLenLine;
                        headLengthCol = remainingLenCol;
                    }
                    currentPosInS1Line = r2Start.lineNumber;
                    currentPosInS1Col = r2Start.column;
                    break;
                }
                if (headText !== null) {
                    resultReplacements.push(new TextReplacement(new range_1.Range(headSrcRangeStartLine, headSrcRangeStartCol, headSrcRangeEndLine, headSrcRangeEndCol), headText));
                }
                currentPosInS1Line = headEndInS1Line;
                currentPosInS1Col = headEndInS1Col;
                headHasValue = false;
            }
            let consumedStartS0Line = null;
            let consumedStartS0Col = null;
            let consumedEndS0Line = null;
            let consumedEndS0Col = null;
            while (true) {
                if (currentPosInS1Line === r2End.lineNumber && currentPosInS1Col === r2End.column) {
                    break;
                }
                ensureHead();
                if (headIsInfinite) {
                    let distLine, distCol;
                    if (currentPosInS1Line === r2End.lineNumber) {
                        distLine = 0;
                        distCol = r2End.column - currentPosInS1Col;
                    }
                    else {
                        distLine = r2End.lineNumber - currentPosInS1Line;
                        distCol = r2End.column - 1;
                    }
                    let rangeInS0EndLine, rangeInS0EndCol;
                    if (distLine === 0) {
                        rangeInS0EndLine = headSrcRangeStartLine;
                        rangeInS0EndCol = headSrcRangeStartCol + distCol;
                    }
                    else {
                        rangeInS0EndLine = headSrcRangeStartLine + distLine;
                        rangeInS0EndCol = distCol + 1;
                    }
                    if (consumedStartS0Line === null) {
                        consumedStartS0Line = headSrcRangeStartLine;
                        consumedStartS0Col = headSrcRangeStartCol;
                    }
                    consumedEndS0Line = rangeInS0EndLine;
                    consumedEndS0Col = rangeInS0EndCol;
                    currentPosInS1Line = r2End.lineNumber;
                    currentPosInS1Col = r2End.column;
                    headSrcRangeStartLine = rangeInS0EndLine;
                    headSrcRangeStartCol = rangeInS0EndCol;
                    break;
                }
                let headEndInS1Line, headEndInS1Col;
                if (headLengthLine === 0) {
                    headEndInS1Line = currentPosInS1Line;
                    headEndInS1Col = currentPosInS1Col + headLengthCol;
                }
                else {
                    headEndInS1Line = currentPosInS1Line + headLengthLine;
                    headEndInS1Col = headLengthCol + 1;
                }
                let r2EndIsBeforeHeadEnd = false;
                if (r2End.lineNumber < headEndInS1Line) {
                    r2EndIsBeforeHeadEnd = true;
                }
                else if (r2End.lineNumber === headEndInS1Line) {
                    r2EndIsBeforeHeadEnd = r2End.column < headEndInS1Col;
                }
                if (r2EndIsBeforeHeadEnd) {
                    let splitLenLine, splitLenCol;
                    if (currentPosInS1Line === r2End.lineNumber) {
                        splitLenLine = 0;
                        splitLenCol = r2End.column - currentPosInS1Col;
                    }
                    else {
                        splitLenLine = r2End.lineNumber - currentPosInS1Line;
                        splitLenCol = r2End.column - 1;
                    }
                    let remainingLenLine, remainingLenCol;
                    if (splitLenLine === headLengthLine) {
                        remainingLenLine = 0;
                        remainingLenCol = headLengthCol - splitLenCol;
                    }
                    else {
                        remainingLenLine = headLengthLine - splitLenLine;
                        remainingLenCol = headLengthCol;
                    }
                    if (headText !== null) {
                        if (consumedStartS0Line === null) {
                            consumedStartS0Line = headSrcRangeStartLine;
                            consumedStartS0Col = headSrcRangeStartCol;
                        }
                        consumedEndS0Line = headSrcRangeEndLine;
                        consumedEndS0Col = headSrcRangeEndCol;
                        const [, t2] = splitText(headText, splitLenLine, splitLenCol);
                        headText = t2;
                        headLengthLine = remainingLenLine;
                        headLengthCol = remainingLenCol;
                        headSrcRangeStartLine = headSrcRangeEndLine;
                        headSrcRangeStartCol = headSrcRangeEndCol;
                    }
                    else {
                        let splitPosLine, splitPosCol;
                        if (splitLenLine === 0) {
                            splitPosLine = headSrcRangeStartLine;
                            splitPosCol = headSrcRangeStartCol + splitLenCol;
                        }
                        else {
                            splitPosLine = headSrcRangeStartLine + splitLenLine;
                            splitPosCol = splitLenCol + 1;
                        }
                        if (consumedStartS0Line === null) {
                            consumedStartS0Line = headSrcRangeStartLine;
                            consumedStartS0Col = headSrcRangeStartCol;
                        }
                        consumedEndS0Line = splitPosLine;
                        consumedEndS0Col = splitPosCol;
                        headSrcRangeStartLine = splitPosLine;
                        headSrcRangeStartCol = splitPosCol;
                        headLengthLine = remainingLenLine;
                        headLengthCol = remainingLenCol;
                    }
                    currentPosInS1Line = r2End.lineNumber;
                    currentPosInS1Col = r2End.column;
                    break;
                }
                if (consumedStartS0Line === null) {
                    consumedStartS0Line = headSrcRangeStartLine;
                    consumedStartS0Col = headSrcRangeStartCol;
                }
                consumedEndS0Line = headSrcRangeEndLine;
                consumedEndS0Col = headSrcRangeEndCol;
                currentPosInS1Line = headEndInS1Line;
                currentPosInS1Col = headEndInS1Col;
                headHasValue = false;
            }
            if (consumedStartS0Line !== null) {
                resultReplacements.push(new TextReplacement(new range_1.Range(consumedStartS0Line, consumedStartS0Col, consumedEndS0Line, consumedEndS0Col), r2.text));
            }
            else {
                ensureHead();
                const insertPosS0Line = headSrcRangeStartLine;
                const insertPosS0Col = headSrcRangeStartCol;
                resultReplacements.push(new TextReplacement(new range_1.Range(insertPosS0Line, insertPosS0Col, insertPosS0Line, insertPosS0Col), r2.text));
            }
        }
        while (true) {
            ensureHead();
            if (headIsInfinite) {
                break;
            }
            if (headText !== null) {
                resultReplacements.push(new TextReplacement(new range_1.Range(headSrcRangeStartLine, headSrcRangeStartCol, headSrcRangeEndLine, headSrcRangeEndCol), headText));
            }
            headHasValue = false;
        }
        return new TextEdit(resultReplacements).normalize();
    }
    toString(text) {
        if (text === undefined) {
            return this.replacements.map(edit => edit.toString()).join('\n');
        }
        if (typeof text === 'string') {
            return this.toString(new abstractText_1.StringText(text));
        }
        if (this.replacements.length === 0) {
            return '';
        }
        return this.replacements.map(r => {
            const maxLength = 10;
            const originalText = text.getValueOfRange(r.range);
            // Get text before the edit
            const beforeRange = range_1.Range.fromPositions(new position_1.Position(Math.max(1, r.range.startLineNumber - 1), 1), r.range.getStartPosition());
            let beforeText = text.getValueOfRange(beforeRange);
            if (beforeText.length > maxLength) {
                beforeText = '...' + beforeText.substring(beforeText.length - maxLength);
            }
            // Get text after the edit
            const afterRange = range_1.Range.fromPositions(r.range.getEndPosition(), new position_1.Position(r.range.endLineNumber + 1, 1));
            let afterText = text.getValueOfRange(afterRange);
            if (afterText.length > maxLength) {
                afterText = afterText.substring(0, maxLength) + '...';
            }
            // Format the replaced text
            let replacedText = originalText;
            if (replacedText.length > maxLength) {
                const halfMax = Math.floor(maxLength / 2);
                replacedText = replacedText.substring(0, halfMax) + '...' +
                    replacedText.substring(replacedText.length - halfMax);
            }
            // Format the new text
            let newText = r.text;
            if (newText.length > maxLength) {
                const halfMax = Math.floor(maxLength / 2);
                newText = newText.substring(0, halfMax) + '...' +
                    newText.substring(newText.length - halfMax);
            }
            if (replacedText.length === 0) {
                // allow-any-unicode-next-line
                return `${beforeText}❰${newText}❱${afterText}`;
            }
            // allow-any-unicode-next-line
            return `${beforeText}❰${replacedText}↦${newText}❱${afterText}`;
        }).join('\n');
    }
}
exports.TextEdit = TextEdit;
class TextReplacement {
    static joinReplacements(replacements, initialValue) {
        if (replacements.length === 0) {
            throw new errors_1.BugIndicatingError();
        }
        if (replacements.length === 1) {
            return replacements[0];
        }
        const startPos = replacements[0].range.getStartPosition();
        const endPos = replacements[replacements.length - 1].range.getEndPosition();
        let newText = '';
        for (let i = 0; i < replacements.length; i++) {
            const curEdit = replacements[i];
            newText += curEdit.text;
            if (i < replacements.length - 1) {
                const nextEdit = replacements[i + 1];
                const gapRange = range_1.Range.fromPositions(curEdit.range.getEndPosition(), nextEdit.range.getStartPosition());
                const gapText = initialValue.getValueOfRange(gapRange);
                newText += gapText;
            }
        }
        return new TextReplacement(range_1.Range.fromPositions(startPos, endPos), newText);
    }
    static fromStringReplacement(replacement, initialState) {
        return new TextReplacement(initialState.getTransformer().getRange(replacement.replaceRange), replacement.newText);
    }
    static delete(range) {
        return new TextReplacement(range, '');
    }
    constructor(range, text) {
        this.range = range;
        this.text = text;
    }
    get isEmpty() {
        return this.range.isEmpty() && this.text.length === 0;
    }
    static equals(first, second) {
        return first.range.equalsRange(second.range) && first.text === second.text;
    }
    toSingleEditOperation() {
        return {
            range: this.range,
            text: this.text,
        };
    }
    toEdit() {
        return new TextEdit([this]);
    }
    equals(other) {
        return TextReplacement.equals(this, other);
    }
    extendToCoverRange(range, initialValue) {
        if (this.range.containsRange(range)) {
            return this;
        }
        const newRange = this.range.plusRange(range);
        const textBefore = initialValue.getValueOfRange(range_1.Range.fromPositions(newRange.getStartPosition(), this.range.getStartPosition()));
        const textAfter = initialValue.getValueOfRange(range_1.Range.fromPositions(this.range.getEndPosition(), newRange.getEndPosition()));
        const newText = textBefore + this.text + textAfter;
        return new TextReplacement(newRange, newText);
    }
    extendToFullLine(initialValue) {
        const newRange = new range_1.Range(this.range.startLineNumber, 1, this.range.endLineNumber, initialValue.getTransformer().getLineLength(this.range.endLineNumber) + 1);
        return this.extendToCoverRange(newRange, initialValue);
    }
    removeCommonPrefixAndSuffix(text) {
        const prefix = this.removeCommonPrefix(text);
        const suffix = prefix.removeCommonSuffix(text);
        return suffix;
    }
    removeCommonPrefix(text) {
        const normalizedOriginalText = text.getValueOfRange(this.range).replaceAll('\r\n', '\n');
        const normalizedModifiedText = this.text.replaceAll('\r\n', '\n');
        const commonPrefixLen = (0, strings_1.commonPrefixLength)(normalizedOriginalText, normalizedModifiedText);
        const start = textLength_1.TextLength.ofText(normalizedOriginalText.substring(0, commonPrefixLen))
            .addToPosition(this.range.getStartPosition());
        const newText = normalizedModifiedText.substring(commonPrefixLen);
        const range = range_1.Range.fromPositions(start, this.range.getEndPosition());
        return new TextReplacement(range, newText);
    }
    removeCommonSuffix(text) {
        const normalizedOriginalText = text.getValueOfRange(this.range).replaceAll('\r\n', '\n');
        const normalizedModifiedText = this.text.replaceAll('\r\n', '\n');
        const commonSuffixLen = (0, strings_1.commonSuffixLength)(normalizedOriginalText, normalizedModifiedText);
        const end = textLength_1.TextLength.ofText(normalizedOriginalText.substring(0, normalizedOriginalText.length - commonSuffixLen))
            .addToPosition(this.range.getStartPosition());
        const newText = normalizedModifiedText.substring(0, normalizedModifiedText.length - commonSuffixLen);
        const range = range_1.Range.fromPositions(this.range.getStartPosition(), end);
        return new TextReplacement(range, newText);
    }
    isEffectiveDeletion(text) {
        let newText = this.text.replaceAll('\r\n', '\n');
        let existingText = text.getValueOfRange(this.range).replaceAll('\r\n', '\n');
        const l = (0, strings_1.commonPrefixLength)(newText, existingText);
        newText = newText.substring(l);
        existingText = existingText.substring(l);
        const r = (0, strings_1.commonSuffixLength)(newText, existingText);
        newText = newText.substring(0, newText.length - r);
        existingText = existingText.substring(0, existingText.length - r);
        return newText === '';
    }
    toString() {
        const start = this.range.getStartPosition();
        const end = this.range.getEndPosition();
        return `(${start.lineNumber},${start.column} -> ${end.lineNumber},${end.column}): "${this.text}"`;
    }
}
exports.TextReplacement = TextReplacement;
function rangeFromPositions(start, end) {
    if (start.lineNumber === end.lineNumber && start.column === Number.MAX_SAFE_INTEGER) {
        return range_1.Range.fromPositions(end, end);
    }
    else if (!start.isBeforeOrEqual(end)) {
        throw new errors_1.BugIndicatingError('start must be before end');
    }
    return new range_1.Range(start.lineNumber, start.column, end.lineNumber, end.column);
}
//# sourceMappingURL=textEdit.js.map