package Ġorg . jetbrains . kotlin . ab icmp . tasks Ċ Ċ import Ġorg . jetbrains . kotlin . ab icmp . check ers . is Sam Adapter Name Ċ import Ġorg . jetbrains . kotlin . ab icmp . class Flags Ċ import Ġorg . jetbrains . kotlin . ab icmp . is Synt hetic Ċ import Ġorg . jetbrains . kotlin . ab icmp . listOf NotNull Ċ import Ġorg . jetbrains . kotlin . ab icmp . reports . Jar Report Ċ import Ġorg . jetbrains . kotlin . ab icmp . reports . REPORT _ CSS Ċ import Ġorg . jetbrains . kotlin . ab icmp . reports . isNotEmpty Ċ import Ġorg . jetbrains . kotlin . ab icmp . tag Ċ import Ġorg . object web . asm . Class Reader Ċ import Ġorg . object web . asm . tree . Class Node Ċ import Ġorg . object web . asm . tree . Inner Class Node Ċ import Ġjava . io . File Ċ import Ġjava . io . InputStream Ċ import Ġjava . io . PrintWriter Ċ import Ġjava . util . jar . Jar File Ċ import Ġorg . apache . log 4 j . Logger Ċ Ċ class ĠJar Task ( ĊĠĠĠ Ġheader : ĠString , ĊĠĠĠ Ġprivate Ġval Ġjar File 1 : ĠJar File , ĊĠĠĠ Ġprivate Ġval Ġjar File 2 : ĠJar File , ĊĠĠĠ Ġprivate Ġval Ġheader 1 : ĠString , ĊĠĠĠ Ġprivate Ġval Ġheader 2 : ĠString , ĊĠĠĠ Ġprivate Ġval ĠoutputFile : ĠFile , ĊĠĠĠ Ġprivate Ġval Ġchecker Configuration : ĠCheck er Configuration Ċ ) Ġ: ĠRunnable Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġignore Anonymous Or Local Classes Ġ= Ġtrue ĊĠĠĠ Ġprivate Ġval Ġignore Java Classes Ġ= Ġtrue ĊĊĠĠĠ Ġprivate Ġval Ġreport Ġ= ĠJar Report ( header , Ġheader 1 , Ġheader 2 , ĊĠĠĠĠĠĠĠ Ġjar File 1 . name ĊĠĠĠĠĠĠĠ Ġ// jar File 1 . name . substring After ('/ '). substring Before (". jar "). drop Last ( 1 ) ĊĠĠĠĠĠĠĠ Ġ, ĊĠĠĠĠĠĠĠ Ġjar File 2 . name ĊĠĠĠĠĠĠĠ Ġ// jar File 2 . name . substring After ('/ '). substring Before (". jar "). drop Last ( 1 ) ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġval Ġdefect Report Ġget () Ġ= Ġreport . def ect Report ĊĊĠĠĠ Ġprivate Ġvar Ġtotal D iffs Ġ= Ġ 0 ĊĊĠĠĠ Ġprivate Ġval Ġnames 1 Ġ= ĠHashSet < String >() ĊĊĠĠĠ Ġprivate Ġval Ġlog Ġ= ĠLogger . getLogger (" mut ator Logger ") ĊĊĠĠĠ Ġoverride Ġfun Ġrun () Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . debug (" Comp aring Ġj ars : Ġ${ jar File 1 . name }, Ġ${ jar File 2 . name }") ĊĊĠĠĠĠĠĠĠ Ġadd J ars Info () ĊĊĠĠĠĠĠĠĠ Ġcheck Jar File 1 () ĊĠĠĠĠĠĠĠ Ġcheck Jar File 2 () ĊĊĠĠĠĠĠĠĠ Ġwrite Report If Required () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġexecute (): ĠPair < Int , ĠFile >? Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . debug (" Comp aring Ġj ars : Ġ${ jar File 1 . name }, Ġ${ jar File 2 . name }") ĊĊĠĠĠĠĠĠĠ Ġadd J ars Info () ĊĊĠĠĠĠĠĠĠ Ġcheck Jar File 1 () ĊĠĠĠĠĠĠĠ Ġcheck Jar File 2 () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( total D iffs Ġ== Ġ 0 ) Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġwrite Report If Required () ĊĠĠĠĠĠĠĠ Ġreturn Ġtotal D iffs Ġto ĠoutputFile ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcheck Jar File 1 () Ġ{ ĊĠĠĠĠĠĠĠ Ġjar File 1 . stream (). forEach Ġ{ Ġentry 1 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname 1 Ġ= Ġentry 1 . name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( name 1 . endsWith (". class ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( name 1 . contains (" kotlin / ")) Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnames 1 . add ( name 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentry 2 Ġ= Ġjar File 2 . getEntry ( name 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry 2 Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Node Ġ= Ġparse Class Node ( jar File 1 . getInputStream ( entry 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! class Node . shouldBe Ignored ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreport . add Missing ClassName 2 ("$ name 1 Ġ${ class Node . access . class Flags () }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ++ total D iffs ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass 1 Ġ= Ġparse Class Node ( jar File 1 . getInputStream ( entry 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass 2 Ġ= Ġparse Class Node ( jar File 2 . getInputStream ( entry 2 )) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! class 1 . shouldBe Ignored () Ġ|| Ġ! class 2 . shouldBe Ignored ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" Comp aring Ġclasses : Ġ${ class 1 . name }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Report Ġ= Ġreport . class Report ( class 1 . name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Task Ġ= ĠClass Task ( checker Configuration , Ġclass 1 , Ġclass 2 , Ġclass Report ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass Task . run () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( class Report . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ++ total D iffs ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" Skipping Ġ$ name 1 ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġparse Class Node ( input : ĠInputStream ): ĠClass Node Ġ= ĊĠĠĠĠĠĠĠ ĠClass Node (). also Ġ{ ĠClass Reader ( input ). accept ( it , ĠClass Reader . SKIP _ CODE ) Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcheck Jar File 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġjar File 2 . stream (). forEach Ġ{ Ġentry 2 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname 2 Ġ= Ġentry 2 . name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( name 2 . endsWith (". class ") Ġ&& Ġname 2 Ġ! in Ġnames 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( name 2 . contains (" kotlin / ")) Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Node Ġ= Ġparse Class Node ( jar File 2 . getInputStream ( entry 2 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! class Node . shouldBe Ignored ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreport . add Missing ClassName 1 ("$ name 2 Ġ${ class Node . access . class Flags () }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ++ total D iffs ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwrite Report If Required () Ġ{ ĊĠĠĠĠĠĠĠ Ġprintln (" TD Ġ= Ġ${ total D iffs }") ĊĊĠĠĠĠĠĠĠ Ġif Ġ( report . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPrintWriter ( outputFile ). use Ġ{ Ġout Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġout . tag (" html ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġout . tag (" head ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġout . print Css () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġout . tag (" body ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreport . write ( out ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠPrintWriter . print Css () Ġ{ ĊĠĠĠĠĠĠĠ Ġtag (" style ", ĠREPORT _ CSS ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClass Node . shouldBe Ignored (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( ignore Java Classes Ġ&& Ġis Java Class ()) Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġif Ġ( access . is Synt hetic ()) Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġif Ġ( ignore Anonymous Or Local Classes Ġ&& Ġis Anonymous Or Local Class ()) Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClass Node . is Anonymous Or Local Class () Ġ= ĊĠĠĠĠĠĠĠ Ġis Sam Adapter Name ( name ) Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinner Classes . listOf NotNull < Inner Class Node >(). any Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . name Ġ== Ġthis . name Ġ&& Ġit . outer Name Ġ== Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClass Node . is Java Class () Ġ= ĊĠĠĠĠĠĠĠ Ġsource File Ġ!= Ġnull Ġ&& Ġsource File . endsWith (". java ") ĊĊĠĠĠ Ġprivate Ġfun Ġadd J ars Info () Ġ{ ĊĠĠĠĠĠĠĠ Ġreport . info Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtag (" p ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtag (" b ", Ġheader 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (": Ġ${ jar File 1 . name }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtag (" p ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtag (" b ", Ġheader 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (": Ġ${ jar File 2 . name }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } ĊĊĊĊ