Skip to content

린터 아키텍처

이 글은 @leaysgur님이 leaysgur.github.io/posts에 올린 내용을 옮긴 것입니다.

apps/oxlint

oxlint 바이너리는 apps/oxlint 크레이트의 main.rs를 빌드한 결과입니다.

Cargo.toml 설정

여기서 인자를 파싱한 뒤 LintRunner를 실행합니다.

린트 실행 흐름

crates/oxc_diagnostics

LintServiceoxc_diagnosticsmpsc::channel Sender를 넘겨 린트 결과를 받습니다.

린트 결과 수신

수신한 메시지를 포맷해 출력합니다. 포맷은 miette 크레이트가 담당합니다.

miette 크레이트

crates/oxc_linter

LintService부터 살펴보면:

  • self.runtimeArc<Runtime>으로 보유
  • Runtime이 린트할 경로를 보유
  • 실행 시 rayon으로 Runtime 경로를 병렬 순회
  • 종료 신호로 None 전송

LintService 구현

Runtime: process_path()

  • 경로에서 확장자와 내용을 추정
  • .[m|c]?[j|t]s 또는 .[j|t]sx 확장 지원
  • .vue, .astro, .svelte 예외 처리 및 script 블록 부분 지원
  • JavaScript·TypeScript 소스 처리
  • 린트 실행 후 결과를 DiagnosticService로 전송

Runtime 경로 처리

Runtime: process_source()

  • 파서로 소스를 AST로 파싱
  • SemanticBuilderLintContext를 만들고 Linter에 통과

Runtime 소스 처리

crates/oxc_semantic: SemanticBuilder

SemanticBuilder는 소스에서 추출한 의미 정보를 구축합니다.

SemanticBuilder 소스

  • source_text: 소스 코드
  • nodes: AST 노드
  • classes: 클래스
  • scopes: 스코프
  • trivias: 주석
  • jsdoc: JSDoc
  • 기타

SemanticBuilder가 빌드하면 SemanticBuilderReturn이 나오지만, LintContext에는 Semantic만 전달됩니다.

SemanticBuilder 반환

crates/oxc_linter: LintContext

LintContext 소스

컨텍스트를 나타내며 본체는 Semantic입니다. 각 정보용 getter와 린트 이슈를 알리는 diagnostic() 같은 메서드가 있습니다.

crates/oxc_linter: Linter

Linter 소스

Linterrun()이 린트 과정의 핵심입니다.

  • Linter는 대상 소스에 적용할 규칙을 self.rules에 보유
  • 규칙마다 트레이트에 따라 세 가지 처리 중 구현 가능
  • 이 세 패턴을 순차 실행

현재 구현된 규칙은 아래 목록을 참고하세요.

구현된 규칙

새 규칙을 추가할 때는 이 목록도 갱신해야 합니다.

린터 예제

저장소에 린터를 만드는 최소 코드 구성이 있습니다.

최소 린터 코드