/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 2 1 ĠJetBrains Ġs . r . o . Ġand ĠKotlin ĠProgramming ĠLanguage Ġcontributors . Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe Ġlicense / LICENSE . txt Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . incremental . classpath Diff Ċ Ċ import Ġorg . jetbrains . kotlin . incremental . classpath Diff . Class Snapshot Gran ularity . CLASS _ MEMBER _ LEVEL Ċ import Ġorg . jetbrains . org . object web . asm . Class Reader Ċ import Ġorg . jetbrains . org . object web . asm . Class Writer Ċ import Ġorg . jetbrains . org . object web . asm . Op codes Ċ import Ġorg . jetbrains . org . object web . asm . tree . Class Node Ċ import Ġorg . jetbrains . org . object web . asm . tree . Field Node Ċ import Ġorg . jetbrains . org . object web . asm . tree . Method Node Ċ Ċ /** ĠComputes Ġa Ġ[ Java Class Snapshot ] Ġof Ġa ĠJava Ġclass . Ġ*/ Ċ object ĠJava Class Snapshot ter Ġ{ ĊĊĠĠĠ Ġfun Ġsnapshot ( class File : ĠClass File With Contents , Ġgranularity : ĠClass Snapshot Gran ularity ): ĠJava Class Snapshot Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġwill Ġextract ĠABI Ġinformation Ġfrom Ġthe Ġgiven Ġclass Ġand Ġstore Ġit Ġinto Ġthe Ġ` abi Class ` Ġvariable . ĊĠĠĠĠĠĠĠ Ġ// ĠIt Ġis Ġacceptable Ġto Ġcollect Ġmore Ġinfo Ġthan Ġrequired , Ġbut Ġit Ġis Ġincorrect Ġto Ġcollect Ġless Ġinfo Ġthan Ġrequired . ĊĠĠĠĠĠĠĠ Ġ// ĠThere Ġare Ġ 2 Ġapproaches : ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠ 1 . ĠCollect ĠABI Ġinfo Ġdirectly . ĠThe Ġcollected Ġinfo Ġmust Ġbe Ġex haustive Ġ( now Ġand Ġin Ġthe Ġfuture Ġwhen Ġthere Ġare Ġupdates Ġto ĠJava / ASM ). ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠ 2 . ĠCollect Ġall Ġinfo Ġand Ġremove Ġnon - ABI Ġinfo . ĠThe Ġremoved Ġinfo Ġshould Ġbe Ġex haustive , Ġbut Ġeven Ġif Ġit 's Ġnot , Ġit Ġis Ġstill ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠ Ġacceptable . ĊĠĠĠĠĠĠĠ Ġ// ĠIn Ġthe Ġfollowing , Ġwe Ġwill Ġuse Ġthe Ġsecond Ġapproach Ġas Ġit Ġis Ġsa fer . ĊĠĠĠĠĠĠĠ Ġval Ġabi Class Ġ= ĠClass Node () ĊĊĠĠĠĠĠĠĠ Ġ// ĠFirst , Ġcollect Ġall Ġinfo . ĊĠĠĠĠĠĠĠ Ġ// ĠNote Ġthe Ġparsing Ġoptions Ġpassed Ġto ĠClass Reader : ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠSKIP _ CODE Ġand ĠSKIP _ FR AMES Ġare Ġset Ġas Ġmethod Ġbodies Ġwill Ġnot Ġbe Ġpart Ġof Ġthe ĠABI Ġof Ġthe Ġclass . ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠSKIP _ DEBUG Ġis Ġnot Ġset Ġas Ġit Ġwould Ġskip Ġmethod Ġparameters , Ġwhich Ġmay Ġbe Ġused Ġby Ġannotation Ġprocessors Ġlike ĠRoom . ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠEXP AND _ FR AMES Ġis Ġnot Ġneeded Ġ( and Ġnot Ġrelevant Ġwhen ĠSKIP _ CODE Ġis Ġset ). ĊĠĠĠĠĠĠĠ Ġval Ġclass Reader Ġ= ĠClass Reader ( class File . contents ) ĊĠĠĠĠĠĠĠ Ġclass Reader . accept ( abi Class , ĠClass Reader . SKIP _ CODE Ġor ĠClass Reader . SKIP _ FR AMES ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠThen , Ġremove Ġnon - ABI Ġinfo , Ġwhich Ġincludes : ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠMethod Ġbodies : ĠShould Ġhave Ġalready Ġbeen Ġremoved Ġ( see ĠSKIP _ CODE Ġabove ) ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠPrivate Ġfields Ġand Ġmethods ĊĠĠĠĠĠĠĠ Ġfun ĠInt . is Private () Ġ= Ġ( this Ġand ĠOp codes . ACC _ PRIVATE ) Ġ!= Ġ 0 ĊĠĠĠĠĠĠĠ Ġabi Class . fields . remove If Ġ{ Ġit . access . is Private () Ġ} ĊĠĠĠĠĠĠĠ Ġabi Class . methods . remove If Ġ{ Ġit . access . is Private () Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠNormalize Ġthe Ġclass : ĠSort Ġfields Ġand Ġmethods Ġas Ġtheir Ġorder Ġis Ġnot Ġimportant Ġ( we Ġstill Ġuse ĠList Ġinstead Ġof ĠSet Ġas Ġwe Ġwant Ġthe ĊĠĠĠĠĠĠĠ Ġ// Ġserialized Ġsnapshot Ġto Ġbe Ġdeterministic ). ĊĠĠĠĠĠĠĠ Ġabi Class . fields . sort With ( compare By ({ Ġit . name Ġ}, Ġ{ Ġit . desc Ġ})) ĊĠĠĠĠĠĠĠ Ġabi Class . methods . sort With ( compare By ({ Ġit . name Ġ}, Ġ{ Ġit . desc Ġ})) ĊĊĠĠĠĠĠĠĠ Ġ// ĠSnapshot Ġthe Ġclass ĊĠĠĠĠĠĠĠ Ġval Ġclass Ab i Hash Ġ= Ġsnapshot Class ( abi Class ) ĊĠĠĠĠĠĠĠ Ġval Ġclass Member Level Snapshot Ġ= Ġif Ġ( gran ularity Ġ== ĠCLASS _ MEMBER _ LEVEL ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfields Ab i Ġ= Ġabi Class . fields . map Ġ{ ĠJava Element Snapshot ( it . name , Ġsnapshot Field ( it )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmethods Ab i Ġ= Ġabi Class . methods . map Ġ{ ĠJava Element Snapshot ( it . name , Ġsnapshot Method ( it )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Ab i Ex cluding Members Ġ= Ġabi Class . let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . fields . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . methods . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠJava Element Snapshot ( it . name , Ġsnapshot Class ( it )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠJava Class Member Level Snapshot ( class Ab i Ex cluding Members , Ġfields Ab i , Ġmethods Ab i ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĊĠĠĠĠĠĠĠ Ġreturn ĠJava Class Snapshot ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Id Ġ= Ġclass File . class Info . class Id , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Ab i Hash Ġ= Ġclass Ab i Hash , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Member Level Snapshot Ġ= Ġclass Member Level Snapshot , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsup ert ypes Ġ= Ġclass File . class Info . sup ert ypes ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsnapshot Class ( class Node : ĠClass Node ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġclass Writer Ġ= ĠClass Writer ( 0 ) ĊĠĠĠĠĠĠĠ Ġclass Node . accept ( class Writer ) ĊĠĠĠĠĠĠĠ Ġreturn Ġclass Writer . toByteArray (). hash To Long () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsnapshot Field ( field Node : ĠField Node ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġclass Node Ġ= Ġempty Class () ĊĠĠĠĠĠĠĠ Ġclass Node . fields . add ( field Node ) ĊĠĠĠĠĠĠĠ Ġreturn Ġsnapshot Class ( class Node ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsnapshot Method ( method Node : ĠMethod Node ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġclass Node Ġ= Ġempty Class () ĊĠĠĠĠĠĠĠ Ġclass Node . methods . add ( method Node ) ĊĠĠĠĠĠĠĠ Ġreturn Ġsnapshot Class ( class Node ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġempty Class () Ġ= ĠClass Node (). also Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġneed Ġto Ġprovide Ġsome Ġminimal Ġinfo Ġto Ġthe Ġclass : ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠName Ġis Ġrequired . ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠClass Ġversion Ġis Ġrequired Ġif Ġmethod Ġbodies Ġare Ġconsidered , Ġbut Ġwe Ġhave Ġremoved Ġmethod Ġbodies Ġin Ġthis Ġclass , Ġso Ġit 's Ġoptional . ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġ- ĠOther Ġinfo Ġis Ġoptional . ĊĠĠĠĠĠĠĠ Ġit . name Ġ= Ġ" Empty Class " ĊĠĠĠ Ġ} Ċ } Ċ