MCPcopy Create free account
hub / github.com/Rich-Harris/magic-string / move

Method move

src/MagicString.ts:631–745  ·  view source on GitHub ↗

* Moves the characters from `start` and `end` to `index`. * * `affinity` controls where the range is anchored at `index`. With the * default `'right'`, it is inserted before the content that starts at `index`; * with `'left'`, it is inserted after the content that ends at `index`. The

(start: number, end: number, index: number, affinity: 'left' | 'right' = 'right')

Source from the content-addressed store, hash-verified

629 * mirroring the `appendLeft`/`appendRight` distinction.
630 */
631 move(start: number, end: number, index: number, affinity: 'left' | 'right' = 'right'): this {
632 start = start + this.offset
633 end = end + this.offset
634 index = index + this.offset
635
636 if (start === end)
637 return this
638
639 if (index >= start && index <= end) {
640 throw new MagicStringError('cannot move a selection inside itself')
641 }
642
643 /* v8 ignore next 2 -- DEBUG is always true in tests */
644 if (DEBUG)
645 this.stats.time('move')
646
647 this._split(start)
648 this._split(end)
649 this._split(index)
650
651 const first = this.byStart.get(start)
652 const last = this.byEnd.get(end)
653
654 // The splicing below assumes the chunks spanning [start, end) are still a
655 // forward run in the current list. An earlier move can have interleaved a
656 // chunk from outside the range, or put `last` before `first`, and then the
657 // pointer rewrites produce a cycle rather than an error, so toString() and
658 // generateMap() loop forever.
659 //
660 // Only move() reorders chunks, so this is skipped until one has run, which
661 // keeps the common single-move case free of the walk.
662 if (this.hasMovedChunks) {
663 let cursor = first
664 while (cursor !== last) {
665 cursor = cursor.next
666 if (!cursor || cursor.start < start || cursor.end > end) {
667 throw new MagicStringError(
668 `cannot move ${start} to ${end} because an earlier move split that range`,
669 )
670 }
671 }
672 }
673
674 const oldLeft = first.previous
675 const oldRight = last.next
676
677 // Anchor the range at `index` according to `affinity`: `'right'` puts it
678 // before the chunk starting at `index`, `'left'` after the chunk ending at
679 // `index`. When no such anchor exists (`index` is at an end of the string)
680 // the range falls to that end.
681 //
682 // The early returns catch the cases where the range is already in place:
683 // splicing it in next to itself would link the chunk list back on itself
684 // and drop the range from the output.
685 let newLeft: Chunk | null
686 let newRight: Chunk | null
687 if (affinity === 'left') {
688 newLeft = this.byEnd.get(index) ?? null

Callers

nothing calls this directly

Calls 3

_splitMethod · 0.95
timeMethod · 0.80
timeEndMethod · 0.80

Tested by

no test coverage detected