Многоэтапная обработка
KSP поддерживает многоэтапную обработку, то есть обработку файлов в несколько этапов. Результаты каждого этапа обработки используются как дополнительные входные данные на каждом следующем этапе.
Чтобы использовать многоэтапную обработку, возвращайте отложенные символы из SymbolProcessor.process() в виде List<KSAnnotated>. KSP обрабатывает эти символы на следующем этапе.
Чтобы отложить недопустимые символы, отфильтруйте их с помощью 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
}
Многоэтапная обработка завершается, когда за весь этап не создаётся ни одного нового файла. Если остаются необработанные отложенные символы, KSP регистрирует ошибку для каждого процессора, у которого остались отложенные символы.
Откладывание символов до следующего этапа
Процессоры могут отложить символ до следующего этапа, если им требуется дополнительная информация от других процессоров. Процессор может откладывать символ на нескольких этапах, пока не станет доступна необходимая информация. Когда информация становится доступна, процессор может обработать символ.
Откладывайте символы только в следующих случаях:
Для обработки символа необходима дополнительная информация.
-
Символ получен из исходного кода.
Например, процессору, который генерирует builder для класса с аннотацией, может потребоваться, чтобы типы всех параметров конструктора разрешались в конкретные типы. На первом этапе тип одного из параметров может не разрешаться. На следующем этапе он может разрешиться благодаря файлам, сгенерированным за это время. Тогда процессор сможет обработать класс.
Проверка символов
Проверка — удобный способ определить, следует ли отложить символ до следующего этапа. Процессору следует определить, какая информация требуется для корректной обработки символа.
Поведение проверки по умолчанию может не подойти для всех вариантов использования. Чтобы настроить проверку, используйте KSValidateVisitor и передайте лямбда-выражение predicate, которое выбирает проверяемые символы.
При реализации пользовательской проверки используйте KSType.isError, чтобы определить, допустим ли тип. Если isError имеет значение true, KSP не удалось разрешить тип. Используйте эту информацию, чтобы решить, следует ли отложить обработку до следующего этапа.
Доступ к файлам и символам
Доступ к новым и существующим файлам осуществляется через Resolver.
KSP предоставляет два API для доступа к файлам:
Resolver.getAllFiles()возвращает список как ранее существовавших, так и вновь созданных файлов.Resolver.getNewFiles()возвращает только файлы, созданные на предыдущем этапе.
Используйте Resolver.getSymbolsWithAnnotation() в качестве основного способа получения нужных символов.
На каждом этапе Resolver.getSymbolsWithAnnotation() возвращает только символы из вновь созданных файлов и символы, отложенные на предыдущем этапе. Это позволяет избежать ненужной повторной обработки.
Создание экземпляра процессора
KSP создаёт экземпляр процессора только один раз. Вы можете сохранять информацию в экземпляре процессора и повторно использовать её на нескольких этапах.
Однако повторно использовать между этапами можно не все символы KSP. Результаты разрешения символов могут изменяться при создании процессорами новых файлов, что может повлиять на достоверность ранее разрешённых символов.
Обработка ошибок и исключений
Ошибки
Процессор сообщает об ошибке, вызывая KSPLogger.error().
Когда процессор сообщает об ошибке, KSP вызывает SymbolProcessor.onError() вместо SymbolProcessor.finish(). Обработка останавливается после завершения текущего этапа.
На этом этапе остальные процессоры продолжают работу в обычном режиме. KSP обрабатывает ошибки только после завершения работы всех процессоров на текущем этапе.
Исключения
KSP различает исключения, выброшенные самим KSP, и исключения, выброшенные процессорами. Оба типа немедленно прекращают обработку и регистрируются как ошибки через KSPLogger.
В конце этапа, на котором произошла ошибка или исключение, KSP вызывает SymbolProcessor.onError() у всех процессоров. SymbolProcessor предоставляет реализацию onError() по умолчанию, которая ничего не делает. Переопределите этот метод, чтобы реализовать собственную логику обработки ошибок.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/ksp-multi-round.html