How ESLint Performs Static Analysis on JavaScript
ESLint is an open-source static analysis tool designed to identify problems, enforce coding standards, and prevent bugs in JavaScript code without executing it. To accomplish this, ESLint reads the source code, converts it into a structural representation known as an Abstract Syntax Tree (AST), traverses that tree to match nodes against predefined rules, and outputs any identified violations along with optional automated fixes.
1. Parsing Code into an Abstract Syntax Tree (AST)
The static analysis process begins with parsing. ESLint cannot efficiently analyze raw text strings with regular expressions alone, so it uses a JavaScript parser—by default, Espree (which is built on Acorn)—to tokenize and parse the code into an AST following the ESTree specification.
During this phase: * Lexical Analysis
(Tokenization): The source code string is converted into a list
of lexical tokens (such as keywords, identifiers, operators, and
punctuation). * Syntactic Analysis (Tree Construction):
The parser constructs a hierarchical tree of nodes representing the
program’s syntactic structure. For example, a const x = 5;
statement becomes a VariableDeclaration node containing an
Identifier node for x and a
Literal node for 5.
2. Tree Traversal Using the Visitor Pattern
Once the AST is built, ESLint traverses it from the root node downward using the visitor pattern.
As ESLint visits each node in the tree, it emits two distinct events:
* An enter event when arriving at a node (e.g.,
FunctionDeclaration). * An exit event when
leaving the node after all its child nodes have been visited (e.g.,
FunctionDeclaration:exit).
3. Applying and Executing Rules
ESLint rules are individual, isolated plugins or internal modules that register interest in specific AST node types or CSS-like AST selectors.
When ESLint traverses the AST: 1. Subscription:
Rules declare listener functions for specific node types (e.g.,
Identifier, BinaryExpression, or
:not(BlockStatement)). 2. Execution: When
the traverser reaches a matching node, it invokes the rule’s
corresponding callback function. 3. Contextual
Inspection: The rule evaluates the node’s properties, such as
whether a variable is assigned a prohibited value or whether a
comparison uses == instead of ===.
4. Scope and Token Analysis
Certain checks cannot be resolved by analyzing syntax nodes alone. ESLint supplements the AST with specialized helper systems:
- Scope Management (
eslint-scope): Tracks lexical scopes, closures, variable declarations, and variable references. This enables rules likeno-unused-varsandno-undefto determine where variables are defined and whether they are ever accessed. - Token and Comment Handling: For stylistic rules (such as indentation, semicolons, or spacing), ESLint allows rules to inspect the raw token stream and comments, determining character positions, line breaks, and token adjacencies.
5. Reporting and Automated Fixing
When a rule detects that an AST node or token sequence violates its
criteria: * Reporting: The rule calls
context.report() to register a diagnostic message
specifying the rule name, severity level (warning or error), message
description, and exact line and column numbers. *
Fixing: If the rule supports automatic fixes, it
provides a fix function returning instructions to insert,
remove, or replace specific character ranges in the original source
text. ESLint applies these edits iteratively until no further fixable
errors remain or an iteration limit is reached.