Обработка в несколько раундов
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 предоставляет реализацию по умолчанию по умолчанию для onError() в качестве части интерфейса SymbolProcessor. Вы можете переопределить этот метод, чтобы реализовать собственную логику обработки ошибок.
Дополнительные сведения
Поведение по умолчанию для проверки валидности
Логика проверки валидности по умолчанию, предоставляемая KSP, проверяет все непосредственно доступные символы внутри охватывающей области символа, который проверяется. Проверка валидности по умолчанию проверяет, разрешены ли ссылки в охватывающей области до конкретного типа, но не углубляется рекурсивно в ссылки для проверки типов.
Написание собственной логики проверки валидности
Поведение проверки валидности по умолчанию может не подойти во всех случаях. Вы можете обратиться к KSValidateVisitor и написать собственную логику проверки валидности, предоставив пользовательскую лямбду predicate, которая затем используется KSValidateVisitor для фильтрации символов, которые необходимо проверить.
© 2010–2023 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