upload something

This commit is contained in:
2025-11-23 02:03:41 +08:00
parent 3ea1d5b360
commit 934e511f25
709 changed files with 52244 additions and 0 deletions

12
symbols/build.gradle.kts Normal file
View File

@@ -0,0 +1,12 @@
plugins {
kotlin("jvm")
id("com.google.devtools.ksp")
id("firmament.common")
}
dependencies {
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0")
implementation("com.google.auto.service:auto-service-annotations:1.1.1")
implementation("com.google.devtools.ksp:symbol-processing-api:1.9.23-1.0.20")
implementation("com.google.code.gson:gson:2.11.0")
}

View File

@@ -0,0 +1,7 @@
package moe.nea.firmament.annotations
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
annotation class Subscribe

View File

@@ -0,0 +1,63 @@
package moe.nea.firmament.annotations.process
import com.google.auto.service.AutoService
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
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.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSName
class CompatMetaProcessor(val logger: KSPLogger, val codeGenerator: CodeGenerator, val sourceSetName: String) :
SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val files = resolver.getAllFiles().toList()
val packages = files.mapTo(mutableSetOf()) { it.packageName.asString() }
packages.add("moe.nea.firmament.annotations.generated.$sourceSetName")
val compatMeta = resolver.getSymbolsWithAnnotation("moe.nea.firmament.util.compatloader.CompatMeta")
.singleOrNull() as KSClassDeclaration? ?: return listOf()
val dependencies = Dependencies(aggregating = true, *files.toTypedArray())
val generatedFileName = "GeneratedCompat${sourceSetName.replaceFirstChar { it.uppercaseChar() }}"
val compatFile =
codeGenerator.createNewFile(dependencies, "moe.nea.firmament.annotations.generated.$sourceSetName", generatedFileName)
.bufferedWriter()
compatFile.appendLine("// This file is @generated by SubscribeAnnotationProcessor")
compatFile.appendLine("// Do not edit")
compatFile.appendLine("package moe.nea.firmament.annotations.generated.$sourceSetName")
compatFile.appendLine("class $generatedFileName : moe.nea.firmament.util.compatloader.ICompatMetaGen {")
compatFile.appendLine("""
override fun owns(className: String): Boolean {
return moe.nea.firmament.util.compatloader.CompatHelper.isOwnedByPackage(className, ${
packages.joinToString { "\"" + it + "\"" }
})
}
override val meta: moe.nea.firmament.util.compatloader.ICompatMeta
get() = ${compatMeta.qualifiedName!!.asString()}
""")
compatFile.appendLine("}")
compatFile.close()
val metaInf = codeGenerator.createNewFileByPath(
dependencies,
"META-INF/services/moe.nea.firmament.util.compatloader.ICompatMetaGen", extensionName = "")
.bufferedWriter()
metaInf.append("moe.nea.firmament.annotations.generated.$sourceSetName.")
metaInf.appendLine(generatedFileName)
metaInf.close()
return listOf()
}
@AutoService(SymbolProcessorProvider::class)
class Provider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return CompatMetaProcessor(environment.logger,
environment.codeGenerator,
environment.options["firmament.sourceset"] ?: "main")
}
}
}

View File

@@ -0,0 +1,80 @@
package moe.nea.firmament.annotations.process
import com.google.auto.service.AutoService
import com.google.devtools.ksp.containingFile
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
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.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSFile
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import java.io.OutputStreamWriter
import java.nio.charset.StandardCharsets
import java.util.TreeSet
class GameTestContainingClassProcessor(
val logger: KSPLogger,
val codeGenerator: CodeGenerator,
val sourceSetName: String,
) : SymbolProcessor {
@AutoService(SymbolProcessorProvider::class)
class Provider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return GameTestContainingClassProcessor(
environment.logger,
environment.codeGenerator,
environment.options["firmament.sourceset"] ?: "main")
}
}
val allClasses: MutableSet<String> = TreeSet()
val allSources = mutableSetOf<KSFile>()
override fun process(resolver: Resolver): List<KSAnnotated> {
val annotated = resolver.getSymbolsWithAnnotation("net.minecraft.test.GameTest").toList()
annotated.forEach {
val containingClass = it.parent as KSClassDeclaration
allClasses.add(containingClass.qualifiedName!!.asString())
allSources.add(it.containingFile!!)
}
return emptyList()
}
fun createJson(): JsonObject {
return JsonObject().apply {
addProperty("schemaVersion", 1)
addProperty("id", "firmament-gametest")
addProperty("name", "Firmament Gametest")
addProperty("version", "1.0.0")
addProperty("environment", "*")
add("entrypoints", JsonObject().apply {
add("fabric-gametest", JsonArray().apply {
allClasses.forEach {
add(it)
}
})
})
}
}
override fun finish() {
if (allClasses.isEmpty()) return
val stream = codeGenerator.createNewFile(Dependencies(aggregating = true, *allSources.toTypedArray()),
"",
"fabric.mod",
"json")
val output = OutputStreamWriter(stream, StandardCharsets.UTF_8)
Gson().toJson(createJson(), output)
output.close()
}
}

