Skip to content

Commit 15765ba

Browse files
committed
Add the exampel project to integration tests
1 parent e2b5248 commit 15765ba

File tree

10 files changed

+478
-0
lines changed

10 files changed

+478
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.google.devtools.ksp.test
2+
3+
import TestsCommon
4+
import org.gradle.testkit.runner.GradleRunner
5+
import org.gradle.testkit.runner.TaskOutcome
6+
import org.junit.Assert
7+
import org.junit.Test
8+
import java.io.File
9+
import java.util.jar.*
10+
11+
class PlaygroundIT : TestsCommon() {
12+
override val testProjectName = "playground"
13+
14+
@Test
15+
fun testPlayground() {
16+
val gradleRunner = GradleRunner.create().withProjectDir(testProjectDir)
17+
18+
val resultCleanBuild = gradleRunner.withArguments("clean", "build").build()
19+
20+
Assert.assertEquals(TaskOutcome.SUCCESS, resultCleanBuild.task(":workload:build")?.outcome)
21+
22+
val artifact = File(testProjectDir, "workload/build/libs/workload-1.0-SNAPSHOT.jar")
23+
Assert.assertTrue(artifact.exists())
24+
25+
val jarFile = JarFile(artifact)
26+
Assert.assertTrue(jarFile.getEntry("TestProcessor.log").size > 0)
27+
Assert.assertTrue(jarFile.getEntry("HELLO.class").size > 0)
28+
Assert.assertTrue(jarFile.getEntry("com/example/AClassBuilder.class").size > 0)
29+
}
30+
}
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,83 @@
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+
println(symbols)
27+
symbols
28+
.filter { it is KSClassDeclaration }
29+
.map { it.accept(BuilderVisitor(), Unit) }
30+
}
31+
32+
inner class BuilderVisitor : KSVisitorVoid() {
33+
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
34+
classDeclaration.primaryConstructor!!.accept(this, data)
35+
}
36+
37+
override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
38+
val parent = function.parentDeclaration as KSClassDeclaration
39+
val packageName = parent.containingFile!!.packageName.asString()
40+
val className = "${parent.simpleName.asString()}Builder"
41+
val file = codeGenerator.createNewFile(Dependencies(true, function.containingFile!!), packageName , className)
42+
file.appendText("package $packageName\n\n")
43+
file.appendText("class $className{\n")
44+
function.parameters.forEach {
45+
val name = it.name!!.asString()
46+
val typeName = StringBuilder(it.type.resolve().declaration.qualifiedName?.asString() ?: "<ERROR>")
47+
if (typeName.toString() == "<ERROR>") {
48+
File("/tmp/BuilderLog").appendText("${(it.name as KSName).asString()}:${function.containingFile?.fileName}")
49+
}
50+
val typeArgs = it.type.element!!.typeArguments
51+
if (it.type.element!!.typeArguments.isNotEmpty()) {
52+
typeName.append("<")
53+
typeName.append(
54+
typeArgs.map {
55+
val type = it.type?.resolve()
56+
"${it.variance.label} ${type?.declaration?.qualifiedName?.asString()}" +
57+
if (type?.nullability == Nullability.NULLABLE) "?" else ""
58+
}.joinToString(", ")
59+
)
60+
typeName.append(">")
61+
}
62+
// typeName.append(if ((it.type?.type as? KSUserType)?.isNullable == true) "?" else "")
63+
file.appendText(" private var $name: $typeName? = null\n")
64+
file.appendText(" internal fun with${name.capitalize()}($name: $typeName): $className {\n")
65+
file.appendText(" this.$name = $name\n")
66+
file.appendText(" return this\n")
67+
file.appendText(" }\n\n")
68+
}
69+
file.appendText(" internal fun build(): ${parent.qualifiedName!!.asString()} {\n")
70+
file.appendText(" return ${parent.qualifiedName!!.asString()}(")
71+
file.appendText(
72+
function.parameters.map {
73+
"${it.name!!.asString()}!!"
74+
}.joinToString(", ")
75+
)
76+
file.appendText(")\n")
77+
file.appendText(" }\n")
78+
file.appendText("}\n")
79+
file.close()
80+
}
81+
}
82+
83+
}

0 commit comments

Comments
 (0)