Upgrade to Pro — share decks privately, control downloads, hide ads and more …

kotlin compiler plugin

kotlin compiler plugin

@hotchemi

June 21, 2017
Tweet

More Decks by @hotchemi

Other Decks in Programming

Transcript

  1. • 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
  2. • Abstract syntax tree 1 + 1 == 2 •

    KtBinaryExpression(1 + 1 == 2) • KtBinaryexpression(1 + 1) • KtConstantExpression(1) • KtOperationReference(+) • KtConstantExpression(1) • KtOperationReference(==) • KtConstantExpression(2)
  3. 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
  4. • Kotlin compiler plugin • perfectly undocumented part • currently

    just for JVM? • kapt3 plugin • all-open plugin • no-arg plugin • android-extensions plugin
  5. AST JVM • no-arg plugin 0: aload_0 1: invokespecial //

    Method java/ lang/Object."<init>":()V 4: return NoArgClassBuilderInterceptorExtension
  6. • Extension points • generates JVM bytecode by AST •

    ExpressionCodegenExtension • ClassBuilderInterceptorExtension • Change modifier of variable • DeclarationAttributeAltererExtension
  7. • How to create • Need to prepare: • gradle-plugin

    • maven-plugin • idea-plugin • don’t talk about this
  8. • How to create • components lifecycle(Gradle) • 1. KotlinGradleSubplugin

    • 2. CommandLineProcessor • 3. ComponentRegistrar • 4. Register extensions
  9. • Under the food • capture assert method calling •

    in ExpressionCodegenExtension • parse argument AST • and generates JVM bytecode manually
  10. 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
  11. • pain points • requires deep understanding of • Kotlin

    compiler API/AST • JVM stack machine • No documents, just read code
  12. • References • JetBrains/kotlin • compiler plugin codes • Oracle

    JVM specification doc • https://github.com/cmf/psiviewer