View File

@@ -0,0 +1,136 @@
package moe.nea.firmament.annotations.process
import com.google.auto.service.AutoService
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
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.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.symbol.Nullability
import com.google.devtools.ksp.validate
import moe.nea.firmament.annotations.Subscribe
class SubscribeAnnotationProcessor(
val logger: KSPLogger,
val codeGenerator: CodeGenerator,
val sourceSetName: String,
) : SymbolProcessor {
override fun finish() {
subscriptions.sort()
if (subscriptions.isEmpty()) return
val subscriptionSet = subscriptions.mapTo(mutableSetOf()) { it.cf }
val dependencies = Dependencies(
aggregating = true,
*subscriptionSet.toTypedArray())
val generatedFileName = "AllSubscriptions${sourceSetName.replaceFirstChar { it.uppercaseChar() }}"
val subscriptionsFile =
codeGenerator
.createNewFile(dependencies, "moe.nea.firmament.annotations.generated.$sourceSetName", generatedFileName)
.bufferedWriter()
subscriptionsFile.apply {
appendLine("// This file is @generated by SubscribeAnnotationProcessor")
appendLine("// Do not edit")
appendLine("package moe.nea.firmament.annotations.generated.$sourceSetName")
appendLine()
appendLine("import moe.nea.firmament.events.subscription.*")
appendLine()
appendLine("@Suppress()")
appendLine("class $generatedFileName : SubscriptionList {")
appendLine(" override fun provideSubscriptions(addSubscription: (Subscription<*>) -> Unit) {")
for (subscription in subscriptions) {
val owner = subscription.pQName.asString()
val method = subscription.child.simpleName.asString()
val type = subscription.type.declaration.qualifiedName!!.asString()
appendLine(" addSubscription(Subscription<$type>(")
appendLine(" ${owner},")
appendLine(" ${owner}::${method},")
appendLine(" ${type},")
appendLine(" \"${method}\"))")
}
appendLine(" }")
appendLine("}")
}
subscriptionsFile.close()
val metaInf = codeGenerator.createNewFileByPath(
dependencies,
"META-INF/services/moe.nea.firmament.events.subscription.SubscriptionList", extensionName = "")
.bufferedWriter()
metaInf.append("moe.nea.firmament.annotations.generated.$sourceSetName.")
metaInf.appendLine(generatedFileName)
metaInf.close()
}
data class Subscription(
val parent: KSClassDeclaration,
val child: KSFunctionDeclaration,
val type: KSType,
) : Comparable<Subscription> {
val cf = parent.containingFile!!
val pQName = parent.qualifiedName!!
val tName = type.declaration.qualifiedName!!
override fun compareTo(other: Subscription): Int {
var compare = pQName.asString().compareTo(other.pQName.asString())
if (compare != 0) return compare
compare = other.child.simpleName.asString().compareTo(child.simpleName.asString())
if (compare != 0) return compare
compare = other.tName.asString().compareTo(tName.asString())
if (compare != 0) return compare
return 0
}
}
val subscriptions = mutableListOf<Subscription>()
fun processCandidates(list: List<KSAnnotated>) {
for (element in list) {
if (element !is KSFunctionDeclaration) {
logger.error("@Subscribe annotation on a not-function", element)
continue
}
if (element.isAbstract) {
logger.error("@Subscribe annotation on an abstract function", element)
continue
}
val parent = element.parentDeclaration
if (parent !is KSClassDeclaration || parent.classKind != ClassKind.OBJECT) {
logger.error("@Subscribe on a non-object", element)
continue
}
val param = element.parameters.singleOrNull()
if (param == null) {
logger.error("@Subscribe annotated functions need to take exactly one parameter", element)
continue
}
val type = param.type.resolve()
if (type.nullability != Nullability.NOT_NULL) {
logger.error("@Subscribe annotated functions cannot take a nullable event", element)
continue
}
subscriptions.add(Subscription(parent, element, type))
}
}
override fun process(resolver: Resolver): List<KSAnnotated> {
val candidates = resolver.getSymbolsWithAnnotation(Subscribe::class.qualifiedName!!).toList()
val valid = candidates.filter { it.validate() }
val invalid = candidates.filter { !it.validate() }
processCandidates(valid)
return invalid
}
}
@AutoService(SymbolProcessorProvider::class)
class SubscribeAnnotationProcessorProvider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return SubscribeAnnotationProcessor(environment.logger,
environment.codeGenerator,
environment.options["firmament.sourceset"] ?: "main")
}
}