DEV Community

Cover image for Linters...How ESLint works?

Posted on • Updated on

Linters...How ESLint works?


Linters. The little things that remind us of every mistake we ever made. That is one definition of linters. In this blog, I will try to get you a little bit closer to linter architecture, usage, and benefits of using a linter. Buckle up, and prepare to find out what are those little sneaky things that always know when you're wrong!



IT'S ALIVE! - Stephen Curtis Johnson

Lint, or a linter is a static code analysis tool, that is used in such a way, that can flag programming errors, bugs, bad constructs, or stylistic errors.

Stephen Curtis Johnson, a computer scientist who worked at Bell Labs, father of the Yacc, spell, Portable C Compiler is also the father of the Lint.

The term "lint" was derived from the name of the tiny bits of fiber and fluff shed by clothing. In 1979, lint was used outside of Bell Labs for the first time in the seventh version of the Unix operating system.

Analysis that a linter is performing can also be performed by an optimizing compiler, which aims to generate faster code.

Lint-like tools are especially useful for dynamically typed languages, like JavaScript and Python.

Dynamic type checking is the process of verifying the type safety of a program at runtime.


Static Analysis means that automated software runs through your code source without executing it. What it does is, statically checks for potential bugs, memory leaks, or anything else that may be useful.



Image source HERE

The neverending battle as shown in the image has caused too many casualties. Then one day, the brave coding general stepped with his iron foot on the mountain bigger than the sky and yelled "Code standardization!!!"

Standardizing your code is very important. Having a guideline and running linters against the codebase avoid aesthetical changes in your pull request, like replacing all tabs for spaces, variable assignment indentation, or similar.


Did you know that in CSS, the Universal selector (*) may slow down a page loading time? Many linters include a performance check. They can add different kinds of performance improvements for experienced and newcomers developers.

There are many benefits of using linters. Beside code standardization, linters improve code review discussion level, it can make code look like it's written by a single person and much more.

抽 ESLint

ESLint is an open source JavaScript linting utility originally created by Nicholas C. Zakas in June 2013. JavaScript, being a dynamic and loosely-typed language, is especially prone to developer error. Without the benefit of a compilation process, JavaScript code is t typically executed in order to find syntax or other errors.

PHILOSOPHY (according to ESLint)

Everything is pluggable!

  • Rule API is used both by bundled and custom rules
  • Formatter API is used both by bundled and custom formatters
  • Additional rules and formatters can be specified at a runtime
  • Rules and formatters don't have to be bundled to be used

Every rule:

  • Is standalone
  • Can be turned off or on (nothin can be deemed "too important to turn off")
  • Can be set to a warning or error individually


  • Rules are "agenda-free" - ESLint does not promote any particular coding style
  • Any bundled rules are generalizable



Image source HERE


  • bin/eslint.js - a dumb wrapper that does nothing more than bootstrap ESLint, passing the command line arguments to CLI.
  • lib/api.js - This file exposes an object that contains public classes Linter, CLIEngine, RuleTester, and SourceCode.
  • lib/cli.js - this is the heart of the ESLint CLI. It takes an array of arguments and then uses ESLint to execute the commands. By keeping this as a separate utility, it allows others to effectively call ESLint from within another Node.js program as if it were done on the command line. The main call is cli.execute(). This is also the part that does all the file reading, directory traversing, input, and output.
  • lib/init/ - this module contains --init functionality that set up a configuration file for end users.
  • lib/cli-engine/ - this module is CLIEngine class that finds source code files and configuration files then does code verifying with the Linter class.
  • lib/linter/ - this module is the core Linter class that does code verifying based on configuration options. This file does no file I/O and does not interact with the console at all.
  • lib/rule-tester/ - this module is RuleTester class that is a wrapper around Mocha so that rules can be unit tested. This class lets us write consistently formatted tests for each rule that is implemented and be confident that each of the rules work.
  • lib/source-code/ - this module is SourceCode class that is used to represent the parsed source code. It takes in source code and the Program node of the AST representing the code.
  • lib/rules/ - this contains built-in rules that verify source code.

The CLI object is the API for the command line interface.

CLI object responsibilities:

  • Interprets command line arguments
  • Reads from the file system
  • Outputs to the console
  • Outputs to the filesystem
  • Uses a formatter
  • Returns the correct exit code

The CLI object may not call process.exit() directly, and perform any asynchronous operations.

THE CLIEngine object

The CLIEngine type represents the core functionality of the CLI except that it reads nothing from the command line and doesn't output anything by default. Instead, it accepts many (but not all) of the arguments that are passed into the CLI. It reads both configuration and source files as well as managing the environment that is passed into the Linter object.

Main method: executeOnFiles() - accepts an array of file and directory names to run the linter on.

CLIEngine object responsibilities:

  • Managing the execution environment for Linter
  • Reading from the file system
  • Reading configuration information from config files (including .eslintrc and package.json)

CLIEngine object may not:

  • Call process.exit() directly
  • Perform any asynchronous operations
  • Output to the console
  • Use formatters


The main method of the Linter object is verify() and accepts two arguments: the source text to verify and a configuration object (the baked configuration of the given configuration file plus command line options). The method first parses the given text with espree (or whatever the configured parser is) and retrieves the AST. The AST is produced with both line/column and range locations which are useful for reporting location of issues and retrieving the source text related to an AST node, respectively.

The LINTER object responsibilities:

  • Inspecting JavaScript code strings
  • Creating an AST for the code
  • Executing rules on the AST
  • Reporting back the results of the execution

The LINTER object may not:

  • Call process.exit() directly
  • Perform any asynchronous operations
  • Use Node.js-specific features
  • Access the file system
  • Call console.log() or any other similar method


Individual rules are the most specialized part of the ESLint architecture. Rules can do very little, they are simply a set of instructions executed against an AST that is provided. They do get some context information passed in, but the primary responsibility of a rule is to inspect the AST and report warnings.

These objects responsibilities are:

  • Inspect the AST for specific patterns
  • Reporting warnings when certain patterns are found

These objects may not:

  • Call process.exit() directly
  • Perform any asynchronous operations
  • Use Node.js-specific features
  • Access the file system
  • Call console.log() or any other similar method




Please leave the comment, tell me about you, about your work, comment your thoughts, connect with me via Twitter or LinkedIn.

Let this year be your year, let this year be our year. Until the next typing...

Have a nice time!


Top comments (0)