Skip to content

Commit 3ca6821

Browse files
committed
Add the exampel project to integration tests
1 parent 0edf778 commit 3ca6821

File tree

10 files changed

+476
-0
lines changed

10 files changed

+476
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.google.devtools.ksp.test
2+
3+
import org.gradle.testkit.runner.GradleRunner
4+
import org.gradle.testkit.runner.TaskOutcome
5+
import org.junit.Assert
6+
import org.junit.Rule
7+
import org.junit.Test
8+
import java.io.File
9+
import java.util.jar.*
10+
11+
class PlaygroundIT {
12+
@Rule
13+
@JvmField
14+
val project: TemporaryTestProject = TemporaryTestProject("playground")
15+
16+
@Test
17+
fun testPlayground() {
18+
val gradleRunner = GradleRunner.create().withProjectDir(project.root)
19+
20+
val resultCleanBuild = gradleRunner.withArguments("clean", "build").build()
21+
22+
Assert.assertEquals(TaskOutcome.SUCCESS, resultCleanBuild.task(":workload:build")?.outcome)
23+
24+
val artifact = File(project.root, "workload/build/libs/workload-1.0-SNAPSHOT.jar")
25+
Assert.assertTrue(artifact.exists())
26+
27+
JarFile(artifact).use { jarFile ->
28+
Assert.assertTrue(jarFile.getEntry("TestProcessor.log").size > 0)
29+
Assert.assertTrue(jarFile.getEntry("HELLO.class").size > 0)
30+
Assert.assertTrue(jarFile.getEntry("com/example/AClassBuilder.class").size > 0)
31+
}
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pluginManagement {
2+
val kotlinVersion: String by settings
3+
val kspVersion: String by settings
4+
val testRepo: String by settings
5+
plugins {
6+
id("com.google.devtools.ksp") version kspVersion
7+
kotlin("jvm") version kotlinVersion
8+
}
9+
repositories {
10+
maven(testRepo)
11+
gradlePluginPortal()
12+
google()
13+
}
14+
}
15+
16+
rootProject.name = "playground"
17+
18+
include(":workload")
19+
include(":test-processor")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
val kspVersion: String by project
2+
val testRepo: String by project
3+
4+
plugins {
5+
kotlin("jvm")
6+
}
7+
8+
group = "com.example"
9+
version = "1.0-SNAPSHOT"
10+
11+
repositories {
12+
maven(testRepo)
13+
mavenCentral()
14+
google()
15+
}
16+
17+
dependencies {
18+
implementation(kotlin("stdlib"))
19+
implementation("com.squareup:javapoet:1.12.1")
20+
implementation("com.google.devtools.ksp:symbol-processing-api:$kspVersion")
21+
}
22+
23+
sourceSets.main {
24+
java.srcDirs("src/main/kotlin")
25+
}
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.example.annotation
2+
3+
annotation class Builder {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import com.google.devtools.ksp.processing.CodeGenerator
2+
import com.google.devtools.ksp.processing.Dependencies
3+
import com.google.devtools.ksp.processing.KSPLogger
4+
import com.google.devtools.ksp.processing.Resolver
5+
import com.google.devtools.ksp.processing.SymbolProcessor
6+
import com.google.devtools.ksp.symbol.*
7+
import java.io.File
8+
import java.io.OutputStream
9+
10+
fun OutputStream.appendText(str: String) {
11+
this.write(str.toByteArray())
12+
}
13+
class BuilderProcessor : SymbolProcessor {
14+
lateinit var codeGenerator: CodeGenerator
15+
16+
override fun finish() {
17+
18+
}
19+
20+
override fun init(options: Map<String, String>, kotlinVersion: KotlinVersion, codeGenerator: CodeGenerator, logger: KSPLogger) {
21+
this.codeGenerator = codeGenerator
22+
}
23+
24+
override fun process(resolver: Resolver) {
25+
val symbols = resolver.getSymbolsWithAnnotation("com.example.annotation.Builder")
26+
symbols
27+
.filter { it is KSClassDeclaration }
28+
.map { it.accept(BuilderVisitor(), Unit) }
29+
}
30+
31+
inner class BuilderVisitor : KSVisitorVoid() {
32+
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
33+
classDeclaration.primaryConstructor!!.accept(this, data)
34+
}
35+
36+
override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
37+
val parent = function.parentDeclaration as KSClassDeclaration
38+
val packageName = parent.containingFile!!.packageName.asString()
39+
val className = "${parent.simpleName.asString()}Builder"
40+
val file = codeGenerator.createNewFile(Dependencies(true, function.containingFile!!), packageName , className)
41+
file.appendText("package $packageName\n\n")
42+
file.appendText("class $className{\n")
43+
function.parameters.forEach {
44+
val name = it.name!!.asString()
45+
val typeName = StringBuilder(it.type.resolve().declaration.qualifiedName?.asString() ?: "<ERROR>")
46+
val typeArgs = it.type.element!!.typeArguments
47+
if (it.type.element!!.typeArguments.isNotEmpty()) {
48+
typeName.append("<")
49+
typeName.append(
50+
typeArgs.map {
51+
val type = it.type?.resolve()
52+
"${it.variance.label} ${type?.declaration?.qualifiedName?.asString()}" +
53+
if (type?.nullability == Nullability.NULLABLE) "?" else ""
54+
}.joinToString(", ")
55+
)
56+
typeName.append(">")
57+
}
58+
file.appendText(" private var $name: $typeName? = null\n")
59+
file.appendText(" internal fun with${name.capitalize()}($name: $typeName): $className {\n")
60+
file.appendText(" this.$name = $name\n")
61+
file.appendText(" return this\n")
62+
file.appendText(" }\n\n")
63+
}
64+
file.appendText(" internal fun build(): ${parent.qualifiedName!!.asString()} {\n")
65+
file.appendText(" return ${parent.qualifiedName!!.asString()}(")
66+
file.appendText(
67+
function.parameters.map {
68+
"${it.name!!.asString()}!!"
69+
}.joinToString(", ")
70+
)
71+
file.appendText(")\n")
72+
file.appendText(" }\n")
73+
file.appendText("}\n")
74+
file.close()
75+
}
76+
}
77+
78+
}

0 commit comments

Comments
 (0)