Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions apps/oxlint/src-js/plugins/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ast, initAst, initSourceText, sourceText } from "./source_code.ts";
import visitorKeys from "../generated/keys.ts";
import { debugAssert, debugAssertIsNonNull } from "../utils/asserts.ts";

import type { Node } from "./types.ts";
import type { NodeOrToken } from "./types.ts";
import type { Node as ESTreeNode } from "../generated/types.d.ts";

/**
Expand Down Expand Up @@ -241,28 +241,38 @@ export function getOffsetFromLineColumn(loc: LineColumn): number {
}

/**
* Get the `Location` for an AST node. Used in `loc` getters on AST nodes.
* Calculate the `Location` for an AST node or token.
*
* Overwrites the `loc` getter with the calculated `Location`, so accessing `loc` twice on same node
* Used in `loc` getters on AST nodes.
*
* Defines a `loc` property on the node/token with the calculated `Location`, so accessing `loc` twice on same node
* results in the same object each time.
*
* For internal use only.
*
* @param node - AST node object
* @param nodeOrToken - AST node or token
* @returns Location
*/
export function getNodeLoc(node: Node): Location {
export function getNodeLoc(nodeOrToken: NodeOrToken): Location {
// Build `lines` and `lineStartIndices` tables if they haven't been already.
// This also decodes `sourceText` if it wasn't already.
if (lines.length === 0) initLines();

const loc = {
start: getLineColumnFromOffsetUnchecked(node.start),
end: getLineColumnFromOffsetUnchecked(node.end),
start: getLineColumnFromOffsetUnchecked(nodeOrToken.start),
end: getLineColumnFromOffsetUnchecked(nodeOrToken.end),
};

// Replace `loc` getter with the calculated value
Object.defineProperty(node, "loc", { value: loc, writable: true });
// Define `loc` property with the calculated `Location`, so accessing `loc` twice on same node/token
// results in the same object each time.
//
// We do not make the `loc` property enumerable, because it wasn't present before.
// It would be weird if `Object.keys(node)` included `loc` if the property had been accessed previously,
// but not if it hadn't.
//
// We also don't make it configurable, because deleting it wouldn't make `node.loc` evaluate to `undefined`,
// because the access would fall through to the getter on the prototype.
Object.defineProperty(nodeOrToken, "loc", { value: loc, writable: true });

return loc;
}
Expand Down
Loading