Slide 1

Slide 1 text

Kotlin Fest 2024 @kitakkun_pb ΋ͬͱKotlinΛ޷͖ʹͳΔʂ K2࣌୅ͷKotlin Compiler Plugin։ൃ

Slide 2

Slide 2 text

2 • kitakkun / Takumi Kitagawa • X: @kitakkun_pb • GitHub: @kitakkun • Android Engineer @ • େֶ࣌୅͸ Kotlin Compiler Plugin
 Λ׆༻ͨ͠ݚڀΛ͍ͯ͠·ͨ͠ ొஃऀϓϩϑΟʔϧ

Slide 3

Slide 3 text

ຊηογϣϯʹ͍ͭͯ • ର৅ • Kotlin Compiler Pluginͷ࢓૊Έɾ։ൃํ๏ʹڵຯ͕͋Δํ • औΓѻ͏಺༰ • Kotlin Compilerͷ಺෦ߏ଄ • Kotlin Compiler Plugin APIͷղઆ • Kotlin Compiler Pluginͷ׆༻ྫ 3

Slide 4

Slide 4 text

Kotlin Compilerͷ಺෦ߏ଄

Slide 5

Slide 5 text

Kotlin Compiler • KotlinͷιʔεϓϩάϥϜΛ࣮ߦՄೳϓϩάϥϜ΁ͱม׵ • Frontend ͱ Backend ͔Β੒Δ • Frontend ιʔεϓϩάϥϜͷղੳ • Backend ࠷దԽɾ໨తϓϩάϥϜʢJVM, Native, JS…ʣͷग़ྗ • K2ίϯύΠϥͰ͸ Frontend ΞʔΩςΫνϟʹେ෯มߋ 5

Slide 6

Slide 6 text

Kotlin Compiler FrontendʢK2ʣOverview 6 Changed in K2 Checker Source KtTokens AST/PSI RAW_FIR FIR IR FIR2IR Resolve Lex Parse

Slide 7

Slide 7 text

Source KtTokens ※ۭനτʔΫϯ͸লུ ... https://github.com/JetBrains/kotlin/blob/master/compiler/psi/src/org/ jetbrains/kotlin/lexer/KtTokens.java 7 fun kotlinFest ( ) = " 2024 " fun kotlinFest() = "2024" ࣈ۟ղੳ (Lex)

Slide 8

Slide 8 text

KtTokens ※ۭനτʔΫϯ͸লུ https://github.com/JetBrains/kotlin/blob/master/compiler/psi/src/org/ jetbrains/kotlin/lexer/KtTokens.java 8 fun kotlinFest ( ) = " 2024 " AST/PSI kotlin.FILE: fun kotlinFest() = "2024" PACKAGE_DIRECTIVE: IMPORT_LIST: FUN: fun kotlinFest() = "2024" fun: fun WHITE_SPACE: IDENTIFIER: kotlinFest VALUE_PARAMETER_LIST: () LPAR: ( RPAR: ) WHITE_SPACE: EQ: = WHITE_SPACE: STRING_TEMPLATE: "2024" OPEN_QUOTE: " LITERAL_STRING_TEMPLATE_ENTRY: 2024 REGULAR_STRING_PART: 2024 CLOSING_QUOTE: " FIR ߏจղੳ (Parse)

Slide 9

Slide 9 text

FIR - Frontend Intermediate Representation • Frontend ઐ༻ͷதؒදݱʢK2Ͱಋೖʣ • ίϯύΠϥ͕ίʔυʹ͍ͭͯ஌Γ͏Δ৘ใશͯΛؚΉ • ͍͔ͭ͘ͷϑΣʔζΛܦͯஈ֊తʹղܾ͞ΕΔ 9 K1Ͱ͸ PSI + Descriptor, BindingContext Source KtTokens AST/PSI RAW_FIR FIR Resolve

Slide 10

Slide 10 text

FIRΛղܾ͢Δ14ϑΣʔζ ॳظͷ FIR ͸׬શͳ৘ใΛ࣋ͨͣ
 14ͷϑΣʔζͰஈ֊తʹղܾ͞ΕΔ https://github.com/JetBrains/kotlin/blob/master/ compiler/ fi r/tree/src/org/jetbrains/kotlin/ fi r/ declarations/FirResolvePhase.kt 10 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 11

Slide 11 text

1. RAW_FIR 11 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS AST͔Β௚઀ಘΒΕΔੜͷFIR ଟ͘ͷ৘ใ͕ܽམͨ͠ঢ়ଶ • γϯϘϧͷࢀরઌ • ܕ৘ใ • etc...

Slide 12

Slide 12 text

2. IMPORTS 12 importจΛղܾ • import͞Ε͍ͯΔγϯϘϧΛಛఆ • ύοέʔδ෦෼ͱͦΕҎ߱Ͱ෼ׂ • ྫ: kotlin.collections.List
 → kotlin.collections / List • classId = package + className • callableId = package + callableName RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 13

Slide 13 text

3. COMPILER_REQUIRED_ANNOTATIONS 13 ίϯύΠϥΞϊςʔγϣϯͷܕΛղܾ • @SinceKotlin, @JvmRecord, … • @Deprecated, @Target͸
 Ҿ਺΋ղܾ͞ΕΔ @Deprecated("Use hoge instead") @Target(AnnotationTarget.CLASS) annotation class MyMarker RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 14

Slide 14 text

4. COMPANION_GENERATION 14 class A { companion object { … } } Compiler PluginʹΑΓఏڙ͞ΕΔ
 companion object Λੜ੒ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 15

Slide 15 text

શΫϥεͷεʔύʔλΠϓΛղܾ͠
 λΠϓΤΠϦΞεͷల։Λߦ͏ 5. SUPER_TYPES 15 class A : B() // AliasedC -> C open class B : AliasedC interface C typealias AliasedC = C RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 16

Slide 16 text

sealedΫϥεͷܧঝΫϥεΛه࿥ 6. SEALED_CLASS_INHERITORS 16 sealed class A data object B: A() data class C( ... ): A() RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 17

Slide 17 text

7. TYPES 17 fun a(): Int = ... fun b(str: String) { ... } fun Int.increment() = ... class A annotation class Annotation ໌ࣔతʹهड़͞ΕͨܕΛղܾ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 18

Slide 18 text

8. STATUS 18 ϝϯόએݴͷ Status Λղܾ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS class A { // visibility private fun hoge() { … } // modality abstract fun fuga() // modifiers suspend fun foo() }

Slide 19

Slide 19 text

9. EXPECT_ACTUAL_MATCHING 19 // commonMain expect val platform: String // jvmMain actual val platform = "jvm" // iosMain actual val platform = "ios" MultiplatformϓϩδΣΫτͷ expectએݴͱactualએݴͷରԠ෇͚ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 20

Slide 20 text

10. CONTRACTS 20 contractϒϩοΫΛղܾ • contract = ίϯύΠϥͱͷ໿ଋࣄ @kotlin.internal.InlineOnly public inline fun T.apply(block: T.() - > Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() return this } ↓ block͕1౓͔͠ݺ͹Εͳ͍͜ͱΛڭ͍͑ͯΔ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 21

Slide 21 text

11. IMPLICIT_TYPES_BODY_RESOLVE 21 callableͳએݴͷ҉໧తͳܕΛղܾ + constϓϩύςΟͷॳظԽࣜͷղܾ fun foo() = 0 // Int val bar = "str" // String val baz get() = foo() / / Int RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS const val a = 0 + 10

Slide 22

Slide 22 text

12. CONSTANT_EVALUATION 22 constϓϩύςΟͷॳظԽࣜͱ
 ΞϊςʔγϣϯҾ਺ͷσϑΥϧτ஋
 ΛධՁ const val a = 0 + 10 ↓ const val a = 10 annotation class A(val a: Int = 10) RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 23

Slide 23 text

13. ANNOTATION_ARGUMENTS 23 એݴ෦ͷΞϊςʔγϣϯҾ਺Λղܾ annotation class A( val a: Int = 10 ) @A(a = 20) class B RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 24

Slide 24 text

14. BODY_RESOLVE 24 એݴͷຊମʢBodyʣΛղܾ fun a() { val hoge = object { ... } } RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 25

Slide 25 text

14. BODY_RESOLVE (Local Declarations) 25 એݴͷຊମʢBodyʣΛղܾ ϩʔΧϧએݴΛൃݟͨ͠Β COMPILER_REQUIRED_ANNOTATIONS ~ ANNOTATION_ARGUMENTS ·ͰΛہॴతʹద༻ fun a() { // local declaration val hoge = object { ... } } RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 26

Slide 26 text

CHECKER 26 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS Resolved FIR Checker RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 27

Slide 27 text

FIR2IR 27 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS Resolved FIR Checker IR (backend) FIR2IR RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 28

Slide 28 text

Kotlin Compiler Backend 28 IR Lowered IR Target Code .class 01101010 10101010 01011 JS JVM Native JS FIR

Slide 29

Slide 29 text

Kotlin Compiler ·ͱΊ • Frontend ͱ Backend 2ͭͷ෦෼͔Β੒Δ • Frontend • ιʔείʔυͷղੳ͕ओ໨త • FIR ͱ͍͏ஈ֊తʹղܾ͞ΕΔதؒදݱΛѻ͏ • Backend • ࠷దԽ΍໨తϓϩάϥϜͷग़ྗ͕໨త • IR ͱ͍͏׬શʹ৘ใ͕ղܾ͞ΕͨதؒදݱΛѻ͏ 29

Slide 30

Slide 30 text

Kotlin Compiler Plugin

Slide 31

Slide 31 text

Kotlin Compiler Plugin ίϯύΠϥͷ֤ม׵ϑΣʔζʹհೖ͠தؒදݱʢFIR / IRʣΛૢ࡞ 31 Compiler Frontend Compiler Backend KtTokens AST/PSI RAW_FIR FIR Source IR Lowered IR Target Code FIR֦ு IR֦ு

Slide 32

Slide 32 text

Frontend֦ுͷجૅ

Slide 33

Slide 33 text

Frontend֦ுʹͰ͖Δ͜ͱ • εʔύʔλΠϓͷ௥Ճ FirSupertypeGenerationExtension • એݴͷੜ੒ FirDeclarationGenerationExtension • Status ͷม׵ FirStatusTransformerExtension • FIRνΣοΧʔͷ௥Ճ FirAdditionalCheckersExtension • … 33 https://github.com/JetBrains/kotlin/blob/master/docs/ fi r/ fi r-plugins.md

Slide 34

Slide 34 text

FirSupertypeGenerationExtension 34 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS class A class A : MyInterface

Slide 35

Slide 35 text

FirStatusTransformerExtension 35 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS class A open class A

Slide 36

Slide 36 text

FirDeclarationGenerationExtension 36 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS class A class A { companion object { ... } fun hoge() }

Slide 37

Slide 37 text

FirAdditionalCheckersExtension 37 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS Resolved FIR Checker RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS FIR CheckerΛ௥Ճ

Slide 38

Slide 38 text

FirExtension Architecture

Slide 39

Slide 39 text

FirExtension Architecture 39 FirSession FirSessionComponent … FirExtension

Slide 40

Slide 40 text

FirExtension 40 abstract class FirExtension( val session: FirSession ) { ... } FirSession FirSessionComponent … FirExtension શͯͷFIR֦ுͷجఈΫϥεͰ FirSession ΁ͷࢀরΛ࣋ͭ

Slide 41

Slide 41 text

FirSession 41 abstract class FirSession @PrivateSessionConstructor constructor( val sessionProvider: FirSessionProvider?, val kind: Kind ) : ComponentArrayOwner() { // ... } FirSession FirSessionComponent … FirExtension • FIRίϯύΠϧηογϣϯͷ؅ཧ୯Ґ • FirSessionComponentΛଋͶ͍ͯΔ

Slide 42

Slide 42 text

FirSessionComponent 42 interface FirSessionComponent val FirSession.firProvider: FirProvider by FirSession.sessionComponentAccessor() FIR֦ுͷ࣮૷ʹඞཁͳ৘ใΛఏڙ • FirProvider • FirSymbolProvider • … FirSession FirSessionComponent … FirExtension

Slide 43

Slide 43 text

FirExtensionͱPredicate

Slide 44

Slide 44 text

FirExtension ͱ Predicate • શͯͷFIR֦ு͸ʮPredicateʯΛج࣠ʹઃܭ • Predicate ≒ γϯϘϧͷϚονϯάύλʔϯ • ΞϊςʔγϣϯΛϕʔεʹॲཧର৅Λಛఆ • Ϣʔβʔ͕FIRίϯύΠϥʹࢦࣔΛग़͢།Ұͷʢਖ਼ࣜͳʣํ๏ 44 abstract class FirExtension(val session: FirSession) { open fun FirDeclarationPredicateRegistrar.registerPredicates() {} }

Slide 45

Slide 45 text

2छྨͷPredicate • LookupPredicate Ϛον͢ΔγϯϘϧϦετΛฦ٫ • DeclarationPredicate એݴ͕Ϛον͢Δ͔൑ఆ (true or false) • ಺෦తͳ࢖ΘΕํ͕एׯҟͳΔ͚ͩͰେ͖ͳҧ͍͸ͳ͍ • DeclarationPredicate Λ࢖͏͜ͱ͕ଟ͍ 45

Slide 46

Slide 46 text

Predicateʹ࢖͑Δύλʔϯ 46 @Marker class A { fun b() } annotated(FqName("Marker")) parentAnnotated(FqName("Marker"))

Slide 47

Slide 47 text

Predicateʹ࢖͑Δύλʔϯ 47 @Marker class A { fun b() } annotatedOrUnder(FqName("Marker")) annotated(FqName("Marker")) parentAnnotated(FqName("Marker"))

Slide 48

Slide 48 text

Predicate͸Annotationϕʔε

Slide 49

Slide 49 text

Q: ௨ৗͷΞϊςʔγϣϯ͕ղܾ͞ΕΔϑΣʔζ͸ʁ 49 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 50

Slide 50 text

Q: ௨ৗͷΞϊςʔγϣϯ͕ղܾ͞ΕΔϑΣʔζ͸ʁ 50 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS ͜͜Ͱ͢ʂ

Slide 51

Slide 51 text

Q: FIR֦ு͕ؔ࿈͢ΔϑΣʔζ͸ʁ 51 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 52

Slide 52 text

Q: FIR֦ு͕ؔ࿈͢ΔϑΣʔζ͸ʁ 52 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 53

Slide 53 text

Q: FIR֦ு͕ؔ࿈͢ΔϑΣʔζ͸ʁ 53 RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES STATUS EXPECT_ACTUAL_MATCHING CONTRACTS IMPLICIT_TYPES_BODY_RESOLVE CONSTANT_EVALUATION BODY_RESOLVE ANNOTATION_ARGUMENTS

Slide 54

Slide 54 text

TYPESϑΣʔζΑΓલʹ PredicateͷΞϊςʔγϣϯΛղܾ͠ͳ͍ͱ❌

Slide 55

Slide 55 text

Predicateʹؔ͢Δ஫ҙ఺ 55 • Predicate Ͱ༻͍ΔΞϊςʔγϣϯ͸
 COMPILER_REQUIRED_ANNOTATIONS Ͱ
 ղܾࡁΈͰͳ͚Ε͹ͳΒͳ͍ • FirExtension ͷ registerPredicates Λ࣮૷͠
 Predicate Λ࠷ॳʹొ࿥͓ͯ͘͠ RAW_FIR IMPORTS COMPILER_REQUIRED_ANNOTATIONS COMPANION_GENRATION SUPER_TYPES SEALED_CLASS_INHERITORS TYPES EXPEC IMPLICIT CON ANNO

Slide 56

Slide 56 text

Frontend֦ுͷ·ͱΊ • એݴͷมߋ΍௥Ճɺղੳͱ͍֦ͬͨு͕ओͱͳΔ • FirSessionΛܦ༝ͯ͠FirSessionComponent΁ΞΫηε͢Δ͜ͱͰ
 ඞཁͳ৘ใΛऔಘͰ͖Δ • Predicate͸ΞϊςʔγϣϯΛϕʔεʹͨ͠Ϛονϯάύλʔϯ • FirExtensionͷதͰ Predicate ͷࣄલొ࿥͕ඞཁ 56

Slide 57

Slide 57 text

Backend֦ுͷجૅ

Slide 58

Slide 58 text

Backend֦ுʹͰ͖Δ͜ͱ • ׬શʹ৘ใ͕ղܾ͞Εͨ IR ϊʔυΛૢ࡞ • ڀۃతʹ͸ Frontend Ͱߦ͍ͬͯΔ΄ͱΜͲͷ͜ͱΛ࣮ݱͰ͖Δ • ͨͩ͠ɺFrontendͷํ͕޲͘վมॲཧ΋͋Δ • IR্ͷվม͸ IDE Ͱೝࣝ͠ͳ͍ 58

Slide 59

Slide 59 text

IrGenerationExtension • BackendίϯύΠϥ ͷ IR ੜ੒ʹհೖ͢ΔͨΊͷ Extension • IR ϊʔυͷղੳɾੜ੒ɾม׵͕Ͱ͖Δ 59 IrGenerationExtension IrModuleFragment IrPluginContext

Slide 60

Slide 60 text

IrModuleFragment ίϯύΠϧର৅ͷϞδϡʔϧΛද͢IRͷج఺ϊʔυ 60 IrSimpleFunction ... ... ... ... IrFile IrFile IrFile IrModuleFragment

Slide 61

Slide 61 text

IrPluginContext IRͷૢ࡞ʹ໾ཱͭػೳΛఏڙ • ֤छ IrSymbol ΁ͷΞΫηε • referenceClass • referenceFunctions • referenceProperties • referenceConstructors • … • irFactory, irBuiltIns ͳͲIRվมʹ໾ཱͭίϯϙʔωϯτΛ࣋ͭ 61

Slide 62

Slide 62 text

IRϊʔυͷղੳ • IrElementVisitor Λ༻͍ͯ
 ֤छ IRϊʔυΛ๚໰Ͱ͖Δ 62 IrClass IrSimpleFunction IrFile IrModuleFragment visitFile visitClass visitSimpleFunction IrFile IrProperty … …

Slide 63

Slide 63 text

IRϊʔυͷม׵ • IrElementTransformer Λ༻͍ͯ
 ֤छIRϊʔυΛม׵Ͱ͖Δ • ๚໰தϊʔυΑΓԼͷ֊૚ʹ͋Δ IRϊʔυΛมߋՄೳ 63 IrProperty IrClass IrSimpleFunction IrFile IrModuleFragment visitClass IrFile IrProperty … … ௥Ճ!!

Slide 64

Slide 64 text

Backend֦ுͷ·ͱΊ • ར༻Ͱ͖Δ֦ு͸ IrGenerationExtension • IrModuleFragment = ϞδϡʔϧͷIRج఺ϊʔυ • IrPluginContext = IRվมʹศརͳػೳΛఏڙ • IRͷղੳʹ͸ IrElementVisitor Λ࢖͏ • IRͷվมʹ͸ IrElementTransformer Λ࢖͏ 64

Slide 65

Slide 65 text

࡞Γͳ͕Βཧղ͢Δ Kotlin Compiler Plugin

Slide 66

Slide 66 text

Plugin Architecture

Slide 67

Slide 67 text

Plugin Architecture 67 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin

Slide 68

Slide 68 text

Plugin Architecture 68 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin

Slide 69

Slide 69 text

Plugin Architecture 69 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin Gradle Extension ↓ SubpluginOption

Slide 70

Slide 70 text

Plugin Architecture 70 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin -P plugin:pluginId:key=value

Slide 71

Slide 71 text

Plugin Architecture 71 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin -P plugin:pluginId:key=value ↓ CompilerCon fi guration

Slide 72

Slide 72 text

Plugin Architecture 72 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin Extensionͷొ࿥ ※CompilerCon fi guration΁ΞΫηεՄೳ

Slide 73

Slide 73 text

Plugin Architecture 73 CompilerPluginRegistrar Extension { Extension CommandLineProcessor KotlinCompilerPluginSupportPlugin ίʔυͷվมॲཧ

Slide 74

Slide 74 text

ຊηογϣϯͰΧόʔ͢ΔྖҬʢ࠷খߏ੒ʣ 74 CompilerPluginRegistrar Extension { Extension

Slide 75

Slide 75 text

ࠓճ࡞ΔίϯύΠϥϓϥάΠϯ

Slide 76

Slide 76 text

Greeting Compiler Plugin ΞϊςʔγϣϯΛ෇༩ͨ͠Ϋϥε͕ݩؾΑ͘ѫࡰͰ͖ΔΑ͏ʹͳΓ·͢ɻ 76 @Greetable class A val a = A() a.greet("ੈք") // Aʮ͜Μʹͪ͸ɺੈքʂʯ

Slide 77

Slide 77 text

The Inside of Greeting Compiler Plugin 77 class LovelyClass

Slide 78

Slide 78 text

The Inside of Greeting Compiler Plugin 78 @Greetable class LovelyClass

Slide 79

Slide 79 text

The Inside of Greeting Compiler Plugin 79 @Greetable class LovelyClass { fun greet(name: String) } FIR֦ுͰੜ੒

Slide 80

Slide 80 text

The Inside of Greeting Compiler Plugin 80 @Greetable class LovelyClass { fun greet(name: String) { println("LovelyClassʮ͜Μʹͪ͸ɺ$nameʂʯ") } } IR֦ுͰੜ੒

Slide 81

Slide 81 text

ϓϩδΣΫτશମͷߏ੒ 81 greeting-plugin (root) greeting-annotations Ξϊςʔγϣϯ༻Ϟδϡʔϧ greeting-compiler ίϯύΠϥϓϥάΠϯ test ݕূ༻Ϟδϡʔϧ

Slide 82

Slide 82 text

ϓϩδΣΫτશମͷϏϧυઃఆ 82 // settings.gradle.kts dependencyResolutionManagement { repositories { mavenCentral() } } include(":greeting-annotations") include(":greeting-compiler") include(":test") // build.gradle.kts (project root) plugins { kotlin("jvm") version "2.0.0" apply false } greeting-plugin build.gradle.kts settings.gradle.kts

Slide 83

Slide 83 text

83 plugins { kotlin("jvm") } … greeting-annotations build.gradle.kts ϥΠϒϥϦϞδϡʔϧͷϏϧυઃఆ ( :greeting-annotations ) greeting-plugin

Slide 84

Slide 84 text

… ίϯύΠϥϓϥάΠϯͷϏϧυઃఆ ( :greeting-compiler ) 84 plugins { kotlin("jvm") } dependencies { implementation( kotlin("compiler-embeddable") ) } greeting-compiler build.gradle.kts greeting-annotations greeting-plugin

Slide 85

Slide 85 text

ϓϥάΠϯݕূ༻ϞδϡʔϧͷϏϧυઃఆ ( :test ) 85 plugins { kotlin("jvm") } dependencies { testImplementation(kotlin("test")) testCompileOnly( project(":greeting-annotations") ) kotlinCompilerPluginClasspath( project(":greeting-compiler") ) } build.gradle.kts test … greeting-compiler greeting-annotations greeting-plugin

Slide 86

Slide 86 text

ϥΠϒϥϦϞδϡʔϧͷ࣮૷

Slide 87

Slide 87 text

ϥΠϒϥϦϞδϡʔϧͷ࣮૷ ʢ :greeting-annotations ) 87 package greeting.annotations @Target(AnnotationTarget.CLASS) annotation class Greetable greeting-annotations src/main/kotlin greeting.annotations Greetable.kt

Slide 88

Slide 88 text

Frontend֦ுͷ࣮૷

Slide 89

Slide 89 text

FIR֦ுͰߦ͏͜ͱ 89 @Greetable class LovelyClass { fun greet(name: String) } ؔ਺એݴͷੜ੒

Slide 90

Slide 90 text

FIR֦ுͰ࣮૷Λߦ͏ϑΝΠϧ 90 greeting-compiler src/main/kotlin greeting.compiler. fi r GreetablePredicate.kt GreetingFirDeclarationGenerationExtension.kt GreetingDeclarationKey.kt

Slide 91

Slide 91 text

package greeting.compiler.fir val greetablePredicate = DeclarationPredicate.create { annotated(FqName("greeting.annotations.Greetable")) } Predicateͷఆٛ 91 greeting-compiler src/main/kotlin greeting.compiler. fi r GreetablePredicate.kt

Slide 92

Slide 92 text

FIRͰੜ੒͞Εͨએݴʹࢦఆ͢ΔDeclarationKeyͷఆٛ 92 package greeting.compiler.fir object GreetingDeclarationKey : GeneratedDeclarationKey() greeting-compiler src/main/kotlin greeting.compiler. fi r GreetingDeclarationKey.kt

Slide 93

Slide 93 text

FirDeclarationGenerationExtension • એݴͷੜ੒Λߦ͏Extension • ੜ੒͢Δએݴ໊/IDͷऔಘ → get…Names/get…Ids • એݴͷੜ੒ॲཧ → generate… 93 @Greetable class A @Greetable class A { fun greet(name: String) }

Slide 94

Slide 94 text

class GreetingFirDeclarationGenerationExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { override fun getCallableNamesForClass( classSymbol: FirClassSymbol <*> , context: MemberGenerationContext ): Set = TODO() override fun generateFunctions( callableId: CallableId, context: MemberGenerationContext? ): List = TODO() } 94 Name.identi er("greet") Λฦ͢ fun greet(name: String): String Λੜ੒

Slide 95

Slide 95 text

class GreetingFirDeclarationGenerationExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { override fun getCallableNamesForClass( classSymbol: FirClassSymbol <* > , context: MemberGenerationContext ): Set { if (session.predicateBasedProvider.matches(greetablePredicate, classSymbol)) { return setOf(Name.identifier("greet")) } return emptySet() } // .. . } 95 @Greetable class A

Slide 96

Slide 96 text

class GreetingFirDeclarationGenerationExtension(session: FirSession) : … { override fun getCallableNamesForClass( ... ) : Set { .. . } override fun generateFunctions( callableId: CallableId, context: MemberGenerationContext? ): List { return listOf( createMemberFunction( owner = context ? . owner ?: return emptyList(), key = GreetingDeclarationKey, name = callableId.callableName, returnType = session.builtinTypes.unitType.type, config = { valueParameter(Name.identifier("name"), session.builtinTypes.stringType.type) } ).symbol ) } } 96 fun greet(name: String)

Slide 97

Slide 97 text

Predicateͷొ࿥ʢ๨Εͣʹʂʂʣ 97 class GreetingFirDeclarationGenerationExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { // . .. override fun FirDeclarationPredicateRegistrar.registerPredicates() { register(greetablePredicate) } } registerPredicates Ͱ @Greetable ͷ Predicate Λొ࿥

Slide 98

Slide 98 text

Backend֦ுͷ࣮૷

Slide 99

Slide 99 text

IR֦ுͰߦ͏͜ͱ 99 @Greetable class LovelyClass { fun greet(name: String) { println("LovelyClassʮ͜Μʹͪ͸ɺ$nameʂʯ") } } ؔ਺ຊମͷੜ੒

Slide 100

Slide 100 text

IR֦ுͰߦ͏͜ͱ 100 @Greetable class LovelyClass { fun greet(name: String) { print("LovelyClassʮ͜Μʹͪ͸ɺ") print(name) println("ʂʯ") } } IRੜ੒͠΍͍͢ܗࣜʹมߋ

Slide 101

Slide 101 text

IR֦ுͰ࣮૷Λߦ͏Ϋϥε 101 greeting-compiler src/main/kotlin greeting.compiler.ir GreetingIrElementTransformer.kt GreetingIrGenerationExtension.kt

Slide 102

Slide 102 text

IrGenerationExtension ͷ࣮૷ 102 package greeting.compiler.ir class GreetingIrGenerationExtension() : IrGenerationExtension { // ... } greeting-compiler src/main/kotlin greeting.compiler.ir GreetingIrGenerationExtension.kt

Slide 103

Slide 103 text

IrGenerationExtension ͷ࣮૷ 103 package greeting.compiler.ir class GreetingIrGenerationExtension() : IrGenerationExtension { override fun generate( moduleFragment: IrModuleFragment, pluginContext: IrPluginContext ) { moduleFragment.transformChildrenVoid( GreetingIrElementTransformer(pluginContext) ) } }

Slide 104

Slide 104 text

IrElementTransformerVoid ͷ࣮૷ 104 package greeting.compiler.ir class GreetingIrElementTransformer( private val pluginContext: IrPluginContext ) : IrElementTransformerVoid()

Slide 105

Slide 105 text

IrElementTransformerVoid ͷ࣮૷ 105 package greeting.compiler.ir class GreetingIrElementTransformer( private val pluginContext: IrPluginContext ) : IrElementTransformerVoid() { private val printFunctionSymbol: IrSimpleFunctionSymbol = TODO() private val printlnFunctionSymbol: IrSimpleFunctionSymbol = TODO() override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement = TODO() }

Slide 106

Slide 106 text

IrElementTransformerVoid ͷ࣮૷ 106 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { private val printFunctionSymbol = pluginContext.referenceFunctions( CallableId(FqName("kotlin.io"), Name.identifier("print")) ) ... // . .. }

Slide 107

Slide 107 text

IrElementTransformerVoid ͷ࣮૷ 107 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { private val printFunctionSymbol = pluginContext.referenceFunctions( CallableId(FqName("kotlin.io"), Name.identifier("print")) ).single { it.owner.valueParameters.singleOrNull() ? . type == pluginContext.irBuiltIns.anyNType } // . .. }

Slide 108

Slide 108 text

IrElementTransformerVoid ͷ࣮૷ 108 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { private val printFunctionSymbol = pluginContext.referenceFunctions( CallableId(FqName("kotlin.io"), Name.identifier("print")) ).single { it.owner.valueParameters.singleOrNull() ? . type == pluginContext.irBuiltIns.anyNType } private val printlnFunctionSymbol = pluginContext.referenceFunctions( CallableId(FqName("kotlin.io"), Name.identifier("println")) ).single { it.owner.valueParameters.singleOrNull() ? . type == pluginContext.irBuiltIns.anyNType } … }

Slide 109

Slide 109 text

IrElementTransformerVoid ͷ࣮૷ 109 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { private val printFunctionSymbol = … ✅ private val printlnFunctionSymbol = … ✅ // TODO: FIRͰੜ੒ͨ͠એݴͷຊମΛੜ੒ override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement = TODO() }

Slide 110

Slide 110 text

110 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // . .. override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { } } // TODO1: ؔ܎ͷͳ͍ؔ਺Λແࢹ // TODO2: greetؔ਺ͷbodyΛੜ੒

Slide 111

Slide 111 text

111 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // . .. override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { // TODO1: ؔ܎ͷͳ͍ؔ਺Λແࢹ val origin = declaration.origin as? IrDeclarationOrigin.GeneratedByPlugin if (origin ? . pluginKey !is GreetingDeclarationKey) return declaration // ... } } Fir֦ுͰੜ੒ͨ͠ DeclarationKey 
 Λ͍࣋ͬͯΔ͔νΣοΫ

Slide 112

Slide 112 text

112 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // .. . override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { / / . .. / / TODO2: greetؔ਺ͷbodyͷੜ੒ val irBuilder = pluginContext.irBuiltIns.createIrBuilder(declaration.symbol) declaration.body = irBuilder.irBlockBody { // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") // print(name) // println("ʂʯ") } return declaration } }

Slide 113

Slide 113 text

113 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // .. . override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { / / . .. / / TODO2: greetؔ਺ͷbodyͷੜ੒ val irBuilder = pluginContext.irBuiltIns.createIrBuilder(declaration.symbol) declaration.body = irBuilder.irBlockBody { // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") // print(name) // println("ʂʯ") } return declaration } }

Slide 114

Slide 114 text

114 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // .. . override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { / / . .. / / TODO2: greetؔ਺ͷbodyͷੜ੒ val irBuilder = pluginContext.irBuiltIns.createIrBuilder(declaration.symbol) declaration.body = irBuilder.irBlockBody { // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") // print(name) // println("ʂʯ") } return declaration } }

Slide 115

Slide 115 text

115 class GreetingIrElementTransformer(…) : IrElementTransformerVoid() { // ... override fun visitSimpleFunction(declaration: IrSimpleFunction) : IrStatement { // . . . val irBuilder = pluginContext.irBuiltIns.createIrBuilder(declaration.symbol) val parentClassName = declaration.parentClassOrNull ?. kotlinFqName ? . asString() declaration.body = irBuilder.irBlockBody { +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) } } return declaration } }

Slide 116

Slide 116 text

116 // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } // print(name) +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } // println("ʂʯ") +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) }

Slide 117

Slide 117 text

117 // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } // print(name) +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } // println("ʂʯ") +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) }

Slide 118

Slide 118 text

118 // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } // print(name) +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } // println("ʂʯ") +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) }

Slide 119

Slide 119 text

119 // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } // print(name) +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } // println("ʂʯ") +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) }

Slide 120

Slide 120 text

120 // print("Ϋϥε໊ʮ͜Μʹͪ͸ɺ") +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("$parentClassNameʮ͜Μʹͪ͸ɺ")) } // print(name) +irCall(printFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irGet(declaration.valueParameters.single())) } // println("ʂʯ") +irCall(printlnFunctionSymbol).apply { putValueArgument(index = 0, valueArgument = irString("ʂʯ")) }

Slide 121

Slide 121 text

Extensionͷ࣮૷͸׬ྃ 121 CompilerPluginRegistrar Extension { Extension

Slide 122

Slide 122 text

ίϯύΠϥ֦ுͷొ࿥ 122 CompilerPluginRegistrar Extension { Extension

Slide 123

Slide 123 text

CompilerPluginRegistrar ֤छ Extension Λొ࿥͢ΔαʔϏε 123 CompilerPluginRegistrar FirExtensionRegistrar IrGenerationExtension FirExtension FirExtension … CompilerCon fi guration get(…) FirExtensionRegistrarAdapter registerExtension(…) registerExtension(…)

Slide 124

Slide 124 text

CompilerPluginRegistrar ͷ࣮૷ ( :greeting-compiler ) 124 package greeting.compiler class GreetingCompilerPluginRegistrar : CompilerPluginRegistrar() { override val supportsK2: Boolean = true override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { FirExtensionRegistrarAdapter.registerExtension(TODO()) IrGenerationExtension.registerExtension(TODO()) } }

Slide 125

Slide 125 text

CompilerPluginRegistrar ͷ࣮૷ ( :greeting-compiler ) 125 package greeting.compiler class GreetingCompilerPluginRegistrar : CompilerPluginRegistrar() { override val supportsK2: Boolean = true override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { FirExtensionRegistrarAdapter.registerExtension(TODO()) IrGenerationExtension.registerExtension(TODO()) } }

Slide 126

Slide 126 text

CompilerPluginRegistrar ͷ࣮૷ ( :greeting-compiler ) 126 package greeting.compiler class GreetingCompilerPluginRegistrar : CompilerPluginRegistrar() { override val supportsK2: Boolean = true override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { FirExtensionRegistrarAdapter.registerExtension(TODO()) IrGenerationExtension.registerExtension(TODO()) } }

Slide 127

Slide 127 text

CompilerPluginRegistrar ͷ࣮૷ ( :greeting-compiler ) 127 package greeting.compiler class GreetingCompilerPluginRegistrar : CompilerPluginRegistrar() { override val supportsK2: Boolean = true override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { FirExtensionRegistrarAdapter.registerExtension(TODO()) IrGenerationExtension.registerExtension(GreetingIrGenerationExtension()) } }

Slide 128

Slide 128 text

CompilerPluginRegistrar ͷ࣮૷ ( :greeting-compiler ) 128 class GreetingCompilerPluginRegistrar : CompilerPluginRegistrar() { override val supportsK2: Boolean = true override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { FirExtensionRegistrarAdapter.registerExtension( GreetingFirExtensionRegistrar() ) IrGenerationExtension.registerExtension(GreetingIrGenerationExtension()) } }

Slide 129

Slide 129 text

FirExtensionRegistrar ʢFIR֦ுͷొ࿥ʣ 129 package greeting.compiler.fir class GreetingFirExtensionRegistrar : FirExtensionRegistrar() { // ֤छFIRͷϑΝΫτϦʔΛ + :: Λ࢖ͬͯొ࿥ override fun ExtensionRegistrarContext.configurePlugin() { + :: GreetingFirDeclarationGenerationExtension } }

Slide 130

Slide 130 text

130 META-INF/services΁ͷఆٛ greeting-compiler src/main/resources META-INF services org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar greeting.compiler.GreetingCompilerPluginRegistrar ⚠͜Ε͕ͳ͍ͱಈ࡞͠ͳ͍ͨΊ஫ҙ

Slide 131

Slide 131 text

ϓϥάΠϯͷݕূ

Slide 132

Slide 132 text

ςετΛॻ͍ͯΈΑ͏ʢ :test ʣ 132 package greeting.test @Greetable class LovelyClass class GreetingTest { @Test fun test() { val lovelyClass = LovelyClass() lovelyClass.greet(name = "ੈք") } }

Slide 133

Slide 133 text

ςετΛॻ͍ͯΈΑ͏ʢ :test ʣ 133

Slide 134

Slide 134 text

Kotlin Compiler Pluginͷ׆༻ྫ

Slide 135

Slide 135 text

͋Ε΋͜Ε΋ Kotlin Compiler Plugin • Compose Compiler • KSP (Kotlin Symbol Processing) • kotlinx.serialization • Detekt • Kapt • … 135

Slide 136

Slide 136 text

back-in-time-plugin

Slide 137

Slide 137 text

back-in-time-plugin ίϯύΠϧλΠϜʹTTDʢTime Travel Debuggingʣ༻ͷίʔυΛૠೖ 137 Compile time Source Kotlin Compiler Plugin Target Code
 (with TTD code)

Slide 138

Slide 138 text

TTDʢTime Travel Debuggingʣʹ͍ͭͯ ϓϩάϥϜͷ಺෦ঢ়ଶΛΩϟϓνϟ͓͖ͯ͠
 աڈͷঢ়ଶΛ܁Γฦ͠࠶ݱ͢Δσόοάख๏ 138 var counter: Int 0 1 2 3 Time Travel

Slide 139

Slide 139 text

back-in-time-pluginͷ࢓૊Έ 139 Runtime App Debugger ঢ়ଶมߋͷ௨஌ ঢ়ଶͷר͖໭͠ཁٻ Compile time Source Kotlin Compiler Plugin Target Code
 (with TTD code) ঢ়ଶมߋͷ௥੻ ঢ়ଶר͖໭͠༻ؔ਺ͷੜ੒

Slide 140

Slide 140 text

back-in-time-plugin Λ࢖͏ͨΊʹඞཁͳ͜ͱ 140 @BackInTime class CounterViewModel : ViewModel() { var counter by mutableIntStateOf(0) private set fun increment(amount: Int) { counter += amount } }

Slide 141

Slide 141 text

DEMO 141

Slide 142

Slide 142 text

back-in-time-plugin • https://github.com/kitakkun/back-in-time-plugin • KMPରԠத • ௨৴෦෼Λ Flipper ͔Β Ktor ͷϐϡΞͳ WebSocket ΁มߋ • σόοΨ࣮૷Λ Flipper Plugin ͔Β Compose ΞϓϦ΁มߋ 142

Slide 143

Slide 143 text

ࢿྉɾϦϙδτϦ΁ͷϦϯΫ 143 https://github.com/kitakkun/greeting-plugin

Slide 144

Slide 144 text

ࢀߟจݙ • աڈηογϣϯ • KotlinConf 2018 - Writing Your First Kotlin Compiler Plugin by Kevin Most • Crash Course on the Kotlin Compiler by Amanda Hinchman-Dominguez • K2 Compiler plugins by Mikhail Glukhikh • K2΁ͷಓɻίϯύΠϥΛ࡞Γ௚ͬͯ͢Ͳ͏͍͏͜ͱʁ / Kotlin Fest 2022 • KotlinެࣜϦϙδτϦ • https://github.com/JetBrains/kotlin/blob/master/docs/ fi r/ fi r-basics.md • https://github.com/JetBrains/kotlin/blob/master/docs/ fi r/ fi r-plugins.md 144

Slide 145

Slide 145 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