Обработка по нескольким раундам
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 предоставляет реализацию по умолчанию no-op для 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