Navigation

7. 도구 설정

자동 검사할 항목은 biome으로 설정하고, 도구가 검사하지 못하는 항목은 리뷰에서 확인합니다.

7.1 Biome 설정으로 자동 검사할 규칙을 명시합니다

자동 검사와 리뷰의 역할을 구분해 판단이 필요한 내용에 집중합니다.

설정이 담당하는 것

기계적으로 판정할 수 있는 규칙은 아래 Biome 설정으로 검사하고, 의미 판단은 리뷰에서 확인합니다.

Biome 규칙담당 컨벤션
style/noEnum, style/useAsConstAssertion규칙 1.7
style/noRestrictedImports규칙 2.5. 심볼 없는 상대경로 예외는 ./*.css 패턴으로 근사합니다
style/useNamingConvention, style/useFilenamingConvention규칙 2.3의 심볼, 파일 표기
style/noParameterAssign, style/useConst, style/noNestedTernary규칙 3.7의 재할당, 중첩 삼항 제한
correctness/noUnusedFunctionParameters규칙 1.5
complexity/useMaxParams규칙 3.2의 인자 세 개 기준
style/noMagicNumbers규칙 4.4
suspicious/noExplicitAny, style/noNonNullAssertion규칙 1.6
plugins의 GritQL 파일규칙 5.1의 ??, || 오른쪽 리터럴

규칙 2.4의 가져오기, 이름 붙인 내보내기, 배럴 제한은 아래 규칙이 담당합니다.

기본 매개변수와 삼항의 대체 리터럴은 GritQL 검사 밖이므로 리뷰합니다. recommended에 이미 든 규칙도 담당 컨벤션을 드러내려고 설정에 명시합니다.

리뷰가 담당하는 것

대상도구 한계처리
모듈 const, 객체 키의 역할허용된 snake_case는 불변 데이터 상수와 그 키에만 적용됨함수, 스키마, 요청 객체와의 구분은 리뷰합니다
허용된 PascalCase의 용도합성 컴포넌트의 {Root, Header, Footer}와 컴포넌트 선언 때문에 허용됨일반 함수, 지역 변수의 camelCase는 리뷰합니다
폴더 이름단수 kebab-case는 파일 이름 검사 대상이 아님리뷰합니다
const 화살표 선언, 이름 붙인 함수의 블록 본문style/useConsistentArrowReturn의 style: "always"는 예외까지 막음켜지 않고 규칙 3.1를 리뷰합니다
넓은 스코프에서 push로 누적useConst는 재할당만 확인함리뷰합니다
사용하지 않는 매개변수를 아예 생략검사는 남겨 둔 매개변수만 봄리뷰합니다
as, @ts-expect-error의도를 구분하지 못함위의 타입 좁히기 규칙에 따라 리뷰합니다
한 줄 문서 블록 /** … */대응 검사가 없음규칙 6.4를 리뷰합니다
config/env.ts 밖의 import.meta.env, process.env대응 검사가 없음규칙 2.6에 따라 리뷰합니다

설정 예외

설정 예외적용 범위와 이유
테스트의 noMagicNumbers 해제리터럴 자체가 기대 계약인 값에 적용합니다. 설정값끼리 비교하도록 바꾸지 않으며, 소스가 이미 이름 붙인 값은 테스트도 가져다 씁니다
도구 설정 파일의 noDefaultExport 해제vite.config.ts처럼 도구가 default를 요구하는 진입점에 적용합니다. 내보내기 규칙의 예외를 설정에 반영합니다
style/useFragmentSyntax 비활성recommended에 없으며 별도로 켜지 않습니다. 프레임워크 규칙이 <Fragment>를 요구합니다

컨벤션 항목을 설정으로 고정합니다.

{
	"linter": {
		"enabled": true,
		"rules": {
			"preset": "recommended",
			"complexity": {"useMaxParams": {"level": "error", "options": {"max": 3}}},
			"correctness": {"noUnusedFunctionParameters": "error"},
			"suspicious": {"noExplicitAny": "error"},
			"performance": {"noNamespaceImport": "error", "noBarrelFile": "error", "noReExportAll": "error"},
			"style": {
				"noDefaultExport": "error",
				"noEnum": "error",
				"noMagicNumbers": "error",
				"noNestedTernary": "error",
				"useAsConstAssertion": "error",
				"noNonNullAssertion": "error",
				"noParameterAssign": "error",
				"useConst": "error",
				"useImportType": "error",
				"useFilenamingConvention": {
					"level": "error",
					"options": {"filenameCases": ["kebab-case"]}
				},
				"noRestrictedImports": {
					"level": "error",
					"options": {
						"patterns": [
							{"group": ["../**", "./**", "!./*.css"], "message": "Import with the absolute alias. Only a bare file import may use ./ for the same folder."}
						]
					}
				},
				"useNamingConvention": {
					"level": "error",
					"options": {
						"strictCase": false,
						"conventions": [
							{"selector": {"kind": "typeLike"}, "formats": ["PascalCase"]},
							{"selector": {"kind": "const", "scope": "global"}, "formats": ["camelCase", "PascalCase", "snake_case"]},
							{"selector": {"kind": "objectLiteralProperty"}, "formats": ["camelCase", "PascalCase", "snake_case"]},
							{"selector": {"kind": "typeProperty"}, "formats": ["camelCase"]},
							{"selector": {"kind": "variable"}, "formats": ["camelCase", "PascalCase"]}
						]
					}
				}
			}
		}
	},
	"overrides": [
		{
			"includes": ["**/*.test.ts"],
			"linter": {"rules": {"style": {"noMagicNumbers": "off"}}}
		},
		{
			"includes": ["**/*.config.ts", "**/*.config.js"],
			"linter": {"rules": {"style": {"noDefaultExport": "off"}}}
		}
	]
}

??, || 오른쪽 리터럴은 GritQL 플러그인으로 잡습니다.

{
	"plugins": ["./no-literal-fallback.grit"]
}
language js

or {
	`$left ?? $right`,
	`$left || $right`
} where {
	$right <: or { string(), number(), `true`, `false`, `[]`, `{}` },
	register_diagnostic(span = $right, message = "Do not put a literal on the right of ?? or ||. Reference a declared name.")
}