* Converts a `{ line: number, column: number }` pair into a source text index. * @param {Object} loc A line/column location. * @param {number} loc.line The line number of the location. (0 or 1-indexed based on language.) * @param {number} loc.column The column number of the location. (0 or 1-i
(loc)
| 487 | * @public |
| 488 | */ |
| 489 | getIndexFromLoc(loc) { |
| 490 | if ( |
| 491 | loc === null || |
| 492 | typeof loc !== "object" || |
| 493 | typeof loc.line !== "number" || |
| 494 | typeof loc.column !== "number" |
| 495 | ) { |
| 496 | throw new TypeError( |
| 497 | "Expected `loc` to be an object with numeric `line` and `column` properties.", |
| 498 | ); |
| 499 | } |
| 500 | |
| 501 | const { |
| 502 | start: { line: lineStart, column: columnStart }, |
| 503 | end: { line: lineEnd, column: columnEnd }, |
| 504 | } = this.getLoc(this.ast); |
| 505 | |
| 506 | if (loc.line < lineStart || lineEnd < loc.line) { |
| 507 | throw new RangeError( |
| 508 | `Line number out of range (line ${loc.line} requested). Valid range: ${lineStart}-${lineEnd}`, |
| 509 | ); |
| 510 | } |
| 511 | |
| 512 | // If the loc is at the start, return the start index of the root node. |
| 513 | if (loc.line === lineStart && loc.column === columnStart) { |
| 514 | return 0; |
| 515 | } |
| 516 | |
| 517 | // If the loc is at the end, return the index one "spot" past the last character of the file. |
| 518 | if (loc.line === lineEnd && loc.column === columnEnd) { |
| 519 | return this.text.length; |
| 520 | } |
| 521 | |
| 522 | // Ensure `#lineStartIndices` are lazily calculated. |
| 523 | this.#ensureLineStartIndicesFromLoc(loc, lineStart); |
| 524 | |
| 525 | const isLastLine = loc.line === lineEnd; |
| 526 | const lineStartIndex = this.#lineStartIndices[loc.line - lineStart]; |
| 527 | const lineEndIndex = isLastLine |
| 528 | ? this.text.length |
| 529 | : this.#lineStartIndices[loc.line - lineStart + 1]; |
| 530 | const positionIndex = lineStartIndex + loc.column - columnStart; |
| 531 | |
| 532 | if ( |
| 533 | loc.column < columnStart || |
| 534 | (isLastLine && positionIndex > lineEndIndex) || |
| 535 | (!isLastLine && positionIndex >= lineEndIndex) |
| 536 | ) { |
| 537 | throw new RangeError( |
| 538 | `Column number out of range (column ${loc.column} requested). Valid range for line ${loc.line}: ${columnStart}-${lineEndIndex - lineStartIndex + columnStart + (isLastLine ? 0 : -1)}`, |
| 539 | ); |
| 540 | } |
| 541 | |
| 542 | return positionIndex; |
| 543 | } |
| 544 | |
| 545 | /** |
| 546 | * Returns the range information for the given node or token. |
no test coverage detected