Slide 1

Slide 1 text

Kotlin compiler plugin

Slide 2

Slide 2 text

Note: recommend to clone these repos - JetBrains/kotlin - hotchemi/kotlin-compiler-plugin-example

Slide 3

Slide 3 text

• Self-Intro • @hotchemi • at Quipper • PermissionsDispatcher, dex.fm

Slide 4

Slide 4 text

• Kotlin compiler • for JVM and JavaScript • kotlin-native generates LLVM bitcode • has frontend and backend • uses IntelliJ open API based AST • AST == abstract syntax tree • ex) PSIElement

Slide 5

Slide 5 text

.kt Tokens AST JVM JS LLVM Frontend Backend

Slide 6

Slide 6 text

this.returnType = “hoge” • Token keyword dot identifier equal literal

Slide 7

Slide 7 text

• Abstract syntax tree 1 + 1 == 2

Slide 8

Slide 8 text

• Abstract syntax tree 1 + 1 == 2 • KtBinaryExpression(1 + 1 == 2) • KtBinaryexpression(1 + 1) • KtConstantExpression(1) • KtOperationReference(+) • KtConstantExpression(1) • KtOperationReference(==) • KtConstantExpression(2)

Slide 9

Slide 9 text

val root = Disposable { } val configuration = CompilerConfiguration() configuration.addKotlinSourceRoot("./") val environment = KotlinCoreEnvironment.createForProduction(root, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) environment.getSourceFiles() ※ requires org.jetbrains.kotlin:kotlin-compiler-embeddable • Tip to get AST

Slide 10

Slide 10 text

• Kotlin compiler plugin • perfectly undocumented part • currently just for JVM? • kapt3 plugin • all-open plugin • no-arg plugin • android-extensions plugin

Slide 11

Slide 11 text

.kt Tokens AST JVM JS LLVM Frontend Backend compiler plugin

Slide 12

Slide 12 text

AST JVM • all-open plugin if (Modality.FINAL) return Modality.OPEN CliAllOpenDeclarationAttributeAltererExtension

Slide 13

Slide 13 text

AST JVM • no-arg plugin 0: aload_0 1: invokespecial // Method java/ lang/Object."":()V 4: return NoArgClassBuilderInterceptorExtension

Slide 14

Slide 14 text

• Extension points • generates JVM bytecode by AST • ExpressionCodegenExtension • ClassBuilderInterceptorExtension • Change modifier of variable • DeclarationAttributeAltererExtension

Slide 15

Slide 15 text

• Extension points • PackageFragmentProviderExtension • for xml parser(android extensions) • AnalysisHandlerExtension • used in kapt3

Slide 16

Slide 16 text

• Extension points • Others • SyntheticResolveExtension • StorageComponentContainerContributor • for IDE?

Slide 17

Slide 17 text

• How to create • Need to prepare: • gradle-plugin • maven-plugin • idea-plugin • don’t talk about this

Slide 18

Slide 18 text

• How to create • components lifecycle(Gradle) • 1. KotlinGradleSubplugin • 2. CommandLineProcessor • 3. ComponentRegistrar • 4. Register extensions

Slide 19

Slide 19 text

Please check hotchemi/kotlin-compiler-plugin-example

Slide 20

Slide 20 text

• Real example • power-assert • pretty simple ver

Slide 21

Slide 21 text

Demo

Slide 22

Slide 22 text

• Under the food • capture assert method calling • in ExpressionCodegenExtension • parse argument AST • and generates JVM bytecode manually

Slide 23

Slide 23 text

assert(1 + 2 == 2)

Slide 24

Slide 24 text

Code: 0: ldc #9 // String assert(1 + 2 == 2) 2: iconst_3 // 1+2 3: invokestatic #15 // Method java/lang/Integer.valueOf:(I)Ljava/ lang/Integer; 6: bipush 9 // offset of + 8: invokestatic #21 // Method kt/powerassert/ RecorderRuntimeKt.record:(Ljava/lang/Object;I)Ljava/lang/Object; 11: checkcast #23 // class java/lang/Number 14: invokevirtual #27 // Method java/lang/Number.intValue:()I 17: iconst_2 // 2 18: if_icmpne 25 // == 21: iconst_1 22: goto 26 25: iconst_0 26: invokestatic #32 // Method java/lang/Boolean.valueOf: (Z)Ljava/lang/Boolean; 29: bipush 13 // offset of == 31: invokestatic #21 // Method kt/powerassert/ RecorderRuntimeKt.record:(Ljava/lang/Object;I)Ljava/lang/Object; 34: checkcast #29 // class java/lang/Boolean 37: invokevirtual #36 // Method java/lang/Boolean.booleanValue:()Z 40: iconst_0 // anchor point 41: invokestatic #40 // Method kt/powerassert/ RecorderRuntimeKt.powerAssert:(Ljava/lang/String;ZI)V 44: return

Slide 25

Slide 25 text

• pain points • requires deep understanding of • Kotlin compiler API/AST • JVM stack machine • No documents, just read code

Slide 26

Slide 26 text

• References • JetBrains/kotlin • compiler plugin codes • Oracle JVM specification doc • https://github.com/cmf/psiviewer