* Converts a source text index into a `{ line: number, column: number }` pair. * @param {number} index The index of a character in a file. * @throws {TypeError|RangeError} If non-numeric index or index out of range. * @returns {{line: number, column: number}} A `{ line: number, column: number
(index)
| 421 | * @public |
| 422 | */ |
| 423 | getLocFromIndex(index) { |
| 424 | if (typeof index !== "number") { |
| 425 | throw new TypeError("Expected `index` to be a number."); |
| 426 | } |
| 427 | |
| 428 | if (index < 0 || index > this.text.length) { |
| 429 | throw new RangeError( |
| 430 | `Index out of range (requested index ${index}, but source text has length ${this.text.length}).`, |
| 431 | ); |
| 432 | } |
| 433 | |
| 434 | const { |
| 435 | start: { line: lineStart, column: columnStart }, |
| 436 | end: { line: lineEnd, column: columnEnd }, |
| 437 | } = this.getLoc(this.ast); |
| 438 | |
| 439 | // If the index is at the start, return the start location of the root node. |
| 440 | if (index === 0) { |
| 441 | return { |
| 442 | line: lineStart, |
| 443 | column: columnStart, |
| 444 | }; |
| 445 | } |
| 446 | |
| 447 | // If the index is `this.text.length`, return the location one "spot" past the last character of the file. |
| 448 | if (index === this.text.length) { |
| 449 | return { |
| 450 | line: lineEnd, |
| 451 | column: columnEnd, |
| 452 | }; |
| 453 | } |
| 454 | |
| 455 | // Ensure `#lineStartIndices` are lazily calculated. |
| 456 | this.#ensureLineStartIndicesFromIndex(index); |
| 457 | |
| 458 | /* |
| 459 | * To figure out which line `index` is on, determine the last place at which index could |
| 460 | * be inserted into `#lineStartIndices` to keep the list sorted. |
| 461 | */ |
| 462 | const lineNumber = |
| 463 | (index >= (this.#lineStartIndices.at(-1) ?? 0) |
| 464 | ? this.#lineStartIndices.length |
| 465 | : findLineNumberBinarySearch(this.#lineStartIndices, index)) - |
| 466 | 1 + |
| 467 | lineStart; |
| 468 | |
| 469 | return { |
| 470 | line: lineNumber, |
| 471 | column: |
| 472 | index - |
| 473 | this.#lineStartIndices[lineNumber - lineStart] + |
| 474 | columnStart, |
| 475 | }; |
| 476 | } |
| 477 | |
| 478 | /** |
| 479 | * Converts a `{ line: number, column: number }` pair into a source text index. |
no test coverage detected