Skip to content

ast-grep Config

코딩 에이전트가 코드베이스를 쉽게 탐색하도록 돕는 ast-grep 규칙.

Updated View as Markdown

@pleaseai/ast-grep-config는 코딩 에이전트가 코드베이스를 쉽게 탐색하도록 돕는 ast-grep 규칙 모음입니다. 공개 심볼은 이름으로 찾을 수 있어야 하고, 에러 타입은 지정된 파일에 모으며, 소스 파일 안에 테스트를 두지 않습니다. TypeScript, Dart, Kotlin, Java, Rust에 대해 ADR-0022의 2층(구조 규칙)을 집행합니다.

모든 규칙은 **경고(warning)**로 배포됩니다. 직접 규칙의 심각도를 올리지 않는 한 빌드를 막지 않습니다.

설치

ast-grep 바이너리는 peer dependency인 @ast-grep/cli가 제공합니다. 프로젝트의 bin 경로에 ast-grep이 잡히도록 이 패키지와 함께 설치하세요.

bun을 쓴다면 trustedDependencies에 @ast-grep/cli를 추가해 postinstall 단계가 실행되게 하세요. 그렇지 않으면 ast-grep을 실행할 때마다 대체 경로 경고가 출력됩니다(please-style check는 영향을 받지 않습니다).

package.jsonjson
{
  "trustedDependencies": ["@ast-grep/cli"]
}

사용법

프로젝트의 sgconfig.yml이 규칙 디렉터리를 가리키게 합니다.

sgconfig.ymlyaml
ruleDirs:
  - node_modules/@pleaseai/ast-grep-config/rules
bunx ast-grep scan

설정 파일을 따로 두지 않고 패키지의 설정을 바로 쓸 수도 있습니다.

bunx ast-grep scan -c node_modules/@pleaseai/ast-grep-config/sgconfig.yml

다섯 가지 원칙

Slug 원칙
code-greppable-public-symbols 공개 심볼은 이름 있는 선언으로 정의하고 노출해, 이름 검색 한 번으로 정의와 사용처를 모두 찾는다.
code-filename-matches-primary-symbol 공개 심볼이 하나인 파일은 언어의 파일 이름 규약으로 정규화했을 때 그 심볼 이름과 일치한다.
code-error-types-in-dedicated-module 모듈의 에러 타입은 지정된 에러 파일이나 패키지에 모은다.
test-path-derivable-from-source 테스트는 툴체인이 정한 테스트 루트 아래, 대상 소스 경로를 미러링한 위치에 둔다.
test-helpers-in-dedicated-location 여러 테스트가 공유하는 헬퍼는 지정된 위치에 둔다.

검사는 두 층으로 나뉩니다.

  • 2층 — 이 패키지의 ast-grep 규칙으로, ast-grep scan으로 실행합니다.
  • 3층 — ast-grep이 보지 못하는 것(파일 이름, 테스트 경로, 헬퍼 공유 여부)을 맡는 경로 검사기 please-style check입니다. 이 패키지의 extract/ 디렉터리에 있는 추출 규칙을 실행합니다. extract/는 ruleDirs에 들어 있지 않으므로 ast-grep scan 출력에는 나타나지 않습니다.

규칙

규칙 Slug 언어
ts-no-default-export code-greppable-public-symbols TypeScript
tsx-no-default-export code-greppable-public-symbols TSX
rust-no-glob-reexport code-greppable-public-symbols Rust
ts-error-outside-errors-file code-error-types-in-dedicated-module TypeScript
tsx-error-outside-errors-file code-error-types-in-dedicated-module TSX
dart-error-outside-errors-file code-error-types-in-dedicated-module Dart
kotlin-error-outside-errors-file code-error-types-in-dedicated-module Kotlin
java-error-outside-error-package code-error-types-in-dedicated-module Java
rust-error-outside-error-file code-error-types-in-dedicated-module Rust
ts-no-in-source-test test-path-derivable-from-source TypeScript
tsx-no-in-source-test test-path-derivable-from-source TSX

규칙마다 옆에 README가 있고, 규칙의 이유, 틀린 예와 올바른 예, 위반을 고치는 단계를 적어 두었습니다(영문). 경고 메시지에 slug와 node_modules 안의 README 경로가 들어 있어 에이전트가 메시지만 보고도 위반을 고칠 수 있습니다.

[code-greppable-public-symbols] Default export hides the symbol's name from
grep. Export a named declaration instead. Fix guide:
node_modules/@pleaseai/ast-grep-config/rules/typescript/ts-no-default-export.md

default export 금지

ts-no-default-export와 tsx-no-default-export는 export default …, export { foo as default }, export { default } from './x'를 잡아냅니다. default import는 가져오는 쪽마다 로컬 이름을 마음대로 정할 수 있어서, 선언 이름으로 검색하면 그런 import 위치를 놓칩니다. named import는 내보낸 이름을 반드시 적어야 합니다.

// 틀린 예
export default class UserService {}

// 올바른 예
export class UserService {}

glob 재export 금지

rust-no-glob-reexport는 가시성 수식어(pub, pub(crate), pub(super))가 붙은 use 중 *가 들어간 것을 잡아냅니다. use super::*; 같은 비공개 glob import는 대상이 아닙니다. glob을 지금 내보내는 항목의 명시적 목록으로 바꾸세요.

