Skip to content

Commit

Permalink
Add annotation processing
Browse files Browse the repository at this point in the history
  • Loading branch information
DRSchlaubi committed Nov 13, 2024
1 parent 37f24a7 commit 9d0c92a
Show file tree
Hide file tree
Showing 15 changed files with 214 additions and 5 deletions.
13 changes: 13 additions & 0 deletions annotation-processor/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
java
`maven-publish`
}

publishing {
publications {
create<MavenPublication>("maven") {
artifactId = "lavalink-annotation-processor"
from(components["java"])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.arbjerg.lavalink.processor;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import javax.tools.StandardLocation;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@SupportedSourceVersion(SourceVersion.RELEASE_17)
@SupportedAnnotationTypes(LavalinkAnnotationProcessor.SPRING_CONFIGURATION)
public class LavalinkAnnotationProcessor extends AbstractProcessor {

public static final String SPRING_CONFIGURATION = "org.springframework.context.annotation.Configuration";
private TypeElement springConfigurationElement;
private final List<CharSequence> configurationClasses = new ArrayList<>();

@Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
springConfigurationElement = processingEnv.getElementUtils().getTypeElement(SPRING_CONFIGURATION);
super.init(processingEnv);
}

@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
writeStorage();
return false;
}
var newConfigurations = roundEnv.getElementsAnnotatedWith(springConfigurationElement)
.stream()
.filter(element -> element.getKind() == ElementKind.CLASS)
.map(clazz -> processingEnv.getElementUtils().getBinaryName((TypeElement) clazz))
.toList();
processingEnv.getMessager().printMessage(Kind.NOTE, "Found the following new configurations: " + newConfigurations);
configurationClasses.addAll(newConfigurations);
return false;
}

private void writeStorage() {
try (var resource = new BufferedWriter(processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/configurations.idx").openWriter())) {
for (CharSequence className : configurationClasses) {
resource.write(className.toString());
resource.newLine();
}
} catch (IOException e) {
processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage());
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dev.arbjerg.lavalink.processor.LavalinkAnnotationProcessor
16 changes: 12 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ plugins {
`kotlin-dsl`
alias(libs.plugins.gradle.publish)
`maven-publish`
alias(libs.plugins.buildconfig)
}

group = "dev.arbjerg"
version = "1.1.2"
allprojects {
group = "dev.arbjerg"
version = "2.0.0"

repositories {
mavenCentral()
repositories {
mavenCentral()
}
}

kotlin {
Expand All @@ -19,6 +22,11 @@ dependencies {
compileOnly(kotlin("gradle-plugin"))
}

buildConfig {
packageName("dev.arbjerg.lavalink.gradle")
buildConfigField("String", "VERSION", provider { "\"${project.version}\"" })
}

gradlePlugin {
plugins {
create("lavalink-gradle-plugin") {
Expand Down
6 changes: 6 additions & 0 deletions example/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ plugins {
group = "dev.arbjerg.lavalink.example"
version = "1.0.0"

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
// Only here to test dependency handling
// And Kotlin is best dependency <3
implementation(kotlin("stdlib", "2.0.21"))
implementation("org.jetbrains.kotlinx", "kotlinx-serialization-json", "1.7.3")
implementation("org.jetbrains.kotlinx", "kotlinx-coroutines-core", "1.9.0")
annotationProcessor("dev.arbjerg", "lavalink-annotation-processor", "2.0.0")
}

java {
Expand Down
1 change: 1 addition & 0 deletions example/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
includeBuild("..")
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

@Configuration
@Service
public class Plugin extends PluginEventHandler {

Expand Down
7 changes: 7 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
[versions]
ksp = "2.0.21-1.0.27"

[libraries]
ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" }

[plugins]
gradle-publish = { id = "com.gradle.plugin-publish", version = "1.3.0" }
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "5.5.0" }
11 changes: 11 additions & 0 deletions kotlin-symbol-processor/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
kotlin("jvm")
}

kotlin {
jvmToolchain(17)
}

dependencies {
implementation(libs.ksp.api)
}
4 changes: 4 additions & 0 deletions kotlin-symbol-processor/src/main/kotlin/Annotations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package dev.arbjerg.lavalink.processor

const val SPRING_CONFIGURATION = "org.springframework.context.annotation.Configuration"
const val PF4J_EXTENSION = "org.pf4j.Extension"
39 changes: 39 additions & 0 deletions kotlin-symbol-processor/src/main/kotlin/ConfigurationProcessor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.arbjerg.lavalink.processor

import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration

class ConfigurationProcessor(private val environment: SymbolProcessorEnvironment) : SymbolProcessor {
private val configurationClasses = mutableListOf<String>()
override fun process(resolver: Resolver): List<KSAnnotated> {
configurationClasses += resolver.getSymbolsWithAnnotation(SPRING_CONFIGURATION)
.filterIsInstance<KSClassDeclaration>()
.mapNotNull { it.qualifiedName?.toString() }
.onEach {
environment.logger.logging("Found configuration class: $it")
}

return emptyList()
}

override fun finish() {
environment.logger.logging("Received finish signal, writing ${configurationClasses.size} to fs")
environment.codeGenerator.createNewFile(
dependencies = Dependencies.ALL_FILES,
packageName = "META-INF",
fileName = "configuration-classes",
extensionName = "idx"
).bufferedWriter().use { writer ->
configurationClasses.forEach {
writer.write(it)
writer.newLine()
}
}
}

companion object Provider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor =
ConfigurationProcessor(environment)
}
}
41 changes: 41 additions & 0 deletions kotlin-symbol-processor/src/main/kotlin/ExtensionProcessor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package dev.arbjerg.lavalink.processor

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

class ExtensionProcessor(private val environment: SymbolProcessorEnvironment) : SymbolProcessor {

private val metaAnnotations = mutableListOf<String>()
private val extensions = mutableListOf<String>()

companion object Provider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor = ExtensionProcessor(environment)
}

override fun process(resolver: Resolver): List<KSAnnotated> {
metaAnnotations += resolver.getSymbolsWithAnnotation(PF4J_EXTENSION)
.filterIsInstance<KSClassDeclaration>()
.filter { it.classKind == ClassKind.ANNOTATION_CLASS }
.onEach { environment.logger.logging("Found meta annotation: ${it.qualifiedName?.asString()}") }
.map { it.qualifiedName.toString() }

return resolver.getNewFiles()
.flatMap { it.declarations }
.filterIsInstance<KSClassDeclaration>()
.filter {
if (it.qualifiedName != null && it.annotations.any { annotation -> annotation.shortName.asString() in metaAnnotations }) {
extensions.add(it.qualifiedName!!.toString())
environment.logger.logging("Found extension: ${it.qualifiedName!!.asString()}")
false
} else {
true
}
}
.toList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dev.arbjerg.lavalink.processor.ConfigurationProcessor$Provider
dev.arbjerg.lavalink.processor.ExtensionProcessor$Provider
5 changes: 5 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
rootProject.name = "lavalink-gradle-plugin"

include(
"kotlin-symbol-processor",
"annotation-processor"
)
15 changes: 14 additions & 1 deletion src/main/kotlin/LavalinkGradlePlugin.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dev.arbjerg.lavalink.gradle

import dev.arbjerg.lavalink.gradle.tasks.*
import dev.arbjerg.lavalink.gradle.tasks.DownloadLavalinkTask
import dev.arbjerg.lavalink.gradle.tasks.GeneratePluginPropertiesTask
import dev.arbjerg.lavalink.gradle.tasks.RunLavalinkTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
Expand Down Expand Up @@ -60,6 +62,17 @@ private fun Project.configureDependencies(): Provider<Dependency> {

dependencies {
add("compileOnly", lavalink("plugin-api"))
if (plugins.hasPlugin("org.gradle.java")) {
add("annotationProcessor", "dev.arbjerg.lavalink:annotation-processor:${BuildConfig.VERSION}")
add("annotationProcessor", "org.pf4j:pf4j:3.12.1")
}
if (plugins.hasPlugin("org.jetbrains.kotlin")) {
if (plugins.hasPlugin("com.google.devtools.ksp")) {
add("ksp", "dev.arbjerg.lavalink:kotlin-symbol-processor:${BuildConfig.VERSION}")
} else {
logger.error("Please configure KSP for Kotlin support https://kotlinlang.org/docs/ksp-quickstart.html#add-a-processor")
}
}
}

return extension.serverVersion.map { serverVersion ->
Expand Down

0 comments on commit 9d0c92a

Please sign in to comment.