Core AST manipulation functions for analyzing nodes, extracting information, and working with code structure. These utilities provide essential functionality for most ESLint rule implementations.
Find variables in the scope chain, supporting both string names and identifier nodes.
/**
* Find the variable of a given name in the scope chain
* @param initialScope - The scope to start finding
* @param nameOrNode - The variable name (string) or Identifier node
* @returns The found variable or null
*/
function findVariable(initialScope: Scope, nameOrNode: string | Node): Variable | null;Usage Examples:
import { findVariable } from "eslint-utils";
// In an ESLint rule
create(context) {
return {
Identifier(node) {
// Find by identifier node
const variable = findVariable(context.getScope(), node);
// Find by string name
const myVar = findVariable(context.getScope(), "myVariableName");
if (variable) {
console.log('Variable found:', variable.name);
console.log('References:', variable.references.length);
}
}
};
}Extract property names from MemberExpression and Property nodes, with support for computed properties.
/**
* Get the property name from a MemberExpression node or a Property node
* @param node - The node to get property name from
* @param initialScope - Optional scope for computed property evaluation
* @returns The property name or null if not determinable
*/
function getPropertyName(node: Node, initialScope?: Scope): string | null;Usage Examples:
import { getPropertyName } from "eslint-utils";
create(context) {
return {
MemberExpression(node) {
const propName = getPropertyName(node, context.getScope());
if (propName === 'dangerousMethod') {
context.report(node, 'Avoid using dangerousMethod');
}
},
Property(node) {
const key = getPropertyName(node);
if (key && key.startsWith('_')) {
context.report(node, 'Private properties should not start with underscore');
}
}
};
}Get descriptive information about function nodes including their names and kinds.
/**
* Get the name and kind of the given function node
* @param node - The function node to analyze
* @param sourceCode - Optional source code object for computed property keys
* @returns Descriptive string of function name and kind
*/
function getFunctionNameWithKind(node: ASTNode, sourceCode?: SourceCode): string;Usage Examples:
import { getFunctionNameWithKind } from "eslint-utils";
create(context) {
const sourceCode = context.getSourceCode();
return {
'FunctionDeclaration, FunctionExpression, ArrowFunctionExpression'(node) {
const nameWithKind = getFunctionNameWithKind(node, sourceCode);
console.log('Function info:', nameWithKind);
// Examples: "function 'myFunc'", "arrow function", "method 'getData'", "constructor"
}
};
}Get the location of function heads for precise error reporting.
/**
* Get the location of the given function node for reporting
* @param node - The function node
* @param sourceCode - The source code object to get tokens
* @returns Location object for reporting
*/
function getFunctionHeadLocation(node: Node, sourceCode: SourceCode): object;Usage Examples:
import { getFunctionHeadLocation } from "eslint-utils";
create(context) {
const sourceCode = context.getSourceCode();
return {
FunctionDeclaration(node) {
const headLoc = getFunctionHeadLocation(node, sourceCode);
context.report({
node,
loc: headLoc,
message: 'Function declaration issue detected'
});
}
};
}Find the innermost scope containing a given location.
/**
* Get the innermost scope which contains a given location
* @param initialScope - The initial scope to search
* @param node - The node location to search for
* @returns The innermost scope containing the node
*/
function getInnermostScope(initialScope: Scope, node: Node): Scope;Usage Examples:
import { getInnermostScope } from "eslint-utils";
create(context) {
return {
Identifier(node) {
const scope = getInnermostScope(context.getScope(), node);
console.log('Innermost scope type:', scope.type);
// Use the precise scope for variable lookups
const variable = scope.set.get(node.name);
}
};
}Check if nodes are wrapped in parentheses, with support for multiple levels.
/**
* Check whether a given node is parenthesized or not
* @param node - The AST node to check
* @param sourceCode - The source code object to get tokens
* @returns True if the node is parenthesized
*/
function isParenthesized(node: Node, sourceCode: SourceCode): boolean;
/**
* Check whether a given node is parenthesized a specific number of times
* @param times - The number of parentheses levels to check for
* @param node - The AST node to check
* @param sourceCode - The source code object to get tokens
* @returns True if the node is parenthesized the specified number of times
*/
function isParenthesized(times: number, node: Node, sourceCode: SourceCode): boolean;Usage Examples:
import { isParenthesized } from "eslint-utils";
create(context) {
const sourceCode = context.getSourceCode();
return {
BinaryExpression(node) {
// Check for any parentheses
if (isParenthesized(node, sourceCode)) {
context.report(node, 'Unnecessary parentheses around expression');
}
// Check for double parentheses
if (isParenthesized(2, node, sourceCode)) {
context.report(node, 'Double parentheses detected');
}
}
};
}