Skip to content

[REFACTOR] Replace getLocFromIndex and getIndexFromLoc methods with ESLint's native APIsΒ #413

@lumirlumir

Description

@lumirlumir

Hi @yeonjuan β€” I came here from ESLint. πŸ˜„

A new feature adding native support for getLocFromIndex and getIndexFromLoc was merged in eslint/rewrite#212, so those methods can be replaced with the native API.

Current implementation:

getIndexFromLoc(loc) {
if (
typeof loc !== "object" ||
typeof loc.line !== "number" ||
typeof loc.column !== "number"
) {
throw new TypeError(
"Expected `loc` to be an object with numeric `line` and `column` properties."
);
}
if (loc.line <= 0) {
throw new RangeError(
`Line number out of range (line ${loc.line} requested). Line numbers should be 1-based.`
);
}
if (loc.line > this.lineStartIndices.length) {
throw new RangeError(
`Line number out of range (line ${loc.line} requested, but only ${this.lineStartIndices.length} lines present).`
);
}
const lineStartIndex = this.lineStartIndices[loc.line - 1];
const lineEndIndex =
loc.line === this.lineStartIndices.length
? this.text.length
: this.lineStartIndices[loc.line];
const positionIndex = lineStartIndex + loc.column;
if (
(loc.line === this.lineStartIndices.length &&
positionIndex > lineEndIndex) ||
(loc.line < this.lineStartIndices.length && positionIndex >= lineEndIndex)
) {
throw new RangeError(
`Column number out of range (column ${loc.column} requested, but the length of line ${loc.line} is ${lineEndIndex - lineStartIndex}).`
);
}
return positionIndex;
}
// Copied from eslint source code
/**
* @see https://github.com/eslint/eslint/blob/f60f2764971a33e252be13e560dccf21f554dbf1/lib/languages/js/source-code/source-code.js#L694
* @param {number} index
* @returns {Position}
*/
getLocFromIndex(index) {
if (typeof index !== "number") {
throw new TypeError("Expected `index` to be a number.");
}
if (index < 0 || index > this.text.length) {
throw new RangeError(
`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`
);
}
if (index === this.text.length) {
return {
line: this.lines.length,
// @ts-ignore
column: this.lines.at(-1).length,
};
}
const lineNumber =
// @ts-ignore
index >= this.lineStartIndices.at(-1)
? this.lineStartIndices.length
: this.lineStartIndices.findIndex((el) => index < el);
return {
line: lineNumber,
column: index - this.lineStartIndices[lineNumber - 1],
};
}

It’s pending release and will be available after @eslint/plugin-kit 0.4.0 is published.

The native API is faster thanks to a more efficient lookup algorithm and lazy calculation, which reduces memory usage and improves performance.

Please feel free to take a look at it!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions