mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-09-03 07:09:23 +00:00
improve class casts including filtering
This commit is contained in:
@@ -9,4 +9,5 @@ repositories {
|
||||
dependencies {
|
||||
implementation libs.kotlin.poet
|
||||
implementation libs.ksp
|
||||
implementation project(":tgbotapi.core")
|
||||
}
|
||||
|
@@ -1,15 +1,21 @@
|
||||
package dev.inmo.tgbotapi.ksp.processor
|
||||
|
||||
import com.google.devtools.ksp.KspExperimental
|
||||
import com.google.devtools.ksp.getAllSuperTypes
|
||||
import com.google.devtools.ksp.getAnnotationsByType
|
||||
import com.google.devtools.ksp.isAnnotationPresent
|
||||
import com.google.devtools.ksp.processing.*
|
||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||
import com.squareup.kotlinpoet.AnnotationSpec
|
||||
import com.squareup.kotlinpoet.ClassName
|
||||
import com.squareup.kotlinpoet.FileSpec
|
||||
import com.squareup.kotlinpoet.asClassName
|
||||
import com.squareup.kotlinpoet.ksp.toClassName
|
||||
import com.squareup.kotlinpoet.ksp.writeTo
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import dev.inmo.tgbotapi.utils.internal.ClassCastsExcluded
|
||||
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
|
||||
import java.io.File
|
||||
|
||||
class TelegramBotAPISymbolProcessor(
|
||||
@@ -18,35 +24,33 @@ class TelegramBotAPISymbolProcessor(
|
||||
private val outputFile: String = "Output",
|
||||
private val outputFolder: String? = null
|
||||
) : SymbolProcessor {
|
||||
private val classCastsIncludedClassName = ClassName("dev.inmo.tgbotapi.utils.internal", "ClassCastsIncluded")
|
||||
private val classCastsIncludedClassName = ClassCastsIncluded::class.asClassName()
|
||||
@OptIn(KspExperimental::class, RiskFeature::class)
|
||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||
val classes = resolver.getSymbolsWithAnnotation(classCastsIncludedClassName.canonicalName).filterIsInstance<KSClassDeclaration>()
|
||||
val classesRegexes: Map<KSClassDeclaration, Pair<Regex, Regex?>> = classes.mapNotNull {
|
||||
it to (it.annotations.firstNotNullOfOrNull {
|
||||
runCatching {
|
||||
if (it.annotationType.resolve().toClassName() == classCastsIncludedClassName) {
|
||||
val regex = it.arguments.first().value as? String ?: return@runCatching null
|
||||
val negativeRegex = (it.arguments.first().value as? String) ?.takeIf { it.isNotEmpty() }
|
||||
Regex(regex) to (negativeRegex ?.let(::Regex))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.getOrNull()
|
||||
val classesRegexes: Map<KSClassDeclaration, Pair<Regex?, Regex?>> = classes.mapNotNull {
|
||||
it to (it.getAnnotationsByType(ClassCastsIncluded::class).firstNotNullOfOrNull {
|
||||
it.typesRegex.takeIf { it.isNotEmpty() } ?.let(::Regex) to it.excludeRegex.takeIf { it.isNotEmpty() } ?.let(::Regex)
|
||||
} ?: return@mapNotNull null)
|
||||
}.toMap()
|
||||
val classesSubtypes = mutableMapOf<KSClassDeclaration, MutableSet<KSClassDeclaration>>()
|
||||
|
||||
resolver.getAllFiles().forEach {
|
||||
it.declarations.forEach { potentialSubtype ->
|
||||
if (potentialSubtype is KSClassDeclaration) {
|
||||
if (
|
||||
potentialSubtype is KSClassDeclaration
|
||||
&& potentialSubtype.isAnnotationPresent(ClassCastsExcluded::class).not()
|
||||
) {
|
||||
val allSupertypes = potentialSubtype.getAllSuperTypes().map { it.declaration }
|
||||
|
||||
for (currentClass in classes) {
|
||||
val regexes = classesRegexes[currentClass]
|
||||
val simpleName = potentialSubtype.simpleName.getShortName()
|
||||
when {
|
||||
currentClass in allSupertypes
|
||||
&& regexes ?.first ?.matches(potentialSubtype.simpleName.toString()) != false
|
||||
&& regexes ?.second ?.matches(potentialSubtype.simpleName.toString()) != true-> {
|
||||
currentClass !in allSupertypes
|
||||
|| regexes ?.first ?.matches(simpleName) == false
|
||||
|| regexes ?.second ?.matches(simpleName) == true -> continue
|
||||
else -> {
|
||||
classesSubtypes.getOrPut(currentClass) { mutableSetOf() }.add(potentialSubtype)
|
||||
}
|
||||
}
|
||||
@@ -55,7 +59,16 @@ class TelegramBotAPISymbolProcessor(
|
||||
}
|
||||
}
|
||||
fun fillWithSealeds(source: KSClassDeclaration, current: KSClassDeclaration = source) {
|
||||
val regexes = classesRegexes[source]
|
||||
current.getSealedSubclasses().forEach {
|
||||
val simpleName = it.simpleName.getShortName()
|
||||
if (
|
||||
regexes ?.first ?.matches(simpleName) == false
|
||||
|| regexes ?.second ?.matches(simpleName) == true
|
||||
|| it.isAnnotationPresent(ClassCastsExcluded::class)
|
||||
) {
|
||||
return@forEach
|
||||
}
|
||||
classesSubtypes.getOrPut(source) { mutableSetOf() }.add(it)
|
||||
fillWithSealeds(source, it)
|
||||
}
|
||||
|
Reference in New Issue
Block a user