package Ġcom . did ig lobal . boost er . transform . r . inline Ċ Ċ import Ġcom . did ig lobal . boost er . kotlin x . Wildcard Ċ import Ġcom . did ig lobal . boost er . kotlin x . as Iterable Ċ import Ġcom . did ig lobal . boost er . kotlin x . execute Ċ import Ġcom . did ig lobal . boost er . kotlin x . file Ċ import Ġcom . did ig lobal . boost er . kotlin x . if NotEmpty Ċ import Ġcom . did ig lobal . boost er . kotlin x . search Ċ import Ġcom . did ig lobal . boost er . kotlin x . touch Ċ import Ġcom . did ig lobal . boost er . transform . Artifact Manager . Companion . ALL _ CLASSES Ċ import Ġcom . did ig lobal . boost er . transform . Artifact Manager . Companion . MER GED _ RES Ċ import Ġcom . did ig lobal . boost er . transform . Artifact Manager . Companion . SYMBOL _ LIST Ċ import Ġcom . did ig lobal . boost er . transform . Transform Context Ċ import Ġcom . did ig lobal . boost er . transform . asm . Class Transformer Ċ import Ġcom . google . auto . service . Auto Service Ċ import Ġorg . gradle . api . logging . Logging Ċ import Ġorg . object web . asm . Op codes . GET STATIC Ċ import Ġorg . object web . asm . tree . Class Node Ċ import Ġorg . object web . asm . tree . Field Insn Node Ċ import Ġorg . object web . asm . tree . Field Node Ċ import Ġorg . object web . asm . tree . L dc Insn Node Ċ import Ġjava . io . File Ċ import Ġjava . io . PrintWriter Ċ Ċ internal Ġconst Ġval ĠR _ STYLE ABLE Ġ= Ġ" R \$ style able " Ċ internal Ġconst Ġval ĠAND ROID _ R Ġ= Ġ" android / R $" Ċ internal Ġconst Ġval ĠCOM _ ANDROID _ INTERNAL _ R Ġ= Ġ" com / android / internal / R $" Ċ Ċ /** Ċ Ġ* ĠRepresents Ġa Ġclass Ġnode Ġtransformer Ġfor Ġconstants Ġshrink ing Ċ Ġ* Ċ Ġ* Ġ@ author Ġj ohn son lee Ċ Ġ*/ Ċ @ Auto Service ( Class Transformer :: class ) Ċ class ĠR Inline Transformer Ġ: ĠClass Transformer Ġ{ ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġapp Package : ĠString ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġapp R Style able : ĠString ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġsymbols : ĠSymbol List ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġignores : ĠSet < Wildcard > ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġlogger : ĠPrintWriter ĊĊĠĠĠ Ġoverride Ġfun Ġon Pre Transform ( context : ĠTransform Context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . app Package Ġ= Ġcontext . original Application Id . replace ('.', Ġ'/') ĊĠĠĠĠĠĠĠ Ġthis . logger Ġ= Ġcontext . reports Dir . file ( Build . AR TI FACT ). file ( context . name ). file (" report . txt "). touch (). print Writer () ĊĠĠĠĠĠĠĠ Ġthis . symbols Ġ= ĠSymbol List . from ( context . artifacts . get ( SYMBOL _ LIST ). single ()) ĊĠĠĠĠĠĠĠ Ġthis . app R Style able Ġ= Ġ"$ app Package /$ R _ STYLE ABLE " ĊĠĠĠĠĠĠĠ Ġthis . ign ores Ġ= Ġcontext . getProperty ( PROPERTY _ IG NO RES , Ġ""). trim (). split (',' ). map ( Wildcard . Companion :: valueOf ). toSet () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( this . symbols . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger _. error (" Inline ĠR Ġsymbols Ġfailed : ĠR . txt Ġdoesn 't Ġexist Ġor Ġblank ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . logger . println (" Inlining ĠR Ġsymbols Ġfailed : ĠR . txt Ġdoesn 't Ġexist Ġor Ġblank ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġretained Symbols : ĠSet < String > ĊĠĠĠĠĠĠĠ Ġval Ġclasspath Ġ= Ġcontext . compile Classpath . map Ġ{ Ġit . absolute Path Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( classpath . any Ġ{ Ġit . contains ( PREFIX _ SUPPORT _ CONSTRAINT _ LAYOUT ) Ġ|| Ġit . contains ( PREFIX _ J ET PACK _ CONSTRAINT _ LAYOUT ) Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠFind Ġsymbols Ġthat Ġshould Ġbe Ġretained ĊĠĠĠĠĠĠĠĠĠĠĠ Ġretained Symbols Ġ= Ġcontext . find Ret ained Symbols () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( ret ained Symbols . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . ign ores Ġ+= Ġset Of ( Wildcard . valueOf (" android / support / constraint / R \$ id ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . ign ores Ġ+= Ġset Of ( Wildcard . valueOf (" android x / constraint layout / R \$ id ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġretained Symbols Ġ= Ġempty Set () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlogger . println ( classpath . join ToString ("\ n Ġ Ġ- Ġ", Ġ" classpath :\ n Ġ Ġ- Ġ", Ġ"\ n ")) ĊĠĠĠĠĠĠĠ Ġlogger . println ("$ PROPERTY _ IG NO RES =$ ign ores \ n ") ĊĊĠĠĠĠĠĠĠ Ġretained Symbols . if NotEmpty Ġ{ Ġsymbols Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ret ained Ġsymbols :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsymbols . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ġ Ġ- ĠR . id .$ it ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠRemove Ġredundant ĠR Ġclass Ġfiles ĊĠĠĠĠĠĠĠ Ġval Ġredundant Ġ= Ġcontext . find Red undant R () ĊĠĠĠĠĠĠĠ Ġredundant . if NotEmpty Ġ{ Ġpairs Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtotal Size Ġ= Ġredundant . map Ġ{ Ġit . first . length () Ġ}. sum () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmaxWidth Ġ= Ġredundant . map Ġ{ Ġit . second . length Ġ}. max ()?. plus ( 1 0 ) Ġ?: Ġ 1 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Delete Ġfiles :") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpairs . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . first . delete ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ġ- Ġ`${ it . second }` ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println ("- ". repeat ( maxWidth )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Total : Ġ$ total Size Ġbytes ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġtransform ( context : ĠTransform Context , Ġklass : ĠClass Node ): ĠClass Node Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( this . symbols . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġklass ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( this . ign ores . any Ġ{ Ġit . matches ( klass . name ) Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ignore Ġ`${ klass . name }` ") ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġklass . replace Symbol Reference With Constant () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġklass ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Post Transform ( context : ĠTransform Context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . logger . close () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠTransform Context . find Red undant R (): ĠList < Pair < File , ĠString >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġartifacts . get ( ALL _ CLASSES ). map Ġ{ Ġclasses Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbase Ġ= Ġclasses . to URI () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġclasses . search Ġ{ Ġr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġr . name . startsWith (" R ") Ġ&& Ġr . name . endsWith (". class ") Ġ&& Ġ( r . name [ 1 ] Ġ== Ġ'$ ' Ġ|| Ġr . name . length Ġ== Ġ 7 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. map Ġ{ Ġr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġr Ġto Ġbase . rel ativ ize ( r . to URI ()). path . substring Before Last (". class ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. flatten (). filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . second Ġ!= Ġapp R Style able Ġ// Ġkeep Ġapplication 's ĠR $ style able . class ĊĠĠĠĠĠĠĠ Ġ}. filter Ġ{ Ġpair Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! ign ores . any Ġ{ Ġit . matches ( pair . second ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClass Node . replace Symbol Reference With Constant () Ġ{ ĊĠĠĠĠĠĠĠ Ġmethods . forEach Ġ{ Ġmethod Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġins ns Ġ= Ġmethod . instructions . iterator (). as Iterable (). filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . opcode Ġ== ĠGET STATIC ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit Ġas ĠField Insn Node ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(" I " Ġ== Ġit . desc Ġ|| Ġ"[ I " Ġ== Ġit . desc ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġit . owner . substring ( it . owner . lastIndexOf ('/') Ġ+ Ġ 1 ). startsWith (" R $ ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġ!( it . owner . startsWith ( COM _ ANDROID _ INTERNAL _ R ) Ġ|| Ġit . owner . startsWith ( ANDROID _ R )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġint Fields Ġ= Ġins ns . filter Ġ{ Ġ" I " Ġ== Ġit . desc Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠintArray Fields Ġ= Ġins ns . filter Ġ{ Ġ"[ I " Ġ== Ġit . desc Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠReplace Ġint Ġfield Ġwith Ġconstant ĊĠĠĠĠĠĠĠĠĠĠĠ Ġint Fields . forEach Ġ{ Ġfield Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġfield . owner . substring ( field . owner . lastIndexOf ("/ R $ ") Ġ+ Ġ 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . instructions . insertBefore ( field , ĠL dc Insn Node ( symbols . getInt ( type , Ġfield . name ))) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod . instructions . remove ( field ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ġ* Ġ${ field . owner }.${ field . name } Ġ=> Ġ${ symbols . getInt ( type , Ġfield . name )} : Ġ$ name .${ method . name }${ method . desc }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNullPointerException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . println (" Ġ! ĠUn res olvable Ġsymbol Ġ`${ field . owner }.${ field . name }` : Ġ$ name .${ method . name }${ method . desc }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠReplace Ġlibrary 's ĠR Ġfields Ġwith Ġapplication 's ĠR Ġfields ĊĠĠĠĠĠĠĠĠĠĠĠ ĠintArray Fields . forEach Ġ{ Ġfield Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield . owner Ġ= Ġ"$ app Package /${ field . owner . substring ( field . owner . lastIndexOf ('/') Ġ+ Ġ 1 )}" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ } Ċ Ċ private Ġfun ĠField Node . value AsString () Ġ= Ġwhen Ġ{ ĊĠĠĠ Ġvalue Ġis ĠString Ġ-> Ġ"\" $ value \"" ĊĠĠĠ Ġelse Ġ-> Ġvalue . toString () Ċ } Ċ Ċ /** Ċ Ġ* ĠFind Ġsymbols Ġthat Ġshould Ġbe Ġretained , Ġsuch Ġas : Ċ Ġ* Ċ Ġ* Ġ- Ġattribute Ġ` constraint _ referenced _ ids ` Ġin Ġ` Constraint Layout ` Ċ Ġ*/ Ċ private Ġfun ĠTransform Context . find Ret ained Symbols (): ĠSet < String > Ġ{ ĊĠĠĠ Ġreturn Ġartifacts . get ( MER GED _ RES ). map Ġ{ ĊĠĠĠĠĠĠĠ ĠRet ained Symbol Collector ( it ). execute () ĊĠĠĠ Ġ}. flatten (). toSet () Ċ } Ċ Ċ private Ġval ĠPROPERTY _ PREFIX Ġ= ĠBuild . AR TI FACT . replace ('- ', Ġ'.') Ċ Ċ private Ġval ĠPROPERTY _ IG NO RES Ġ= Ġ"$ PROPERTY _ PREFIX . ign ores " Ċ Ċ private Ġval ĠPREFIX _ SUPPORT _ CONSTRAINT _ LAYOUT Ġ= Ġ"${ File . separator Char } com . android . support . constraint ${ File . separator Char } constraint - layout " Ċ Ċ private Ġval ĠPREFIX _ J ET PACK _ CONSTRAINT _ LAYOUT Ġ= Ġ"${ File . separator } android x . constraint layout ${ File . separator } constraint layout " Ċ Ċ private Ġval Ġlogger _ Ġ= ĠLogging . getLogger ( R Inline Transformer :: class . java ) Ċ