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

[After Kotlin Fest 2024 LT Night @ Sansan] もっともっとKotlinを好きになる!K2 Compiler Pluginで遊んでみよう!

[After Kotlin Fest 2024 LT Night @ Sansan] もっともっとKotlinを好きになる!K2 Compiler Pluginで遊んでみよう!

kitakkun

July 08, 2024
Tweet

More Decks by kitakkun

Other Decks in Programming

Transcript

  1. தؒදݱʢIR: Intermediate Representationʣ தؒදݱ 
 ɹ= ίϯύΠϧதͷϓϩάϥϜΛ
 ɹ໦ߏ଄Ͱදݱͨ͠΋ͷ • Frontend

    → FIR • Backend → IR 9 IrClass IrSimpleFunction IrProperty IrExpressionBody IrBlockBody IrConst IrStatement IrStatement
  2. copy ͸ private ίϯετϥΫλΛ͢Γൈ͚ΔʢBefore 2.0.20-Beta1ʣ 14 data class A private

    constructor(val a: Int) { companion object { fun create(a: Int) = A(a) } } val a = A.create(10) / / OK val b = a.copy(20) / / OK, but should be an error. ERROR❌
  3. 5छྨͷFIR Checker • એݴ FirDeclarationChecker • ࣜ FirExpressionChecker • ܕ

    FirTypeChecker • ݴޠόʔδϣϯ FirLanguageVersionSettingsChecker • ੍ޚϑϩʔ FirControlFlowChecker 15 ίϯύΠϥ֦ு
 Մೳͳ΋ͷ
  4. 5छྨͷFIR Checker • એݴ FirDeclarationChecker • ࣜ FirExpressionChecker • ܕ

    FirTypeChecker • ݴޠόʔδϣϯ FirLanguageVersionSettingsChecker • ੍ޚϑϩʔ FirControlFlowChecker 16 ίϯύΠϥ֦ு
 Մೳͳ΋ͷ
  5. copy Λݕࠪ͢Δ FirFunctionCallChecker 18 object NoCopyFirFunctionCallChecker : FirFunctionCallChecker(…) { override

    fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter, ) { / / TODO: privateίϯετϥΫλͷΫϥεͷcopy࢖༻Λݕग़ } }
  6. copy Λݕࠪ͢Δ FirFunctionCallChecker 19 override fun check( expression: FirFunctionCall, context:

    CheckerContext, reporter: DiagnosticReporter, ) { // TODO1: copyҎ֎ͷؔ਺ݺͼग़͠Λআ֎ // TODO2: data class Ҏ֎Λআ֎ // TODO3: constructor ͕ private Ͱͳ͍΋ͷΛআ֎ // TODO4: copy ͷ࢖༻ՕॴΛΤϥʔใࠂ }
  7. 20 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // TODO1: copyҎ֎ͷؔ਺ݺͼग़͠Λআ֎ if (expression.calleeReference.name != Name.identifier("copy")) { return } // . .. }
  8. 21 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // copyҎ֎ͷؔ਺ݺͼग़͠Λআ֎ ✅ // TODO2: data class Ҏ֎Λআ֎ val classSymbol = expression.resolvedType .toRegularClassSymbol(context.session) ? : return if (!classSymbol.isData) return // .. . }
  9. 22 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // copyҎ֎ͷؔ਺ݺͼग़͠Λআ֎ ✅ // data class Ҏ֎Λআ֎ ✅ // TODO3: constructor ͕ private Ͱͳ͍΋ͷΛআ֎ val constructorVisibility = classSymbol .primaryConstructorSymbol(context.session) .visibility ? : return if (constructorVisibility ! = Visibilities.Private) return // … }
  10. 23 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // copyҎ֎ͷؔ਺ݺͼग़͠Λআ֎ ✅ // data class Ҏ֎Λআ֎ ✅ // constructor ͕ private Ͱͳ͍΋ͷΛআ֎ ✅ // TODO4: copy ͷ࢖༻ՕॴΛΤϥʔใࠂ }
  11. 24 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source = TODO("Ͳͷએݴʹର͢Δ΋ͷʁ"), factory = TODO("ରԠ͢ΔΤϥʔఆٛ͸ʁ"), a = TODO("Τϥʔใࠂ༻ͷ෇Ճ৘ใ") ) }
  12. DiagnosticRendererFactoryͷ࣮૷ʢΤϥʔͷදࣔํ๏ͷܾఆʣ 28 object NoCopyErrorMessages : BaseDiagnosticRendererFactory() { override val MAP

    = KtDiagnosticFactoryToRendererMap("NoCopy").apply { put( NoCopyFirErrors.COPY_CALL_FOR_DATA_CLASS_WITH_PRIVATE_CONSTRUCTOR, "data class {0} has a private constructor." + "The use of copy method is not allowed", rendererA = TO_STRING, ) } }
  13. 29 override fun check( expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter,

    ) { // TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source = TODO("Ͳͷએݴʹର͢Δ΋ͷʁ"), factory = TODO("ରԠ͢ΔΤϥʔఆٛ͸ʁ"), a = TODO("Τϥʔใࠂ༻ͷ෇Ճ৘ใ") ) }
  14. 30 / / TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source

    = TODO("Ͳͷએݴʹର͢Δ΋ͷʁ"), factory = TODO("ରԠ͢ΔΤϥʔఆٛ͸ʁ"), a = TODO("Τϥʔใࠂ༻ͷ෇Ճ৘ใ") )
  15. 31 / / TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source

    = expression.calleeReference.source, factory = TODO("ରԠ͢ΔΤϥʔఆٛ͸ʁ"), a = TODO("Τϥʔใࠂ༻ͷ෇Ճ৘ใ") )
  16. 32 // TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source =

    expression.calleeReference.source, factory = NoCopyFirErrors. COPY_CALL_FOR_DATA_CLASS_WITH_PRIVATE_CONSTRUCTOR, a = TODO("Τϥʔใࠂ༻ͷ෇Ճ৘ใ") )
  17. 33 // TODO4: copyͷ࢖༻ՕॴΛΤϥʔใࠂ reporter.reportOn( context = context, source =

    expression.calleeReference.source, factory = NoCopyFirErrors. COPY_CALL_FOR_DATA_CLASS_WITH_PRIVATE_CONSTRUCTOR, a = classSymbol.classId.asString() )
  18. 37

  19. ࢀߟจݙ • νΣοΧʔΛ௥Ճ͢ΔFIR֦ு • https://github.com/JetBrains/kotlin/blob/master/docs/ fi r/ fi r- plugins.md#

    fi radditionalcheckersextension • FIRνΣοΧʔͷࡉ͔͍࢓༷ • https://github.com/JetBrains/kotlin/blob/master/compiler/ fi r/checkers/ module.md 38