跪拜 Guibai
← All articles
Backend · JavaScript · Code Standards

ESLint Isn't Magic: How ASTs Turn Code Style Rules Into Machine-Readable Checks

By dzhd ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Understanding the AST traversal model turns ESLint from a black-box config file into a programmable quality gate. Developers who grasp that rules are just node-matching visitors can write custom lint rules for project-specific footguns instead of relying solely on presets.

Summary

A static analysis tool that never executes code, ESLint converts JavaScript and TypeScript into an AST—a structured tree of nodes like VariableDeclaration and Literal. Each rule, from `no-var` to `indent`, is a pattern matcher that traverses that tree and reports violations when it finds a forbidden shape. The flat config format (`eslint.config.mjs`) replaces the old nested `.eslintrc` with a flat array of configuration objects, each specifying file globs, plugins, language options, and rules.

Rule severity uses three levels: error (2) blocks commits for unambiguous mistakes like `var`, warn (1) flags suspicious patterns like `console.log` that require human judgment, and off (0) disables a rule entirely. The `--fix` flag auto-corrects style violations where the correct answer is deterministic—semicolons, quotes, indentation—but leaves judgment-call rules untouched.

A working setup pulls in four packages: the `eslint` core engine, `@eslint/js` for recommended rules, `globals` to declare browser or Node globals so ESLint doesn't falsely report `window is not defined`, and `typescript-eslint` to parse TypeScript syntax that ESLint's native parser cannot understand.

Takeaways
ESLint performs static analysis by parsing source code into an AST and walking every node, never executing the code itself.
The flat config format (`eslint.config.mjs`) uses a flat array of configuration objects, each with its own `files` glob, plugins, and rules, applied top to bottom.
Rule severity levels map to error (2), warn (1), and off (0); the numeric and string forms are equivalent.
Machine-determinable violations like `var` usage get error level, while intent-dependent patterns like `console.log` get warn level because a human must decide.
`--fix` auto-corrects only deterministic style rules (semicolons, quotes, indentation) and leaves judgment-call rules untouched.
`languageOptions.globals` from the `globals` package prevents false `not defined` errors for browser or Node built-ins.
`typescript-eslint` is required because ESLint's native parser cannot understand TypeScript syntax.
`defineConfig` from `eslint/config` provides editor type hints for the configuration object but adds no runtime behavior.
Conclusions

The distinction between error and warn levels encodes a practical philosophy: automate what's certain, defer to humans what's ambiguous. This prevents linting from becoming either too permissive or an obstructive gate that blocks legitimate code.

Flat config's array-of-objects structure makes configuration composable in a way the old nested `.eslintrc` format resisted—you can now merge, override, and share config slices as plain JavaScript values rather than wrestling with cascade semantics.

The AST-based rule model means ESLint's power is bounded by parser accuracy. Any syntax the parser cannot turn into correct AST nodes (like new TypeScript features before `typescript-eslint` updates) is invisible to all rules, creating a silent blind spot.

Concepts & terms
AST (Abstract Syntax Tree)
A tree representation of source code structure where each node corresponds to a language construct (VariableDeclaration, Literal, Identifier). ESLint parses code into an AST and then walks the tree to apply rules.
Flat Config
ESLint's newer configuration format (`eslint.config.mjs`) that replaces nested `.eslintrc` files with a flat array of configuration objects, each specifying its own file scope, plugins, and rules.
Static Analysis
Analyzing code without executing it, by examining its text and structure. Contrasts with dynamic analysis, which runs the code to observe behavior.
Rule Severity Level
A setting per ESLint rule that determines the response to a violation: `2` or `"error"` blocks commits, `1` or `"warn"` warns without blocking, `0` or `"off"` disables the rule.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