검색/코드 동작을 바꾸지 않는 자동 수정이 있는 정적 분석 규칙 만들기

코드 동작을 바꾸지 않는 자동 수정이 있는 정적 분석 규칙 만들기

정적 분석(lint) 규칙을 만들 때 씁니다. 흔한 패턴만 대상으로 하고, 기존 헬퍼를 다시 쓰며, 안전할 때만 자동 수정을 붙이고, 까다로운 구문도 테스트하며, 생성되는 문서는 손으로 고치지 않고 다시 생성합니다.

이 AI 규칙을 사용하려면
## 흔한 패턴만 대상으로 하고 드문 경우는 빼기 각 규칙은 개념적으로 단순하게 유지합니다. 반복해서 나타나며 가치가 높은 패턴을 대상으로 삼고, 드문 경계 조건을 지원하면 규칙이 불명확해지거나 수정이 위험해질 경우에는 지원 대상에서 제외합니다. 생성 함수와 메타데이터로 안정적인 규칙 계약을 정의합니다. 이벤트 기반 어댑터에서는 일반적인 방문자 맵을 반환하지 말고, 제공된 훅을 통해 진입 및 종료 리스너를 등록합니다. 리스너는 문제 객체를 반환하거나 yield해야 하며, 보고는 어댑터가 수행하게 합니다. 각 문제에는 관련 노드와 메시지를 명시하고, 필요한 경우에만 데이터, 수정 또는 제안을 추가합니다. 수정 API가 중단 메커니즘을 제공한다면 안전한 편집임을 입증할 수 없을 때마다 이를 사용합니다. 옵션 기본값은 메타데이터에 두어 프레임워크가 일관되게 병합하도록 하고, 규칙 안에서 병합 로직을 중복 구현하지 않습니다. ## 규칙을 넣을 사전 설정을 정하고 옵션 이름을 check로 시작하기 사전 설정 배치를 제품 결정으로 취급합니다. - 이견이 거의 없는 규칙은 가장 안전한 사전 설정과 그보다 범위가 넓은 모든 사전 설정에 넣습니다. - 유용하지만 특정 관점을 담은 기본값은 권장 사전 설정과 그보다 넓은 컬렉션에만 넣습니다. - 틈새 용도이거나 명시적으로 선택해야 하는 동작은 기본 사전 설정에서 제외합니다. “특정 관점을 강요하지 않음”과 “지나치게 독단적임”을 혼동하지 않습니다. 확실하지 않다면 제안하는 수준을 밝히고 유지관리자에게 결정을 요청합니다. 외부에 제공하는 불리언 옵션은 `true`가 항상 동작을 활성화하도록 `check*` 형식의 긍정적인 이름을 사용합니다. 무시할 패턴 목록에는 `ignore` 같은 관례적인 이름을 계속 사용할 수 있습니다. 지원하는 모든 언어를 명시적으로 선언합니다. 로직이 파일 이름, 원시 텍스트, 주석 또는 지시문에만 의존한다면 실용적인 범위에서 여러 언어를 지원하고, 언어별 노드 유형을 추상화하는 루트 및 주석 보조 함수를 사용합니다. ## 반환하는 값이 드러나게 헬퍼 이름을 짓고 기존 유틸리티 다시 쓰기 비공개 보조 함수는 외부에서 관찰 가능한 계약에 따라 이름을 정합니다. `is*`, `has*`, `should*`, `can*`, `needs*`는 반드시 불리언 값을 반환해야 하며, 의도하지 않은 undefined 값보다 명시적인 `false`를 반환하는 편이 좋습니다. 선택적인 문제 하나에는 `get*Problem`, 여러 문제에는 `get*Problems`를 사용합니다. `report*`는 직접 보고하는 보조 함수에만 사용합니다. 보고 또는 yield를 술어 결과와 결합하지 않습니다. 문제를 별도로 구성한 다음 호출 위치에서 불리언 결정을 내립니다. 보조 함수를 추가하기 전에 저장소의 AST, 범용 유틸리티, 수정 처리, 공유 규칙 모듈을 살펴보고, 그다음 신뢰할 수 있는 생태계 유틸리티를 확인합니다. 정적 평가, 변수 조회, 부작용 감지, 토큰 검사, 참조 해석, 괄호, 세미콜론, 수정 구성에는 통합 내보내기와 기존 보조 함수를 재사용합니다. 명확하게 재사용할 수 있을 때만 보조 함수를 공용으로 승격하고, 작은 규칙 전용 로직은 로컬에 유지합니다. ## 코드가 반드시 빠져나가는지 판단할 때만 제어 흐름 분석 쓰기 규칙이 분기 또는 함수가 return, throw, break, continue, 완전한 선택 또는 무한 루프 같은 구조를 통해 항상 종료되는지 판단해야 한다면 프레임워크의 제어 흐름 분석을 사용합니다. 예외 처리, 레이블, 중첩, 도달 불가능한 구간을 다룰 때는 AST를 직접 순회하는 방식의 정확도가 일반적으로 더 낮습니다. 분기 분석에서는 저장소의 분기 종료 추적기를 등록하고, 바깥쪽 조건문을 빠져나온 뒤 조회합니다. 함수 분석에서는 코드 경로마다 세그먼트 집합을 유지하여 중첩 함수가 부모 함수를 오염시키지 않게 합니다. 관련 AST 노드를 빠져나올 때 도달 가능성을 기록합니다. 프레임워크가 현재 세그먼트를 이미 정리했다면 코드 경로가 끝날 때까지 기다리지 않습니다. 확인할 내용이 마지막 문장이 특정 유형인지, return이 어디에 있는지, 로컬 수정 처리기가 return 또는 throw로 끝나는지뿐이라면 더 단순한 구문 검사를 사용합니다. 실제 도달 가능성 요구가 없으면 제어 흐름 메커니즘을 도입하지 않습니다. ## 자동 생성된 색인과 문서 머리말은 손으로 고치지 말고 다시 생성하기 편집 전에 자동 생성 파일과 자동 생성 영역을 식별합니다. 자동 생성된 인덱스, 표 또는 문서 헤더를 절대로 직접 편집하지 않습니다. 소스 규칙을 추가하거나 제거하거나 이름을 바꾼 뒤에는 해당 결과를 소유한 생성기를 실행합니다. 충돌을 해결할 때는 정본 항목을 보존하고, 결정적으로 생성되는 결과를 수작업으로 다시 구성하지 말고 재생성합니다. 사람이 작성하는 문서는 모든 자동 생성 헤더 경계 아래에 둡니다. 예제에는 저장소가 선호하는 설정 구문을 사용합니다. 예제가 명시적으로 JSON인 경우가 아니라면 따옴표를 사용한 JSON 유사 예제로 바꾸지 않습니다. 공유 규칙 패턴이 관련 저장소나 패키지에도 존재한다면 같은 변경사항을 이식해야 하는지 검토합니다. 이를 자동화된 프로젝트 간 편집이 아니라 명시적인 호환성 결정으로 취급합니다. ## 개발 중에는 만드는 규칙의 테스트만, 마지막에 전체 테스트 돌리기 구현 전이나 구현과 함께 초점을 맞춘 테스트를 작성합니다. 테스트 도구가 진단, 수정, 제안을 함께 기록할 수 있다면 스냅샷 방식 테스트를 우선하고, 전용 파서 모드는 필요한 사례에만 사용합니다. 개발 중에는 대상 규칙 테스트만 실행합니다. 스냅샷은 의도적으로 업데이트하고, 완료 전에 임시 집중 테스트 표시를 제거합니다. 일반적인 편집 반복 과정에는 느린 통합 테스트를 포함하지 않습니다. 수정으로 인해 다른 위치의 위반이 드러나는 경우가 많으므로, 새 규칙을 구현한 뒤와 로직을 수정할 때마다 프로젝트 자체 적용 테스트를 실행합니다. 마지막에는 저장소의 실제 린터, 대상 테스트, 프로젝트 자체 적용 테스트를 실행한 다음 전체 테스트 모음을 한 번만 실행합니다. 다른 lint 도구가 문제없다고 보고한다는 이유만으로 저장소의 린터를 대체하지 않습니다. ## 주석과 까다로운 구문으로 수정 테스트하기 중복된 범위를 만들지 않으면서 동작, 불일치, 수정, 제안을 테스트합니다. 다음 분류에서 관련 사례를 포함합니다. - 타입이 있는 구문, 타입 단언, 제네릭, 옵셔널 체이닝 - JSX, 주석, 추가 괄호, 중첩 및 연쇄 표현식 - 계산된 속성, 템플릿, 스프레드, 구조 분해 - return 값이 사용되는 경우와 사용되지 않는 경우 - 규칙이 타입에 의존할 때 구문만 분석하는 경우와 전체 타입 정보를 사용하는 경우 규칙이 의도적으로 무시하는 사례도 테스트하여 경계를 문서화합니다. 주석이 있는 경우와 자동 세미콜론 삽입 위험이 있는 경우의 수정을 검증합니다. 사례에 다른 파서가 필요하다면 요구사항을 표현할 수 있는 가장 작은 테스트 범위에 설정합니다. ## 코드 동작이 바뀌지 않을 때만 자동 수정을 붙이고 주석 지키기 실행 시 동작을 바꾸지 않는 경우에만 자동 수정을 제공합니다. 동작이 달라질 수 있다면 제안을 우선합니다. 주석 보존은 필수입니다. 교체하거나 제거할 범위에 주석이 포함되어 있으면 수정을 중단하거나, 주석을 원래 위치에 유지하는 범위 인식 편집을 사용합니다. 수정을 내보내기 전에 교체 내용에 괄호가 필요한지, 앞쪽 대괄호나 소괄호 때문에 세미콜론이 필요한지, 인접한 토큰 사이에 공백이 필요한지 확인합니다. 여러 위치를 편집하는 작업에는 생성기 수정을 사용합니다. 옵셔널 체이닝의 동작을 보존하고, 값이 독립 표현식과 다른 방식으로 사용된다면 안전하지 않은 편집을 피합니다. 저장소에 간단한 로컬 보호책이 이미 있는 경우가 아니라면, 가려진 내장 요소, 접근자 또는 프록시의 부작용, 희소 배열의 빈칸을 보존하기 위해서만 수정을 지나치게 복잡하게 만들지 않습니다. 안전성을 확립할 수 없다면 수정 없이 문제만 보고합니다. ## 규칙 이름을 짓고 골격으로 만든 뒤 테스트부터 커밋까지 진행하기 구조와 의도를 설명하는 이름을 선택합니다. `no-`, `prefer-`, `require-`, `consistent-` 같은 접두사가 동작을 명확하게 한다면 사용합니다. 제안하는 대체 항목이 아니라 대상을 이름에 담고, 모호한 이름은 피합니다. 저장소의 골격 생성 기능을 사용하여 구현, 테스트, 문서, 자동 생성 인덱스 항목을 만듭니다. 그런 다음 다음 순서를 따릅니다. 1. 실패하는 테스트 또는 대표적인 테스트를 추가합니다. 2. 해당 테스트를 만족하는 최소한의 규칙 로직을 구현합니다. 3. 동작과 의도적으로 제외한 조건을 문서화합니다. 4. 대상 테스트와 정본 lint 명령을 실행합니다. 5. 프로젝트 자체 적용 테스트를 실행하고, 마지막에 전체 테스트 모음을 실행합니다. 6. 자동 생성 파일이 최신 상태이고 임시 작업 파일이 남아 있지 않은지 확인합니다. 규칙 이름과 옵션 이름 주변에 필요한 구두점을 포함하여 프로젝트의 커밋 메시지 규약을 사용합니다. 소스, 테스트, 문서, 자동 생성 영역, 검증 결과가 일치할 때만 전달이 완료된 것으로 봅니다.