125 lines
4.3 KiB
TypeScript
125 lines
4.3 KiB
TypeScript
import { Point, Range } from "./constants";
|
|
|
|
export class Edit {
|
|
/** The start position of the change. */
|
|
startPosition: Point;
|
|
|
|
/** The end position of the change before the edit. */
|
|
oldEndPosition: Point;
|
|
|
|
/** The end position of the change after the edit. */
|
|
newEndPosition: Point;
|
|
|
|
/** The start index of the change. */
|
|
startIndex: number;
|
|
|
|
/** The end index of the change before the edit. */
|
|
oldEndIndex: number;
|
|
|
|
/** The end index of the change after the edit. */
|
|
newEndIndex: number;
|
|
|
|
constructor({
|
|
startIndex,
|
|
oldEndIndex,
|
|
newEndIndex,
|
|
startPosition,
|
|
oldEndPosition,
|
|
newEndPosition,
|
|
}: {
|
|
startIndex: number;
|
|
oldEndIndex: number;
|
|
newEndIndex: number;
|
|
startPosition: Point;
|
|
oldEndPosition: Point;
|
|
newEndPosition: Point;
|
|
}) {
|
|
this.startIndex = startIndex >>> 0;
|
|
this.oldEndIndex = oldEndIndex >>> 0;
|
|
this.newEndIndex = newEndIndex >>> 0;
|
|
this.startPosition = startPosition;
|
|
this.oldEndPosition = oldEndPosition;
|
|
this.newEndPosition = newEndPosition;
|
|
}
|
|
|
|
/**
|
|
* Edit a point and index to keep it in-sync with source code that has been edited.
|
|
*
|
|
* This function updates a single point's byte offset and row/column position
|
|
* based on an edit operation. This is useful for editing points without
|
|
* requiring a tree or node instance.
|
|
*/
|
|
editPoint(point: Point, index: number): { point: Point; index: number } {
|
|
let newIndex = index;
|
|
const newPoint = { ...point };
|
|
|
|
if (index >= this.oldEndIndex) {
|
|
newIndex = this.newEndIndex + (index - this.oldEndIndex);
|
|
const originalRow = point.row;
|
|
newPoint.row = this.newEndPosition.row + (point.row - this.oldEndPosition.row);
|
|
newPoint.column = originalRow === this.oldEndPosition.row
|
|
? this.newEndPosition.column + (point.column - this.oldEndPosition.column)
|
|
: point.column;
|
|
} else if (index > this.startIndex) {
|
|
newIndex = this.newEndIndex;
|
|
newPoint.row = this.newEndPosition.row;
|
|
newPoint.column = this.newEndPosition.column;
|
|
}
|
|
|
|
return { point: newPoint, index: newIndex };
|
|
}
|
|
|
|
/**
|
|
* Edit a range to keep it in-sync with source code that has been edited.
|
|
*
|
|
* This function updates a range's start and end positions based on an edit
|
|
* operation. This is useful for editing ranges without requiring a tree
|
|
* or node instance.
|
|
*/
|
|
editRange(range: Range): Range {
|
|
const newRange: Range = {
|
|
startIndex: range.startIndex,
|
|
startPosition: { ...range.startPosition },
|
|
endIndex: range.endIndex,
|
|
endPosition: { ...range.endPosition }
|
|
};
|
|
|
|
if (range.endIndex >= this.oldEndIndex) {
|
|
if (range.endIndex !== Number.MAX_SAFE_INTEGER) {
|
|
newRange.endIndex = this.newEndIndex + (range.endIndex - this.oldEndIndex);
|
|
newRange.endPosition = {
|
|
row: this.newEndPosition.row + (range.endPosition.row - this.oldEndPosition.row),
|
|
column: range.endPosition.row === this.oldEndPosition.row
|
|
? this.newEndPosition.column + (range.endPosition.column - this.oldEndPosition.column)
|
|
: range.endPosition.column,
|
|
};
|
|
if (newRange.endIndex < this.newEndIndex) {
|
|
newRange.endIndex = Number.MAX_SAFE_INTEGER;
|
|
newRange.endPosition = { row: Number.MAX_SAFE_INTEGER, column: Number.MAX_SAFE_INTEGER };
|
|
}
|
|
}
|
|
} else if (range.endIndex > this.startIndex) {
|
|
newRange.endIndex = this.startIndex;
|
|
newRange.endPosition = { ...this.startPosition };
|
|
}
|
|
|
|
if (range.startIndex >= this.oldEndIndex) {
|
|
newRange.startIndex = this.newEndIndex + (range.startIndex - this.oldEndIndex);
|
|
newRange.startPosition = {
|
|
row: this.newEndPosition.row + (range.startPosition.row - this.oldEndPosition.row),
|
|
column: range.startPosition.row === this.oldEndPosition.row
|
|
? this.newEndPosition.column + (range.startPosition.column - this.oldEndPosition.column)
|
|
: range.startPosition.column,
|
|
};
|
|
if (newRange.startIndex < this.newEndIndex) {
|
|
newRange.startIndex = Number.MAX_SAFE_INTEGER;
|
|
newRange.startPosition = { row: Number.MAX_SAFE_INTEGER, column: Number.MAX_SAFE_INTEGER };
|
|
}
|
|
} else if (range.startIndex > this.startIndex) {
|
|
newRange.startIndex = this.startIndex;
|
|
newRange.startPosition = { ...this.startPosition };
|
|
}
|
|
|
|
return newRange;
|
|
}
|
|
}
|