kotlin compiler plugin

kotlin compiler plugin

Ce37cf75fa85b89a33916545978c64de?s=128

@hotchemi

June 21, 2017
Tweet

Transcript

  1. Kotlin compiler plugin

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

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

  4. • 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
  5. .kt Tokens AST JVM JS LLVM Frontend Backend

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

  7. • Abstract syntax tree 1 + 1 == 2

  8. • Abstract syntax tree 1 + 1 == 2 •

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

    just for JVM? • kapt3 plugin • all-open plugin • no-arg plugin • android-extensions plugin
  11. .kt Tokens AST JVM JS LLVM Frontend Backend compiler plugin

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

  13. AST JVM • no-arg plugin 0: aload_0 1: invokespecial //

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

    ExpressionCodegenExtension • ClassBuilderInterceptorExtension • Change modifier of variable • DeclarationAttributeAltererExtension
  15. • Extension points • PackageFragmentProviderExtension • for xml parser(android extensions)

    • AnalysisHandlerExtension • used in kapt3
  16. • Extension points • Others • SyntheticResolveExtension • StorageComponentContainerContributor •

    for IDE?
  17. • How to create • Need to prepare: • gradle-plugin

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

    • 2. CommandLineProcessor • 3. ComponentRegistrar • 4. Register extensions
  19. Please check hotchemi/kotlin-compiler-plugin-example

  20. • Real example • power-assert • pretty simple ver

  21. Demo

  22. • Under the food • capture assert method calling •

    in ExpressionCodegenExtension • parse argument AST • and generates JVM bytecode manually
  23. assert(1 + 2 == 2)

  24. 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
  25. • pain points • requires deep understanding of • Kotlin

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

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