Steep의 문서화 기능은 프로그래머가 Ruby 프로그램 컴포넌트(클래스, 모듈, 메서드 등)의 문서를 쉽게 읽을 수 있도록 돕습니다. 주요 기능은 다음과 같습니다.
Steep의 문서화 기능
- 호버(Hover): 소스 코드의 클래스 이름이나 메서드 호출 위에 커서를 올리면 관련 문서가 표시됩니다.
- 자동 완성(Completion): 메서드 이름을 입력할 때 가능한 메서드 목록과 함께 첫 번째 항목의 문서가 나타납니다.
- 시그니처 도움말(Signature Help): 메서드 인수를 작성할 때 가능한 파라미터 목록과 메서드 문서가 제공됩니다. 이러한 문서의 출처는 RBS 파일 내에 마크다운 형식으로 작성된 주석이며, Language Server Protocol(LSP)을 통해 편집기에 전달됩니다.
내부 구현 아키텍처
Steep의 문서화 기능은 내부 API 위에 구축됩니다.
1. AST와 주석: RBS 파일은 RBS::AST
객체로 파싱되며, 각 선언(클래스, 메서드, 속성)은 RBS::Comment
객체를 포함하는 comment
속성을 가집니다. RBS::Comment
는 주석의 문자열 내용을 저장합니다.
2. 파서(rbs_parse
): get_comment
함수를 통해 def
토큰과 같은 현재 토큰의 라인 번호를 기준으로 주석을 찾아 RBS::Comment
객체를 생성하고 AST 객체에 연결합니다.
3. 환경(Environment): RBS gem은 파싱된 RBS 파일을 RBS::Environment
객체에 저장하며, 이는 RBS::Definition
객체로 변환되어 메서드, 변수, 상속 관계 등을 관리합니다. 각 Method
객체는 주석 객체 배열을 가집니다.
4. 타입 체커: Steep의 타입 체커는 Ruby 프로그램의 각 노드에 타입을 할당하고, 상수나 메서드 호출과 관련된 타입을 기반으로 Environment
에서 해당 문서(주석)를 찾아냅니다. LSP 서버는 편집기의 요청에 따라 이 정보를 JSON 형식의 마크다운 문서로 변환하여 반환합니다.
현재 시스템의 문제점
현재 시스템은 문서화 시스템과 타입 체커가 긴밀히 결합되어 있습니다. RBS 파일에서 주석만 변경되어도 내부 오버로드 데이터 구조가 업데이트될 수 있어, 불필요하게 전체 타입 검사를 다시 실행해야 하는 문제가 발생합니다. 이는 타입 검사 결과에는 영향을 주지 않음에도 불구하고 성능 저하를 야기합니다.
해결책: 문서화 인덱스(Index) API 도입
이 문제를 해결하기 위해 문서화 시스템과 타입 체커 사이에 명확한 경계를 설정하는 ‘인덱스’ API 도입이 제안됩니다. * 동작 방식: Steep이 RBS 파일을 로드할 때, 인덱스는 문서화를 등록합니다. 주석만 변경되면 인덱스만 업데이트되고 타입 체커는 실행되지 않습니다. LSP 서버는 식별자를 통해 인덱스에서 문서를 조회합니다. * 장점: * 문서화 시스템과 타입 체커의 결합도 감소. * 서버 재시작 후 인덱스 재활용 가능 (식별자가 직렬화 가능하다면). * 인덱스 분산 가능성.
메서드 오버로드 식별자 설계
인덱스 API의 핵심 과제는 메서드 오버로드를 안정적으로 식별하는 것입니다.
* 기존 방식의 한계: String#hash
와 같은 표기법은 오버로드가 여러 개일 때 특정 오버로드를 지칭하기 어렵습니다. 파일명/라인 번호는 주석 수정 시 변경될 수 있고, 오버로드 인덱스는 파일 로딩 순서에 따라 불안정하며 가독성이 떨어집니다.
* 제안된 해결책: 정규화된 메서드 타입을 식별자로 사용합니다.
* 메서드 이름 뒤에 전체 메서드 시그니처(타입)를 붙여 어떤 오버로드인지 명확히 합니다.
* 메서드 타입이 변경되면 식별자가 무효화되지만, 이는 타입 검사가 필요한 상황이므로 문제가 없습니다.
* JVM의 메서드 디스크립터와 유사한 접근 방식입니다.
* 정규화: 파라미터 이름은 제외하고, 키워드 인수는 정렬하여 일관성을 유지합니다.
* 이렇게 정규화된 메서드 타입은 안정적이고 구현에 독립적이며, 파일 저장, 로드, 비교가 용이한 문자열 형태의 식별자가 됩니다.
향후 확장 가능성
이 인덱스는 “Go to Definition”이나 “Go to Reference”와 같은 기능 구현을 위해 정의 및 참조 위치를 저장하는 데도 활용될 수 있습니다. 또한, RDoc이나 YARD와 같은 다른 문서화 도구와의 연동 가능성도 논의될 수 있습니다.