린터 아키텍처
이 글은 @leaysgur님이 leaysgur.github.io/posts에 올린 내용을 옮긴 것입니다.
apps/oxlint
oxlint 바이너리는 apps/oxlint 크레이트의 main.rs를 빌드한 결과입니다.
여기서 인자를 파싱한 뒤 LintRunner를 실행합니다.
crates/oxc_diagnostics
LintService가 oxc_diagnostics에 mpsc::channel Sender를 넘겨 린트 결과를 받습니다.
수신한 메시지를 포맷해 출력합니다. 포맷은 miette 크레이트가 담당합니다.
crates/oxc_linter
LintService부터 살펴보면:
self.runtime를Arc<Runtime>으로 보유Runtime이 린트할 경로를 보유- 실행 시
rayon으로Runtime경로를 병렬 순회 - 종료 신호로
None전송
Runtime: process_path()
- 경로에서 확장자와 내용을 추정
.[m|c]?[j|t]s또는.[j|t]sx확장 지원.vue,.astro,.svelte예외 처리 및script블록 부분 지원- JavaScript·TypeScript 소스 처리
- 린트 실행 후 결과를
DiagnosticService로 전송
Runtime: process_source()
- 파서로 소스를 AST로 파싱
SemanticBuilder로LintContext를 만들고Linter에 통과
crates/oxc_semantic: SemanticBuilder
SemanticBuilder는 소스에서 추출한 의미 정보를 구축합니다.
source_text: 소스 코드nodes: AST 노드classes: 클래스scopes: 스코프trivias: 주석jsdoc: JSDoc- 기타
SemanticBuilder가 빌드하면 SemanticBuilderReturn이 나오지만, LintContext에는 Semantic만 전달됩니다.
crates/oxc_linter: LintContext
컨텍스트를 나타내며 본체는 Semantic입니다. 각 정보용 getter와 린트 이슈를 알리는 diagnostic() 같은 메서드가 있습니다.
crates/oxc_linter: Linter
이 Linter의 run()이 린트 과정의 핵심입니다.
Linter는 대상 소스에 적용할 규칙을self.rules에 보유- 규칙마다 트레이트에 따라 세 가지 처리 중 구현 가능
- 이 세 패턴을 순차 실행
현재 구현된 규칙은 아래 목록을 참고하세요.
새 규칙을 추가할 때는 이 목록도 갱신해야 합니다.
린터 예제
저장소에 린터를 만드는 최소 코드 구성이 있습니다.