DEV Community

CodeWithDhanian
CodeWithDhanian

Posted on

How JavaScript Lint Rules Work (and Why Abstract Syntax Trees Matter)

Linting tools like ESLint have become an essential part of modern JavaScript development. They help enforce code quality, prevent bugs, and maintain consistent codebases across large teams. But few developers understand how lint rules work behind the scenes. At the core of this powerful system is a data structure known as the Abstract Syntax Tree (AST).

This article will demystify lint rules by showing how they interact with ASTs, provide examples, and even demonstrate how to write your own custom lint rule using ESLint.

What Is a Linter?

A linter is a static code analysis tool. It scans your code without executing it, looking for issues like:

  • Syntax errors
  • Bad practices
  • Style violations
  • Code smells
  • Security flaws

Popular JavaScript linters:

  • ESLint – Highly configurable and plugin-based.
  • Prettier – An opinionated code formatter.
  • JSHint – Lightweight and older alternative.

Example of ESLint in action:

var name = 'John'
console.log(name)
Enter fullscreen mode Exit fullscreen mode

If your ESLint config enforces semicolons and disallows var, it would report:

1:1  error  Unexpected var, use let or const instead
2:17 error  Missing semicolon
Enter fullscreen mode Exit fullscreen mode

What Is an Abstract Syntax Tree (AST)?

An Abstract Syntax Tree is a structured, tree-like representation of your source code. It breaks your code into nested nodes, each representing a piece of syntax.

Code example:

const result = 4 + 6;
Enter fullscreen mode Exit fullscreen mode

The AST will parse this into:

  • A VariableDeclaration node

    • With a VariableDeclarator node
    • Identifier: result
    • BinaryExpression node
      • left: Literal (4)
      • operator: +
      • right: Literal (6)

ASTs ignore formatting. Whether you use tabs, spaces, semicolons, or line breaks, the AST focuses solely on syntax and structure.

To visualize this, you can use AST Explorer.

How ESLint Uses ASTs to Enforce Rules

Here’s what happens when you run ESLint:

  1. Parsing: Your code is parsed into an AST using a parser like Espree.
  2. Traversing: ESLint walks the tree node by node.
  3. Rule Checking: ESLint applies each rule to relevant nodes.
  4. Reporting: If a rule detects a violation, it reports it (and may fix it).

Example: no-console Rule

Code:

console.log('Debugging this line...');
Enter fullscreen mode Exit fullscreen mode

ESLint:

  • Finds a CallExpression node.
  • Sees that the callee is console.log.
  • Applies the no-console rule.
  • Returns a warning or error if it's disallowed.

Writing Your Own ESLint Rule

You can define a custom lint rule using the ESLint plugin system. Let’s write a simple rule that disallows identifiers named foo.

1. Rule Definition

module.exports = {
  meta: {
    type: 'problem',
    docs: {
      description: 'disallow variable named foo',
    },
    messages: {
      noFoo: 'Avoid using "foo" as a variable name.',
    }
  },
  create(context) {
    return {
      Identifier(node) {
        if (node.name === 'foo') {
          context.report({
            node,
            messageId: 'noFoo',
          });
        }
      }
    };
  }
};
Enter fullscreen mode Exit fullscreen mode

2. Sample Input That Triggers It

const foo = 10; // ESLint will report this line
Enter fullscreen mode Exit fullscreen mode

3. ESLint Output

1:7  error  Avoid using "foo" as a variable name.
Enter fullscreen mode Exit fullscreen mode

Real AST Node Types You’ll Encounter

Here’s a cheat sheet of common node types:

Node Type Description
Identifier Variable or function name
Literal Strings, numbers, booleans
BinaryExpression Math/logical ops like a + b
CallExpression Function calls like fn()
VariableDeclaration let, const, or var
FunctionDeclaration function foo() {}
ArrowFunctionExpression const a = () => {}

By targeting these node types, you can write ESLint rules to enforce or restrict just about anything.

Use Cases for Custom Lint Rules

  • Enforce architectural conventions (e.g., prevent direct API calls in UI components)
  • Catch framework-specific mistakes (e.g., disallow setState in React useEffect)
  • Create security checks (e.g., prevent use of eval, innerHTML)

Writing custom rules ensures your entire team writes code that conforms to your organization’s expectations, beyond standard linting.

Experimenting With ASTs

Try this at AST Explorer:

Input:

const total = price + tax;
Enter fullscreen mode Exit fullscreen mode

You'll see:

  • VariableDeclaration at the top
  • Inside: VariableDeclarator with name total
  • Right-hand side: BinaryExpression with left price, operator +, right tax

This shows exactly how tools see and navigate your code.

Summary

Linting tools are more than just static checkers — they're syntax tree traversers. With ASTs, they understand the structure of your code, not just the characters on the screen.

Key Takeaways:

  • ASTs convert code into meaningful structures.
  • ESLint rules walk through these structures and apply checks.
  • You can create your own lint rules by targeting specific node types.
  • AST tools empower you to build better, safer, and more maintainable JavaScript.

Learn JavaScript in Depth — Including ASTs, Tools & Projects

Want to dive even deeper into JavaScript development, including topics like ASTs, tooling, and advanced code techniques?

Explore my in-depth ebook:

JavaScript Complete Guide: Mastering Modern JavaScript With Projects

This book includes:

  • Beginner to advanced JavaScript concepts
  • Code samples and visual guides
  • Hands-on projects to practice and solidify your skills
  • Deep dives into how tools like ESLint, Babel, and Prettier work internally

Perfect for developers who want to move from just writing JavaScript to understanding it deeply.

Get the book here →

Sentry image

How we debugged a broken checkout flow in Flask + React

Dropped carts = lost revenue. See how Sentry tracing can catch a full-stack bug in a Flask + React checkout flow—before it can become a support fire drill.

Read more →

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay