다중 라운드 처리
KSP는 다중 라운드 처리 또는 여러 라운드에 걸쳐 파일을 처리하는 것을 지원합니다. 이는 후속 라운드에서 이전 라운드의 출력을 추가 입력으로 사용한다는 의미입니다.
프로세서 변경 사항
다중 라운드 처리를 사용하려면 SymbolProcessor.process()
함수가 유효하지 않은 심볼에 대해 지연된 심볼 목록(List<KSAnnotated>
)을 반환해야 합니다. KSAnnotated.validate()
를 사용하여 유효하지 않은 심볼을 필터링하여 다음 라운드로 지연시킵니다.
다음 샘플 코드는 유효성 검사를 사용하여 유효하지 않은 심볼을 지연시키는 방법을 보여줍니다.
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation("com.example.annotation.Builder")
val result = symbols.filter { !it.validate() }
symbols
.filter { it is KSClassDeclaration && it.validate() }
.map { it.accept(BuilderVisitor(), Unit) }
return result
}
다중 라운드 동작
심볼을 다음 라운드로 연기
프로세서는 특정 심볼의 처리를 다음 라운드로 연기할 수 있습니다. 심볼이 연기되면 프로세서는 다른 프로세서가 추가 정보를 제공하기를 기다립니다. 필요한 만큼 여러 라운드 동안 심볼을 계속 연기할 수 있습니다. 다른 프로세서가 필요한 정보를 제공하면 프로세서는 연기된 심볼을 처리할 수 있습니다. 프로세서는 필요한 정보가 부족한 유효하지 않은 심볼만 연기해야 합니다. 따라서 프로세서는 classpath에서 심볼을 연기하면 안 됩니다. KSP는 소스 코드에 없는 연기된 심볼도 필터링합니다.
예를 들어, 어노테이션이 달린 클래스에 대한 빌더를 생성하는 프로세서는 생성자의 모든 매개변수 유형이 유효해야 합니다 (구체적인 유형으로 확인됨). 첫 번째 라운드에서는 매개변수 유형 중 하나를 확인할 수 없습니다. 그런 다음 두 번째 라운드에서는 첫 번째 라운드에서 생성된 파일 때문에 확인할 수 있게 됩니다.
심볼 유효성 검사
심볼을 연기해야 하는지 여부를 결정하는 편리한 방법은 유효성 검사를 통하는 것입니다. 프로세서는 심볼을 올바르게 처리하는 데 필요한 정보를 알아야 합니다. 유효성 검사에는 일반적으로 확인이 필요하며 비용이 많이 들 수 있으므로 필요한 것만 확인하는 것이 좋습니다. 이전 예제를 계속해서 살펴보면 빌더 프로세서에 대한 이상적인 유효성 검사는 어노테이션이 달린 심볼의 생성자의 확인된 모든 매개변수 유형에 isError == false
가 포함되어 있는지 여부만 확인합니다.
KSP는 기본 유효성 검사 유틸리티를 제공합니다. 자세한 내용은 고급 섹션을 참조하십시오.
종료 조건
다중 라운드 처리는 전체 라운드 처리에서 새 파일이 생성되지 않으면 종료됩니다. 종료 조건이 충족될 때 처리되지 않은 연기된 심볼이 여전히 존재하면 KSP는 처리되지 않은 연기된 심볼이 있는 각 프로세서에 대한 오류 메시지를 기록합니다.
각 라운드에서 액세스할 수 있는 파일
새로 생성된 파일과 기존 파일 모두 Resolver
를 통해 액세스할 수 있습니다. KSP는 파일에 액세스하기 위한 두 가지 API를 제공합니다: Resolver.getAllFiles()
및 Resolver.getNewFiles()
. getAllFiles()
는 기존 파일과 새로 생성된 파일의 결합된 목록을 반환하는 반면, getNewFiles()
는 새로 생성된 파일만 반환합니다.
getSymbolsAnnotatedWith() 변경 사항
심볼의 불필요한 재처리를 방지하기 위해 getSymbolsAnnotatedWith()
는 새로 생성된 파일에서 발견된 심볼과 마지막 라운드의 연기된 심볼에서 가져온 심볼만 반환합니다.
프로세서 인스턴스화
프로세서 인스턴스는 한 번만 생성됩니다. 즉, 나중에 라운드에 사용할 프로세서 객체에 정보를 저장할 수 있습니다.
라운드 간 일관된 정보
모든 KSP 심볼은 여러 라운드에서 재사용할 수 없습니다. 확인 결과는 이전 라운드에서 생성된 내용을 기반으로 잠재적으로 변경될 수 있기 때문입니다. 그러나 KSP는 기존 코드 수정를 허용하지 않으므로 심볼 이름에 대한 문자열 값과 같은 일부 정보는 여전히 재사용할 수 있습니다. 요약하면 프로세서는 이전 라운드의 정보를 저장할 수 있지만 이 정보가 향후 라운드에서 유효하지 않을 수 있음을 명심해야 합니다.
오류 및 예외 처리
오류(KSPLogger.error()
를 호출하는 프로세서에 의해 정의됨) 또는 예외가 발생하면 현재 라운드가 완료된 후 처리가 중지됩니다. 모든 프로세서는 onError()
메서드를 호출하고 finish()
메서드를 호출하지 않습니다.
오류가 발생했더라도 다른 프로세서는 해당 라운드에 대해 정상적으로 처리를 계속합니다. 즉, 오류 처리는 해당 라운드의 처리가 완료된 후에 발생합니다.
예외가 발생하면 KSP는 KSP의 예외와 프로세서의 예외를 구별하려고 시도합니다. 예외가 발생하면 즉시 처리가 종료되고 KSPLogger에 오류로 기록됩니다. KSP의 예외는 추가 조사를 위해 KSP 개발자에게 보고해야 합니다. 예외 또는 오류가 발생한 라운드가 끝나면 모든 프로세서는 onError() 함수를 호출하여 자체 오류 처리를 수행합니다.
KSP는 SymbolProcessor
인터페이스의 일부로 onError()
에 대한 기본 no-op 구현을 제공합니다. 이 메서드를 재정의하여 사용자 지정 오류 처리 로직을 제공할 수 있습니다.
고급
유효성 검사에 대한 기본 동작
KSP에서 제공하는 기본 유효성 검사 로직은 유효성 검사 중인 심볼의 둘러싸는 범위 내에서 직접 도달할 수 있는 모든 심볼의 유효성을 검사합니다. 기본 유효성 검사는 묶인 범위의 참조를 구체적인 유형으로 확인할 수 있는지 여부를 확인하지만 참조된 유형으로 재귀적으로 이동하여 유효성 검사를 수행하지는 않습니다.
사용자 지정 유효성 검사 로직 작성
기본 유효성 검사 동작이 모든 경우에 적합하지 않을 수 있습니다. KSValidateVisitor
를 참조하고 사용자 지정 predicate
람다를 제공하여 자체 유효성 검사 로직을 작성할 수 있습니다. 그런 다음 KSValidateVisitor
는 확인해야 하는 심볼을 필터링하는 데 사용됩니다.