Skip to content

Linter Architecture

This article is originally posted on leaysgur.github.io/posts by @leaysgur.

apps/oxlint

The oxlint binary is the result of building main.rs from the apps/oxlint crate.

Cargo.toml Configuration

Here, it parses arguments and then runs the LintRunner.

Lint Execution Flow

crates/oxc_diagnostics

The LintService passes the mpsc::channel Sender to oxc_diagnostics to receive lint results.

Receiving Lint Results

It formats and displays the received messages. The formatting is done by the miette crate.

miette Crate Reference

crates/oxc_linter

Starting with the LintService:

  • Holds self.runtime as Arc<Runtime>
  • Runtime holds paths for linting
  • Upon running, it iterates over Runtime paths in parallel using rayon
  • It sends a None to finish

LintService Implementation

Runtime: process_path()

  • Infers extension and content from the path
  • Supports .[m|c]?[j|t]s or .[j|t]sx extensions
  • Exceptions for .vue, .astro, and .svelte with partial support for script blocks
  • Processes JavaScript and TypeScript sources
  • Executes linting and sends results to DiagnosticService

Runtime Path Processing

Runtime: process_source()

  • Processes the source with a parser into an AST
  • Creates a LintContext from SemanticBuilder and runs it through Linter

Runtime Source Processing

crates/oxc_semantic: SemanticBuilder

SemanticBuilder builds semantic information extracted from the source.

SemanticBuilder Source

  • source_text: Source code
  • nodes: AST nodes
  • classes: Classes
  • scopes: Scopes
  • trivias: Comments
  • jsdoc: JSDoc
  • etc.

When SemanticBuilder builds, it generates SemanticBuilderReturn, but only Semantic is passed to LintContext.

SemanticBuilder Return

crates/oxc_linter: LintContext

LintContext Source

Represents the context, with Semantic as the main body. It includes getters for each piece of information and methods like diagnostic() to notify of linting issues.

crates/oxc_linter: Linter

Linter Source

The run() function of this Linter is the core of the linting process.

  • Linter holds rules to execute on the target source in self.rules
  • Each rule can implement three types of processing as per the trait
  • It sequentially executes these three patterns

For the currently implemented rules, refer to this list.

Implemented Rules

For adding new rules, remember to update this list.

Linter Example

The repository provides the minimum code configuration for creating a linter.

Minimal Linter Code

Released under the MIT License.