Skip to content

Commit e5c39ea

Browse files
authored
Merge pull request #275 from simple-robot/dev/main
Release: v4.1.4
2 parents b4a723c + a0bbfa0 commit e5c39ea

File tree

13 files changed

+537
-87
lines changed

13 files changed

+537
-87
lines changed

buildSrc/src/main/kotlin/P.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ object P {
5656
override val homepage: String get() = HOMEPAGE
5757

5858

59-
const val VERSION = "4.1.3"
60-
const val NEXT_VERSION = "4.1.4"
59+
const val VERSION = "4.1.4"
60+
const val NEXT_VERSION = "4.1.5"
6161

6262
override val snapshotVersion = "$NEXT_VERSION-SNAPSHOT"
6363
override val version = if (isSnapshot()) snapshotVersion else VERSION

internal-processors/intents-processor/src/main/kotlin/qg/internal/processors/intents/EventIntentsAggregationProcessor.kt

Lines changed: 110 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* This file is part of simbot-component-qq-guild.
55
*
@@ -28,6 +28,7 @@ import com.google.devtools.ksp.symbol.KSPropertyDeclaration
2828
import com.google.devtools.ksp.symbol.Modifier
2929
import com.squareup.kotlinpoet.*
3030
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
31+
import com.squareup.kotlinpoet.jvm.jvmInline
3132
import com.squareup.kotlinpoet.jvm.jvmName
3233
import com.squareup.kotlinpoet.jvm.jvmStatic
3334
import com.squareup.kotlinpoet.ksp.toClassName
@@ -44,6 +45,10 @@ private const val EVENT_INTENTS_PACKAGE = "love.forte.simbot.qguild.event"
4445
private const val EVENT_INTENTS_CLASS_NAME = "EventIntents"
4546
private val EventIntentsClassName = ClassName(EVENT_INTENTS_PACKAGE, EVENT_INTENTS_CLASS_NAME)
4647

48+
private const val INTENTS_APPENDER_PACKAGE = "love.forte.simbot.qguild.event"
49+
private const val INTENTS_APPENDER_CLASS_NAME = "IntentsAppender"
50+
private val IntentsAppenderClassName = ClassName(INTENTS_APPENDER_PACKAGE, INTENTS_APPENDER_CLASS_NAME)
51+
4752
private const val INTENTS_CONST_NAME = "INTENTS"
4853

4954
private const val INTENTS_PACKAGE = "love.forte.simbot.qguild.event"
@@ -64,6 +69,15 @@ private const val EVENT_NAME_BASED_MARKER_PKG = "love.forte.simbot.qguild.intern
6469
internal class EventIntentsAggregationProcessor(
6570
val environment: SymbolProcessorEnvironment
6671
) : SymbolProcessor {
72+
data class NamesToType(
73+
val names: Set<String>,
74+
val declaration: KSClassDeclaration,
75+
val firstUpper: String,
76+
val firstLower: String,
77+
val snackUpper: String,
78+
val snackLower: String,
79+
)
80+
6781
private val processed = AtomicBoolean(false)
6882

6983
override fun process(resolver: Resolver): List<KSAnnotated> {
@@ -78,32 +92,69 @@ internal class EventIntentsAggregationProcessor(
7892
.getSealedSubclasses()
7993
.toList()
8094

81-
// val allSubObjects = resolver.getAllFiles()
82-
// .filterIsInstance<KSClassDeclaration>()
83-
// .flatMap { dec ->
84-
// sequence {
85-
// yield(dec)
86-
// yieldAll(dec.getSealedSubclasses())
87-
// }
88-
// }
89-
// .filter { declaration ->
90-
// declaration.classKind == ClassKind.OBJECT &&
91-
// declaration.asStarProjectedType()
92-
// .isAssignableFrom(eventIntentsDeclaration.asStarProjectedType())
93-
// }
94-
// .toList()
95-
9695
environment.logger.info("Found sub object: $allSubObjects")
9796

9897
val aggregationBuilder = TypeSpec.objectBuilder(AGGREGATION_OBJ_NAME)
9998

10099
generateAll(aggregationBuilder, allSubObjects)
101-
generateGetByName(aggregationBuilder, allSubObjects)
100+
101+
// name -> type
102+
val nameToTypes = allSubObjects.map { declaration ->
103+
val nameBasedAnnotation = declaration.annotations
104+
.firstOrNull {
105+
(it.annotationType.resolve().declaration as? KSClassDeclaration)?.let { annoDecl ->
106+
annoDecl.simpleName.asString() == EVENT_NAME_BASED_MARKER_NAME
107+
&& annoDecl.packageName.asString() == EVENT_NAME_BASED_MARKER_PKG
108+
} == true
109+
}
110+
111+
fun baseName(): String = declaration.simpleName.asString()
112+
113+
fun findFromAnnotation(name: String): String? =
114+
nameBasedAnnotation?.arguments?.firstOrNull {
115+
it.name?.asString() == name
116+
}?.value as? String?
117+
118+
val firstUpper = findFromAnnotation("firstUpper")
119+
?.takeUnless { it.isBlank() }
120+
?: baseName()
121+
val firstLower = findFromAnnotation("firstLower")
122+
?.takeUnless { it.isBlank() }
123+
?: baseName().replaceFirstChar(Char::lowercaseChar)
124+
val snackUpper = findFromAnnotation("snackUpper")
125+
?.takeUnless { it.isBlank() }
126+
?: baseName().toSnack(true)
127+
val snackLower = findFromAnnotation("snackLower")
128+
?.takeUnless { it.isBlank() }
129+
?: baseName().toSnack(false)
130+
131+
132+
val set = setOf(
133+
firstUpper,
134+
firstLower,
135+
snackUpper,
136+
snackLower,
137+
)
138+
139+
NamesToType(
140+
set,
141+
declaration,
142+
firstUpper,
143+
firstLower,
144+
snackUpper,
145+
snackLower
146+
)
147+
}
148+
149+
generateGetByName(aggregationBuilder, nameToTypes)
150+
151+
val intentsAppenderOpTypeSpec = generateIntentsAppenderOp(nameToTypes)
102152

103153
val fileBuilder = FileSpec.builder(OUTPUT_PACKAGE, AGGREGATION_FILE_NAME)
104154
fileBuilder.addType(aggregationBuilder.build())
155+
fileBuilder.addType(intentsAppenderOpTypeSpec)
105156
fileBuilder.addFileComment(
106-
"本文件内容为自动生成,生成于 %L",
157+
"\n本文件内容为自动生成,生成于 %L\n",
107158
OffsetDateTime.now(ZoneOffset.ofHours(8)).toString()
108159
)
109160

@@ -196,53 +247,12 @@ internal class EventIntentsAggregationProcessor(
196247
builder.addFunction(allIntentsFunc.build())
197248
}
198249

250+
199251
/**
200252
* 生成根据名称获取结果的 `getByName(name: String)`,
201253
* 名称支持驼峰、全大写和全小写。
202254
*/
203-
private fun generateGetByName(builder: TypeSpec.Builder, list: List<KSClassDeclaration>) {
204-
data class NamesToType(val names: Set<String>, val declaration: KSClassDeclaration)
205-
206-
val nameToTypes = list.map { declaration ->
207-
val nameBasedAnnotation = declaration.annotations
208-
.firstOrNull {
209-
(it.annotationType.resolve().declaration as? KSClassDeclaration)?.let { annoDecl ->
210-
annoDecl.simpleName.asString() == EVENT_NAME_BASED_MARKER_NAME
211-
&& annoDecl.packageName.asString() == EVENT_NAME_BASED_MARKER_PKG
212-
} ?: false
213-
}
214-
215-
fun baseName(): String = declaration.simpleName.asString()
216-
217-
fun findFromAnnotation(name: String): String? =
218-
nameBasedAnnotation?.arguments?.firstOrNull {
219-
it.name?.asString() == name
220-
}?.value as? String?
221-
222-
val firstUpper = findFromAnnotation("firstUpper")
223-
?.takeUnless { it.isBlank() }
224-
?: baseName()
225-
val firstLower = findFromAnnotation("firstLower")
226-
?.takeUnless { it.isBlank() }
227-
?: baseName().replaceFirstChar(Char::lowercaseChar)
228-
val snackUpper = findFromAnnotation("snackUpper")
229-
?.takeUnless { it.isBlank() }
230-
?: baseName().toSnack(true)
231-
val snackLower = findFromAnnotation("snackLower")
232-
?.takeUnless { it.isBlank() }
233-
?: baseName().toSnack(false)
234-
235-
236-
val set = setOf(
237-
firstUpper,
238-
firstLower,
239-
snackUpper,
240-
snackLower,
241-
)
242-
243-
NamesToType(set, declaration)
244-
}
245-
255+
private fun generateGetByName(builder: TypeSpec.Builder, nameToTypes: List<NamesToType>) {
246256
val doc = CodeBlock.builder().apply {
247257
addStatement("使用简单的字符串名称来获取一个对应的 [%T] 子类型的 intents 值,", EventIntentsClassName)
248258
addStatement("字符串名称与这个类型的简单类型相关:类名的名称,以及对应的snack(下滑线)格式。")
@@ -295,6 +305,45 @@ internal class EventIntentsAggregationProcessor(
295305
}
296306

297307

308+
/**
309+
* 生成 `IntentsAppenderOp`
310+
*
311+
* ```kotlin
312+
* @JvmInline
313+
* value class IntentsAppenderOp (private val appender: IntentsAppender) {
314+
* fun guilds() { appender.appendIntents(EventIntents.Guilds.intents) }
315+
* fun groupAndC2C() { ... }
316+
* // ...
317+
* }
318+
* ```
319+
*/
320+
private fun generateIntentsAppenderOp(nameToTypes: List<NamesToType>): TypeSpec {
321+
val builder = TypeSpec.classBuilder("IntentsAppenderOp")
322+
.addModifiers(KModifier.PUBLIC, KModifier.VALUE)
323+
.jvmInline()
324+
.primaryConstructor(
325+
FunSpec.constructorBuilder().apply {
326+
addParameter("appender", IntentsAppenderClassName)
327+
}.build()
328+
)
329+
.addProperty(
330+
PropertySpec.builder("appender", IntentsAppenderClassName, KModifier.PRIVATE)
331+
.initializer("appender")
332+
.build()
333+
)
334+
335+
nameToTypes.forEach { nameToType ->
336+
builder.addFunction(FunSpec.builder(nameToType.firstLower).apply {
337+
addModifiers(KModifier.PUBLIC)
338+
addCode(
339+
"appender.appendIntents(%T.intents)",
340+
nameToType.declaration.asStarProjectedType().toClassName()
341+
)
342+
}.build())
343+
}
344+
345+
return builder.build()
346+
}
298347
}
299348

300349
private fun String.toSnack(allUpper: Boolean): String = buildString(length) {

0 commit comments

Comments
 (0)