// 틀린 예
pub use crate::model::*;

// 올바른 예
pub use crate::model::{Account, User};

에러 타입은 전용 모듈에

ast-grep에는 타입 정보가 없으므로 에러 규칙은 이름으로 판단합니다. 클래스 기반 언어에서는 상위 타입 이름이 Error 또는 Exception으로 끝나거나, 자신의 이름이 Error 또는 Exception으로 끝나면서 상위 타입도 있는 클래스가 대상입니다.

  • TypeScript / TSX: extends로 지정한 상위 클래스만 확인합니다. implements는 대상이 아니며, 이름이 *Error/*Exception인 클래스는 extends 절이 있을 때만 대상입니다.
  • Java: 상위 클래스만 확인합니다(Throwable도 포함). implements는 대상이 아닙니다.
  • Dart: 상위 클래스 또는 구현한 타입을 확인합니다. 이름이 *Error/*Exception인 클래스는 상위 클래스 또는 implements 절이 있어야 합니다.
  • Kotlin: 모든 상위 타입을 확인하며(Throwable도 포함) class와 object 선언이 대상입니다.

Rust는 이름이 Error로 끝나는(Exception은 제외) struct/enum, #[derive(…Error)]가 붙은 struct/enum, 그리고 모든 impl Error for T(std::error::Error, core::error::Error 포함)를 잡아냅니다. 에러 타입을 두는 위치는 언어마다 다릅니다.

언어 에러 타입 위치 함께 제외되는 경로
TypeScript / TSX 모듈 디렉터리의 errors.ts *.d.ts, *.test.*, *.spec.*, test/, tests/, __tests__/
Dart / Flutter 라이브러리 디렉터리의 errors.dart *_test.dart, test/, integration_test/, test_driver/
Kotlin 패키지 디렉터리의 Errors.kt src/test/, src/testFixtures/, 이름이 Test로 끝나는 소스 세트
Java 모듈 아래 error/ 하위 패키지 src/test/, src/testFixtures/, src/androidTest/
Rust 모듈 루트 옆 error.rs(또는 error/ 모듈) tests/ 아래 통합 테스트

검사하는 것은 위치뿐입니다. 에러 파일에 헬퍼나 import가 있어도 됩니다.

소스 내 테스트 금지

ts-no-in-source-test와 tsx-no-in-source-test는 Vitest in-source 테스트(if (import.meta.vitest) { … })를 잡아냅니다. test/** glob으로 찾을 수 없고, 프로덕션 빌드에서 제거하려면 번들러 define이 필요하기 때문입니다. 블록을 패키지 테스트 루트 아래, 소스 경로를 미러링한 테스트 파일로 옮기세요. src/math/add.ts라면 test/math/add.test.ts가 됩니다.

프레임워크 파일

프레임워크가 형태를 정하는 파일은 ts-no-default-export와 tsx-no-default-export의 ignores 목록으로만 제외합니다.

  • 타입 선언: *.d.ts, *.d.mts, *.d.cts
  • 설정 파일: *.config.ts와 *.config.*.ts(예: vite.config.prod.ts). .mts, .cts, .tsx 형태도 포함합니다
  • Storybook story(*.stories.ts, *.stories.tsx 등), .vitepress/, .storybook/
  • Nuxt 4: app/pages/, app/layouts/, app/middleware/, app/plugins/, 그리고 app/app.config.ts, app/router.options.ts
  • Nitro: server/api/, server/routes/, server/middleware/, server/plugins/, server/tasks/

전체 목록은 ts-no-default-export.yml과 tsx-no-default-export.yml에 있습니다. 다른 규칙은 이 경로를 제외하지 않습니다. 단, 타입 선언 파일은 ts-error-outside-errors-file과 tsx-error-outside-errors-file에서도 제외됩니다.

app/ 없이 루트에 pages/, layouts/, middleware/, plugins/를 두는 Nuxt 3 구조는 제외하지 않습니다. **/plugins/** 같은 glob은 이름이 plugins인 무관한 디렉터리까지 모두 제외해 버리기 때문입니다. ast-grep은 배포된 규칙의 ignores를 덮어쓸 수 없으므로 명령줄에서 규칙 범위를 좁히세요. 기본 스캔에서는 두 규칙을 끄고, 프레임워크 디렉터리를 제외한 채 한 번 더 실행합니다.

ast-grep scan --off=ts-no-default-export --off=tsx-no-default-export
ast-grep scan --filter '^(ts|tsx)-no-default-export$' \
  --globs '!pages/**' --globs '!layouts/**' \
  --globs '!middleware/**' --globs '!plugins/**' --globs '!app.config.ts'

CI와 에이전트가 같은 명령을 실행하도록 두 명령을 하나의 패키지 스크립트(예: lint:structure)에 넣으세요. Nuxt 4의 app/ 구조로 옮기면 이 두 단계 대신 일반 ast-grep scan을 한 번 실행하세요. 첫 번째 명령만 남기면 두 규칙이 모든 파일에서 꺼집니다.

호환성

  • @ast-grep/cli ^0.45.3
  • Node.js >=22.0.0
Navigation

검색어를 입력하세요…

↑↓ 이동↵ 선택Esc 닫기