Utilities for ESLint plugins providing AST manipulation, static analysis, and rule development helpers.
npx @tessl/cli install tessl/npm-eslint-utils@3.0.0ESLint Utils is a comprehensive JavaScript utility library specifically designed for ESLint plugin development. It provides essential functions for AST manipulation, static code analysis, scope traversal, and rule implementation, offering developers robust tools for creating custom ESLint rules with advanced capabilities.
npm install eslint-utilsimport {
findVariable,
getStaticValue,
hasSideEffect,
ReferenceTracker,
PatternMatcher,
isArrowToken,
isParenthesized
} from "eslint-utils";For CommonJS:
const {
findVariable,
getStaticValue,
hasSideEffect,
ReferenceTracker,
PatternMatcher,
isArrowToken,
isParenthesized
} = require("eslint-utils");Default import (contains all utilities):
import utils from "eslint-utils";
// Access via utils.findVariable(), utils.getStaticValue(), etc.import {
findVariable,
getStaticValue,
hasSideEffect,
ReferenceTracker,
isParenthesized
} from "eslint-utils";
// In an ESLint rule
module.exports = {
meta: { /* ... */ },
create(context) {
const sourceCode = context.getSourceCode();
return {
Identifier(node) {
// Find variable in scope
const variable = findVariable(context.getScope(), node);
// Check if expression has static value
const staticValue = getStaticValue(node, context.getScope());
if (staticValue) {
console.log('Static value:', staticValue.value);
}
// Check if node is parenthesized
if (isParenthesized(node, sourceCode)) {
context.report(node, 'Unnecessary parentheses');
}
// Check for side effects
if (hasSideEffect(node, sourceCode)) {
context.report(node, 'Expression has side effects');
}
}
};
}
};ESLint Utils is structured around several key functional areas:
Core AST manipulation functions for analyzing nodes, extracting information, and working with code structure. Essential for most ESLint rule implementations.
function findVariable(initialScope: Scope, nameOrNode: string | Node): Variable | null;
function getPropertyName(node: Node, initialScope?: Scope): string | null;
function getFunctionNameWithKind(node: ASTNode, sourceCode?: SourceCode): string;
function getFunctionHeadLocation(node: Node, sourceCode: SourceCode): object;
function getInnermostScope(initialScope: Scope, node: Node): Scope;
function isParenthesized(node: Node, sourceCode: SourceCode): boolean;
function isParenthesized(times: number, node: Node, sourceCode: SourceCode): boolean;Advanced static code analysis capabilities including value evaluation and side effect detection. Critical for rules that need to understand code behavior without execution.
function getStaticValue(node: Node, initialScope?: Scope): StaticValue | null;
function getStringIfConstant(node: Node, initialScope?: Scope): string | null;
function hasSideEffect(node: Node, sourceCode: SourceCode, options?: SideEffectOptions): boolean;
interface StaticValue {
value: any;
optional?: boolean;
}
interface SideEffectOptions {
considerGetters?: boolean;
considerImplicitTypeConversion?: boolean;
}Sophisticated system for tracking variable and module references across different import/export patterns. Essential for rules that need to understand cross-module dependencies.
class ReferenceTracker {
constructor(globalScope: Scope, options?: ReferenceTrackerOptions);
iterateGlobalReferences(traceMap: object): IterableIterator<ReferenceResult>;
iterateCjsReferences(traceMap: object): IterableIterator<ReferenceResult>;
iterateEsmReferences(traceMap: object): IterableIterator<ReferenceResult>;
}
interface ReferenceTrackerOptions {
mode?: "legacy" | "strict";
globalObjectNames?: string[];
}
interface ReferenceResult {
node: Node;
path: string[];
type: symbol;
info: any;
}
const READ: symbol;
const CALL: symbol;
const CONSTRUCT: symbol;
const ESM: symbol;Comprehensive collection of token type checking functions for identifying specific punctuation and syntax elements. Useful for rules that need precise token analysis.
function isArrowToken(token: Token): boolean;
function isCommaToken(token: Token): boolean;
function isSemicolonToken(token: Token): boolean;
function isColonToken(token: Token): boolean;
function isOpeningParenToken(token: Token): boolean;
function isClosingParenToken(token: Token): boolean;
function isOpeningBracketToken(token: Token): boolean;
function isClosingBracketToken(token: Token): boolean;
function isOpeningBraceToken(token: Token): boolean;
function isClosingBraceToken(token: Token): boolean;
function isCommentToken(token: Token): boolean;
// Negated versions (isNot...)
function isNotArrowToken(token: Token): boolean;
function isNotCommaToken(token: Token): boolean;
// ... (all positive predicates have isNot... equivalents)Specialized pattern matching class for complex regex operations with proper escape sequence handling. Ideal for rules that need sophisticated string pattern detection.
class PatternMatcher {
constructor(pattern: RegExp, options?: PatternMatcherOptions);
execAll(str: string): IterableIterator<RegExpExecArray>;
test(str: string): boolean;
[Symbol.replace](str: string, replacer: string | Function): string;
}
interface PatternMatcherOptions {
escaped?: boolean;
}interface Token {
type: string;
value: string;
loc: SourceLocation;
range: [number, number];
}
interface Node {
type: string;
loc: SourceLocation;
range: [number, number];
parent?: Node;
}
interface Scope {
type: string;
set: Map<string, Variable>;
upper: Scope | null;
childScopes: Scope[];
block: Node;
}
interface Variable {
name: string;
defs: Definition[];
references: Reference[];
}
interface SourceCode {
getTokenBefore(node: Node, filter?: function): Token | null;
getTokenAfter(node: Node, filter?: function): Token | null;
getFirstToken(node: Node, skip?: number): Token;
getText(node: Node): string;
visitorKeys?: object;
}