-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 支持
KookQuote
的获取和MessageReference
的解析
- Loading branch information
1 parent
ca56600
commit 887ea1d
Showing
16 changed files
with
549 additions
and
141 deletions.
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
internal-processors/message-element-processor/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright (c) 2024. ForteScarlet. | ||
* | ||
* This file is part of simbot-component-kook. | ||
* | ||
* simbot-component-kook is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* simbot-component-kook is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with simbot-component-kook, | ||
* If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget | ||
|
||
plugins { | ||
kotlin("jvm") | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
kotlin { | ||
jvmToolchain(11) | ||
compilerOptions { | ||
javaParameters = true | ||
jvmTarget.set(JvmTarget.JVM_11) | ||
} | ||
} | ||
|
||
configJavaCompileWithModule() | ||
|
||
dependencies { | ||
api(libs.ksp) | ||
api(libs.kotlinPoet.ksp) | ||
testImplementation(kotlin("test-junit5")) | ||
} | ||
|
||
tasks.getByName<Test>("test") { | ||
useJUnitPlatform() | ||
} | ||
|
148 changes: 148 additions & 0 deletions
148
...-processor/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* Copyright (c) 2024. ForteScarlet. | ||
* | ||
* This file is part of simbot-component-kook. | ||
* | ||
* simbot-component-kook is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* simbot-component-kook is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with simbot-component-kook, | ||
* If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package kook.internal.processors.msgelement | ||
|
||
import com.google.devtools.ksp.getClassDeclarationByName | ||
import com.google.devtools.ksp.isAbstract | ||
import com.google.devtools.ksp.processing.Resolver | ||
import com.google.devtools.ksp.processing.SymbolProcessor | ||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment | ||
import com.google.devtools.ksp.symbol.KSAnnotated | ||
import com.google.devtools.ksp.symbol.KSClassDeclaration | ||
import com.google.devtools.ksp.symbol.Modifier | ||
import com.squareup.kotlinpoet.* | ||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy | ||
import com.squareup.kotlinpoet.ksp.toClassName | ||
import com.squareup.kotlinpoet.ksp.writeTo | ||
import java.time.Instant | ||
import java.time.ZoneOffset | ||
|
||
|
||
private const val BASE_ELEMENT_CLASS_PACKAGE = "love.forte.simbot.component.kook.message" | ||
private const val BASE_ELEMENT_CLASS_SIMPLE_NAME = "KookMessageElement" | ||
|
||
private const val BASE_ELEMENT_CLASS_NAME = | ||
"$BASE_ELEMENT_CLASS_PACKAGE.$BASE_ELEMENT_CLASS_SIMPLE_NAME" | ||
|
||
private val BaseElementClassName = | ||
ClassName(BASE_ELEMENT_CLASS_PACKAGE, BASE_ELEMENT_CLASS_SIMPLE_NAME) | ||
|
||
private const val KTX_SERIALIZABLE_ANNOTATION_PACKAGE = "kotlinx.serialization" | ||
private const val KTX_SERIALIZABLE_ANNOTATION_SIMPLE_NAME = "Serializable" | ||
private const val KTX_SERIALIZABLE_ANNOTATION_NAME = | ||
"$KTX_SERIALIZABLE_ANNOTATION_PACKAGE.$KTX_SERIALIZABLE_ANNOTATION_SIMPLE_NAME" | ||
|
||
private val PolymorphicModuleBuilderClassName = | ||
ClassName("kotlinx.serialization.modules", "PolymorphicModuleBuilder") | ||
|
||
private const val OUTPUT_PACKAGE = "love.forte.simbot.component.kook.message" | ||
private const val OUTPUT_FILE = "IncludeKookMessageElements.generated" | ||
private const val OUTPUT_FUN_NAME = "includeKookMessageElements" | ||
|
||
/** | ||
* | ||
* @author ForteScarlet | ||
*/ | ||
class MessageElementProcessor(environment: SymbolProcessorEnvironment) : SymbolProcessor { | ||
private val codeGenerator = environment.codeGenerator | ||
private val elementDeclarations = mutableListOf<KSClassDeclaration>() | ||
|
||
override fun finish() { | ||
val newFun = resolve(elementDeclarations) | ||
|
||
val fileSpec = FileSpec.Companion.builder( | ||
OUTPUT_PACKAGE, OUTPUT_FILE | ||
) | ||
.addFunction(newFun) | ||
.addFileComment("\nAuto-Generated at ${Instant.now().atOffset(ZoneOffset.ofHours(8))}\n") | ||
.build() | ||
|
||
fileSpec.writeTo( | ||
codeGenerator = codeGenerator, | ||
aggregating = true, | ||
originatingKSFiles = buildList { | ||
for (impl in elementDeclarations) { | ||
impl.containingFile?.also { add(it) } | ||
} | ||
} | ||
) | ||
} | ||
|
||
override fun process(resolver: Resolver): List<KSAnnotated> { | ||
val baseClass = resolver.getClassDeclarationByName( | ||
BASE_ELEMENT_CLASS_NAME | ||
) ?: error("Base class $BASE_ELEMENT_CLASS_NAME not found") | ||
|
||
val baseClassStarType = baseClass.asStarProjectedType() | ||
|
||
resolver | ||
.getSymbolsWithAnnotation(KTX_SERIALIZABLE_ANNOTATION_NAME) | ||
.filterIsInstance<KSClassDeclaration>() | ||
.filter { declaration -> | ||
// 是 base class 的子类 | ||
baseClassStarType.isAssignableFrom(declaration.asStarProjectedType()) | ||
} | ||
.filter { declaration -> | ||
// 不是抽象的、不是sealed的可序列化类 | ||
!declaration.isAbstract() && !declaration.modifiers.contains(Modifier.SEALED) | ||
} | ||
.toCollection(elementDeclarations) | ||
|
||
return emptyList() | ||
} | ||
|
||
/** | ||
* 生成函数: | ||
* | ||
* ```kotlin | ||
* internal fun PolymorphicModuleBuilder<KookMessageElement>.includeKookMessageElements() { | ||
* subclass(KookAsset::class, KookAsset.serializer()) | ||
* // ... | ||
* } | ||
* ``` | ||
*/ | ||
private fun resolve(declarations: List<KSClassDeclaration>): FunSpec { | ||
val receiverType = PolymorphicModuleBuilderClassName.parameterizedBy(BaseElementClassName) | ||
// val optAnnotation = | ||
val optAnnotation = AnnotationSpec.builder(ClassName("kotlin", "OptIn")) | ||
.addMember( | ||
"%T::class, %T::class", | ||
ClassName("love.forte.simbot.annotations", "ExperimentalSimbotAPI"), | ||
ClassName("love.forte.simbot.kook", "ExperimentalKookApi") | ||
) | ||
.build() | ||
|
||
val internalAPIAnnotation = ClassName("love.forte.simbot.kook", "InternalKookApi") | ||
|
||
return FunSpec.builder(OUTPUT_FUN_NAME).apply { | ||
modifiers.add(KModifier.INTERNAL) | ||
receiver(receiverType) | ||
addAnnotation(optAnnotation) | ||
addAnnotation(internalAPIAnnotation) | ||
|
||
for (declaration in declarations) { | ||
val className = declaration.toClassName() | ||
addCode("subclass(%T::class, %T.serializer())\n", className, className) | ||
} | ||
}.build() | ||
} | ||
} | ||
|
35 changes: 35 additions & 0 deletions
35
...or/src/main/kotlin/kook/internal/processors/msgelement/MessageElementProcessorProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright (c) 2024. ForteScarlet. | ||
* | ||
* This file is part of simbot-component-kook. | ||
* | ||
* simbot-component-kook is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* simbot-component-kook is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with simbot-component-kook, | ||
* If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package kook.internal.processors.msgelement | ||
|
||
import com.google.devtools.ksp.processing.SymbolProcessor | ||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment | ||
import com.google.devtools.ksp.processing.SymbolProcessorProvider | ||
|
||
/** | ||
* | ||
* @author ForteScarlet | ||
*/ | ||
class MessageElementProcessorProvider : SymbolProcessorProvider { | ||
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor = | ||
MessageElementProcessor(environment) | ||
} | ||
|
1 change: 1 addition & 0 deletions
1
...in/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
kook.internal.processors.msgelement.MessageElementProcessorProvider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.