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; } }