kompile-testing internal

kompile-testing internal

At shibuya.apk

Ce37cf75fa85b89a33916545978c64de?s=128

@hotchemi

April 12, 2019
Tweet

Transcript

  1. kompile-testing internal @hotchemi

  2. • google/compile-testing • Testing tools for javac and apt •

    Used in some code-gen libraries • Dagger2 • JavaPoet • Auto
  3. Compilation compilation = javac() .withProcessors(new Processor()) .compile(JavaFileObjects.forResource("HelloWorld.java")); assertThat(compilation).succeeded(); assertThat(compilation) .generatedSourceFile("GeneratedHelloWorld")

    .hasSourceEquivalentTo( JavaFileObjects.forResource("GeneratedHelloWorld.java"));
  4. None
  5. • kompile-testing • Simple API as compile-testing provides • Supports

    kotlinc and kapt • Version: 0.1.2(alpha)
  6. kotlinc() .withProcessors(Processor()) .addKotlin("input.kt", """ import kompile.testing.TestAnnotation @TestAnnotation class TestClass """.trimIndent())

    .compile() .succeededWithoutWarnings() .generatedFile("generatedKtFile.kt") .hasSourceEquivalentTo(""" class GeneratedKtFile """.trimIndent())
  7. Demo

  8. Under the hood

  9. Register processors - Write KClass info as a jar file

    - For specifying kapt options Add Kotlin file - Just write contents to .kt file - Under source directory Run Kotlin compiler API - Define classpath and kapt options - Then run K2JVMCompiler#exec
  10. K2JVMCompiler().exec( errStream = /* stream to output error */), args

    = /* CLI options */)
  11. • Command line compiler kotlinc hello.kt -d hello.jar kotlin -classpath

    hello.jar HelloKt
  12. • plugin/kapt options kotlinc hello.kt -d hello.jar -Xplugin=$KOTLIN_HOME/lib/kotlin-annotation-processing.jar -P plugin:org.jetbrains.kotlin.kapt3:sources=build/kapt/sources

    -P plugin:org.jetbrains.kotlin.kapt3:classes=build/kapt/classes -P plugin:org.jetbrains.kotlin.kapt3:stubs=build/kapt/stubs -P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt -P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/apt.jar
  13. fun compile(): Compilation { val args = mutableListOf<String>() args.add("-d") args.add(classesDir.toString())

    args.add("-no-stdlib") args.add("-classpath") args.add(fullClasspath().joinToString(separator = ":")) val sourceFiles = sourcesDir.listFiles() if (sourceFiles != null && sourceFiles.isNotEmpty()) { sourceFiles.forEach { args.add(it.toString()) } } val generatedDir = File(rootDir, "generated") args.addAll(annotationProcessorArgs(generatedDir.path)) val systemErrBuffer = Buffer() val stream = PrintStream(systemErrBuffer.outputStream()) val args = *args.toTypedArray() val exitCode = K2JVMCompiler().exec(stream, args) return Compilation(systemErrBuffer.readUtf8(), exitCode, generatedDir) }
  14. private fun annotationProcessorArgs(generatedDirPath: String): List<String> { val sourceDir = File(rootDir,

    "kapt/sources") val stubsDir = File(rootDir, "kapt/stubs") val kaptArgs = mutableMapOf<String, String>() kaptArgs["kapt.kotlin.generated"] = generatedDirPath val plugin = classpathFiles.find { it.name.startsWith(“kotlin-annotation-processing-embeddable”) } return listOf( "-Xplugin=$plugin", "-P", "plugin:org.jetbrains.kotlin.kapt3:sources=$sourceDir", "-P", "plugin:org.jetbrains.kotlin.kapt3:classes=$classesDir", "-P", "plugin:org.jetbrains.kotlin.kapt3:stubs=$stubsDir", "-P", "plugin:org.jetbrains.kotlin.kapt3:apclasspath=$servicesJar", "-P", "plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt", "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true", "-P", "plugin:org.jetbrains.kotlin.kapt3:apoptions=${options(kaptArgs)}" ) }
  15. • Conclusion • Extensible compiler API once you figure out

    • Go into jetbrains/kotlin! • Support Kotlin in your code-gen project with kompile-testing • Still alpha though:D
  16. • References • https://kotlinlang.org/docs/tutorials/command-line.html • https://kotlinlang.org/docs/reference/kapt.html • https://kotlinlang.org/docs/reference/compiler- plugins.html •

    https://speakerdeck.com/kevinmost/writing-your-first- kotlin-compiler-plugin