package Ġcom . h awk ste ch . intellij . plugin . fer n flower Ċ Ċ import Ġcom . google . common . base . Preconditions . checkNotNull Ċ import Ġcom . google . common . base . Preconditions . check State Ċ import Ġcom . intellij . ide . plugins . PluginManager Core Ċ import Ġcom . intellij . ide . util . Properties Component Ċ import Ġcom . intellij . notification . Notification Ċ import Ġcom . intellij . notification . Notification Type Ċ import Ġcom . intellij . openapi . action System .* Ċ import Ġcom . intellij . openapi . application . Application Manager Ċ import Ġcom . intellij . openapi . application . Modal ity State Ċ import Ġcom . intellij . openapi . application . ex . Application Manager Ex Ċ import Ġcom . intellij . openapi . command . Write Command Action . write Command Action Ċ import Ġcom . intellij . openapi . diagnostic . Logger Ċ import Ġcom . intellij . openapi . module . Module Ċ import Ġcom . intellij . openapi . progress . Progress Indicator Ċ import Ġcom . intellij . openapi . progress . Task Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . openapi . roots .* Ċ import Ġcom . intellij . openapi . roots . libraries . Library Ċ import Ġcom . intellij . openapi . roots . ui . configuration . Library Source Root Detector Util Ċ import Ġcom . intellij . openapi . ui . Dialog Wrapper Ċ import Ġcom . intellij . openapi . util . io . File Util Ċ import Ġcom . intellij . openapi . vfs .* Ċ import Ġcom . intellij . ui . components . Legal Notice Dialog Ċ import Ġcom . intellij . util . Common Processors Ċ import Ġcom . intellij . util . System Properties Ċ import Ġorg . jetbrains . annotations . NotNull Ċ import Ġorg . jetbrains . java . de compiler . main . De compiler Context Ċ import Ġorg . jetbrains . java . de compiler . main . F ern flower Ċ import Ġorg . jetbrains . java . de compiler . main . extern . I Byte code Provider Ċ import Ġorg . jetbrains . java . de compiler . main . extern . IF ern flower Logger Ċ import Ġorg . jetbrains . java . de compiler . main . extern . IF ern flower Preferences Ċ import Ġorg . jetbrains . java . de compiler . main . extern . I Result Saver Ċ import Ġorg . jetbrains . java . de compiler . util . Interpreter Util Ċ import Ġjava . io . File Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . io . OutputStream Writer Ċ import Ġjava . nio . charset . StandardCharsets Ċ import Ġjava . util .* Ċ import Ġjava . util . jar . Jar OutputStream Ċ import Ġjava . util . jar . Manifest Ċ import Ġjava . util . zip . Zip Entry Ċ import Ġjava . util . zip . Zip File Ċ import Ġjava . util . zip . Zip OutputStream Ċ import Ġkotlin . collections . HashMap Ċ Ċ /** Ċ Ġ* ĠCreated Ġby Ġb du is en ov Ġon Ġ 1 2 / 1 1 / 1 5 . Ġas ĠDe compile And Att ache Action Ċ Ġ* Ġupdated Ġr fer gus on Ġ 1 2 / 9 / 1 7 Ġand Ġ 9 / 2 / 1 8 . Ċ Ġ* Ġexpanded Ġwith Ġextra Ġfunction Ġa wh aw ks Ġ 4 / 3 / 2 0 1 9 Ċ Ġ*/ Ċ class ĠDe compile WithOptions Plugin : ĠAn Action (), ĠI Byte code Provider , ĠI Result Saver Ġ{ Ċ ĉ private Ġval Ġlogger Ġ= ĠLogger . getInstance ( De compile WithOptions Plugin :: class . java ) ĊĊ ĉ // ĠFrom ĠIde a De compiler Ċ ĉ private Ġval Ġlegal Notice Key Ġ Ġ= Ġ" de compiler . legal . notice . accepted " Ċ ĉ private Ġval Ġdecl ine ExitCode Ġ= ĠDialog Wrapper . NEXT _ USER _ EXIT _ CODE ĊĊ ĉ private Ġvar Ġis Attach Option : Boolean Ġ= Ġfalse Ċ ĉ private Ġvar Ġde compiled Jar Dir : String Ġ= Ġ" Not Set Y et " Ċ ĉ private Ġvar Ġde compiled Src Dir : String Ġ= Ġ" Not Set Y et " Ċ ĉ private Ġvar Ġde compiler Options : Mutable Map < String , ĠAny > Ġ= Ġmutable Map Of () Ċ ĉ private Ġvar Ġtmp Dir : File Ġ= ĠFile (" Not Set Y et ") ĊĊ ĉ /** Ċĉ Ġ* Ġshow Ġ' de compile Ġand Ġattach ' Ġoption Ġonly Ġfor Ġ*. jar Ġfiles Ċĉ Ġ* Ġ@ param Ġe ĠAn ActionEvent Ċĉ Ġ*/ Ċ ĉ override Ġfun Ġupdate ( e : ĠAn ActionEvent ) Ġ{ Ċĉ ĉ val Ġpresentation Ġ= Ġe . presentation Ċĉ ĉ presentation . isEnabled Ġ= Ġfalse Ċĉ ĉ presentation . isVisible Ġ= Ġfalse Ċĉ ĉ val Ġvirtual File Ġ= Ġe . getData ( Common Data Keys . VIRTUAL _ FILE ) Ċĉ ĉ if Ġ( virtual File Ġ!= Ġnull Ġ&& Ċĉĉĉ ĉ " jar " Ġ== Ġvirtual File . extension Ġ&& Ċĉĉĉ ĉ e . project Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ presentation . isEnabled Ġ= Ġtrue Ċĉĉ ĉ presentation . isVisible Ġ= Ġtrue Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun ĠactionPerformed ( event : ĠAn ActionEvent ) Ġ{ Ċĉ ĉ val Ġproject Ġ= Ġevent . project Ġ?: Ġreturn ĊĊĉ ĉ val Ġselected Jar file : Virtual File ? Ġ Ġ= ĠData Keys . VIRTUAL _ FILE . getData ( event . data Context ) Ċĉ ĉ val Ġselected Jar Folder : Virtual File Ġ= Ġselected Jar file !!. parent ĊĊĉ ĉ val Ġstored Settings Ġ= ĠSettings Utils ( project , Ġselected Jar Folder ) ĊĊĊĉ ĉ if Ġ(! Properties Component . getInstance (). is Value Set ( legal Notice Key )) Ġ{ Ċĉĉ ĉ val Ġtitle ĠĠ Ġ= ĠLeg al Bundle . message (" legal . notice . title ", Ġ" Legal ĠTerms ") Ċĉĉ ĉ val Ġmessage Ġ= ĠLeg al Bundle . message (" legal . notice . text ") Ċĉĉ ĉ val Ġanswer Ġ= ĠLeg al Notice Dialog . build ( title , Ġmessage ) Ċĉĉĉĉ ĉ . with Cancel Text (" Dec ide ĠL ater ") Ċĉĉĉĉ ĉ . with Custom Action (" Decl ine Ġand Ġrestart ", Ġdecl ine ExitCode ) Ċĉĉĉĉ ĉ . show () Ċĉĉ ĉ when Ġ( answer ) Ġ{ Ċĉĉĉ ĉ Dialog Wrapper . OK _ EXIT _ CODE Ġ-> Ġ{ Ċĉĉĉĉ ĉ Properties Component . getInstance (). setValue ( legal Notice Key , Ġtrue ) Ċĉĉĉĉ ĉ logger . info (" De compiler Ġlegal Ġnotice Ġaccepted .") Ċĉĉĉ ĉ } Ċĉĉĉ ĉ decl ine ExitCode Ġ-> Ġ{ Ċĉĉĉĉ ĉ PluginManager Core . disable Plugin (" com . h awk ste ch . intellij . plugin . fer n flower de compiler ") Ċĉĉĉĉ ĉ Application Manager Ex . getApplication Ex (). restart ( true ) Ċĉĉĉĉ ĉ logger . info (" De compiler Ġlegal Ġnotice Ġrejected , Ġdisabling Ġde compile Ġand Ġattach Ġplugin .") Ċĉĉĉĉ ĉ return Ċĉĉĉ ĉ } Ċĉĉĉ ĉ else Ġ-> Ġ{ Ċĉĉĉĉ ĉ Notification (" De compile And Attach ", Ġ" De compile Ġrequest Ġrejected ", Ċĉĉĉĉĉĉ ĉ " De compiler Ġcannot Ġcontinue Ġuntil Ġterms Ġof Ġuse Ġare Ġaccepted .", ĠNotification Type . INFORMATION ) Ċĉĉĉĉĉĉ ĉ . notify ( project ) Ċĉĉĉĉ ĉ return Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ val Ġsource V Fs Ġ= Ġevent . getData ( Platform Data Keys . VIRTUAL _ FILE _ ARRAY ) Ċĉ ĉ check State ( source V Fs Ġ!= Ġnull Ġ&& Ġsource V Fs . isNotEmpty (), Ġ" event # getData ( VIRTUAL _ FILE _ ARRAY ) Ġreturned Ġempty Ġarray ") ĊĊĉ ĉ val Ġcontent Ġ= ĠDe compile Options UI ( project , Ġstored Settings ) ĊĊĉ ĉ if ( content . show AndGet ()) Ġ{ Ċĉĉ ĉ is Attach Option ĠĠ Ġ= Ġcontent . get Attach Option () Ċĉĉ ĉ de compiled Jar Dir Ġ= Ġcontent . get De compiled Jar Dir () Ċĉĉ ĉ de compiled Src Dir Ġ= Ġcontent . get De compiled Src Dir () Ċĉĉ ĉ content . get Parsed Options (). forEach { Ġentry Ġ-> Ċĉĉĉ ĉ val Ġf ern Key Ġ= Ġwhen ( entry . key ){ Ċĉĉĉĉ ĉ Settings Utils . Setting Names . REMOVE _ BR ID GE ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . REMOVE _ BR ID GE Ċĉĉĉĉ ĉ Settings Utils . Setting Names . REMOVE _ SYN TH ET IC ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . REMOVE _ SYN TH ET IC Ċĉĉĉĉ ĉ Settings Utils . Setting Names . DE COMPILE _ INNER ĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . DE COMPILE _ INNER Ċĉĉĉĉ ĉ Settings Utils . Setting Names . DE COMPILE _ CLASS _ 1 _ 4 ĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . DE COMPILE _ CLASS _ 1 _ 4 Ċĉĉĉĉ ĉ Settings Utils . Setting Names . DE COMPILE _ ASSERT IONS ĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . DE COMPILE _ ASSERT IONS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . HIDE _ EMPTY _ SUPER ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . HIDE _ EMPTY _ SUPER Ċĉĉĉĉ ĉ Settings Utils . Setting Names . HIDE _ DEFAULT _ CON STRUCTOR ĠĠĠĠ Ġ-> ĠIF ern flower Preferences . HIDE _ DEFAULT _ CON STRUCTOR Ċĉĉĉĉ ĉ Settings Utils . Setting Names . DE COMPILE _ GENERIC _ SIGNATURE S Ġ-> ĠIF ern flower Preferences . DE COMPILE _ GENERIC _ SIGNATURE S Ċĉĉĉĉ ĉ Settings Utils . Setting Names . NO _ EXCEPTION S _ RETURN ĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . NO _ EXCEPTION S _ RETURN Ċĉĉĉĉ ĉ Settings Utils . Setting Names . ENS URE _ SYN CH RON IZED _ MONITOR Ġ Ġ-> ĠIF ern flower Preferences . ENS URE _ SYN CH RON IZED _ MONITOR Ċĉĉĉĉ ĉ Settings Utils . Setting Names . DE COMPILE _ ENUM ĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . DE COMPILE _ ENUM Ċĉĉĉĉ ĉ Settings Utils . Setting Names . REMOVE _ GET _ CLASS _ NEW ĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . REMOVE _ GET _ CLASS _ NEW Ċĉĉĉĉ ĉ Settings Utils . Setting Names . LITERAL S _ AS _ IS ĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . LITERAL S _ AS _ IS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . BOOLEAN _ TRUE _ ONE ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . BOOLEAN _ TRUE _ ONE Ċĉĉĉĉ ĉ Settings Utils . Setting Names . ASCII _ STRING _ CHAR ACT ERS ĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . ASCII _ STRING _ CHAR ACT ERS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . SYN TH ET IC _ NOT _ SET ĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . SYN TH ET IC _ NOT _ SET Ċĉĉĉĉ ĉ Settings Utils . Setting Names . UNDEFINED _ PARAM _ TYPE _ OBJECT Ġ Ġ-> ĠIF ern flower Preferences . UNDEFINED _ PARAM _ TYPE _ OBJECT Ċĉĉĉĉ ĉ Settings Utils . Setting Names . USE _ DEBUG _ VAR _ NAMES ĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . USE _ DEBUG _ VAR _ NAMES Ċĉĉĉĉ ĉ Settings Utils . Setting Names . USE _ METHOD _ PARAMETERS ĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . USE _ METHOD _ PARAMETERS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . REMOVE _ EMPTY _ RAN GES ĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . REMOVE _ EMPTY _ RAN GES Ċĉĉĉĉ ĉ Settings Utils . Setting Names . FIN ALLY _ DE INLINE ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . FIN ALLY _ DE INLINE Ċĉĉĉĉ ĉ Settings Utils . Setting Names . IDE A _ NOT _ NULL _ AN NOT ATION ĠĠĠĠ Ġ-> ĠIF ern flower Preferences . IDE A _ NOT _ NULL _ AN NOT ATION Ċĉĉĉĉ ĉ Settings Utils . Setting Names . L AMBDA _ TO _ AN ONY MO US _ CLASS ĠĠĠ Ġ-> ĠIF ern flower Preferences . L AMBDA _ TO _ AN ONY MO US _ CLASS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . BYTE CODE _ SOURCE _ MAPPING ĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . BYTE CODE _ SOURCE _ MAPPING Ċĉĉĉĉ ĉ Settings Utils . Setting Names . IGNORE _ INVALID _ BYTE CODE ĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . IGNORE _ INVALID _ BYTE CODE Ċĉĉĉĉ ĉ Settings Utils . Setting Names . VERIFY _ AN ONY MO US _ CLASSES ĠĠĠĠ Ġ-> ĠIF ern flower Preferences . VERIFY _ AN ONY MO US _ CLASSES ĊĊĉĉĉĉ ĉ Settings Utils . Setting Names . LOG _ LEVEL ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . LOG _ LEVEL Ċĉĉĉĉ ĉ Settings Utils . Setting Names . MAX _ PROCESS ING _ METHOD ĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . MAX _ PROCESS ING _ METHOD Ċĉĉĉĉ ĉ Settings Utils . Setting Names . RE NAME _ ENT ITIES ĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . RE NAME _ ENT ITIES Ċĉĉĉĉ ĉ // TODO ĠSettings Utils . Setting Names . USER _ RE NA MER _ CLASS ĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . USER _ RE NA MER _ CLASS Ċĉĉĉĉ ĉ Settings Utils . Setting Names . NEW _ LINE _ SEPARATOR ĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . NEW _ LINE _ SEPARATOR Ċĉĉĉĉ ĉ Settings Utils . Setting Names . IND ENT _ STRING ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . IND ENT _ STRING Ċĉĉĉĉ ĉ Settings Utils . Setting Names . BAN NER ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . BAN NER ĊĊĉĉĉĉ ĉ // Settings Utils . Setting Names . DUMP _ ORIGIN AL _ LINES ĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . DUMP _ ORIGIN AL _ LINES Ċĉĉĉĉ ĉ // Settings Utils . Setting Names . UNIT _ TEST _ MODE ĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> ĠIF ern flower Preferences . UNIT _ TEST _ MODE Ċĉĉĉĉ ĉ else Ġ-> Ġ"" Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if ( Ġf ern Key . isNotEmpty () Ġ&& Ġentry . value . isNotEmpty () Ġ) Ġ{ Ċĉĉĉĉ ĉ de compiler Options [ fer n Key ] Ġ= Ġentry . value Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉĉ ĉ object Ġ: ĠTask . Background able ( project , Ġ" De comp iling ...", Ġtrue ) Ġ{ Ċĉĉĉ ĉ override Ġfun Ġrun (@ NotNull Ġindicator : ĠProgress Indicator ) Ġ{ Ċĉĉĉĉ ĉ indicator . fraction Ġ= Ġ 0 . 1 ĊĊĉĉĉĉ ĉ source V Fs !!. toList (). stream () Ġ// Ċĉĉĉĉĉĉ ĉ . filter Ġ{ Ġvf Ġ-> Ġ" jar " Ġ== Ġvf . extension Ġ} Ġ// Ċĉĉĉĉĉĉ ĉ . forEach Ġ{ Ġsource VF Ġ-> Ċĉĉĉĉĉĉĉ ĉ process ( project , Ġsource VF , Ġindicator , Ġ 1 . 0 Ġ/ Ġsource V Fs . size ) Ċĉĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ indicator . fraction Ġ= Ġ 1 . 0 Ċĉĉĉĉ ĉ Virtual FileManager . getInstance (). get FileSystem ( Standard FileSystem s . FILE _ PROTOCOL ). refresh ( true ) Ċĉĉĉ ĉ } ĊĊĉĉĉ ĉ override Ġfun Ġshould Start In Background (): ĠBoolean Ġ{ Ċĉĉĉĉ ĉ return Ġtrue Ċĉĉĉ ĉ } Ċĉĉ ĉ }. queue () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġprocess ( project : ĠProject , Ġsource VF : ĠVirtual File , Ġindicator : ĠProgress Indicator , Ġfraction Step : ĠDouble ): File Ġ{ Ċĉ ĉ indicator . text Ġ= Ġ" De comp iling Ġ'" Ġ+ Ġsource VF . name Ġ+ Ġ"'" Ċĉ ĉ val Ġlibrary Name Ġ= Ġsource VF . name . replace (". jar ", Ġ"- sources . jar ") Ċĉ ĉ val Ġfull Path Ġ= Ġde compiled Jar Dir Ġ+ ĠFile . separator Ġ+ Ġlibrary Name Ċĉ ĉ var ĠoutputFile Ġ= ĠFile ( fullPath ) Ċĉ ĉ val Ġjar FileSystem Instance Ġ= ĠJar FileSystem . getInstance () Ċĉ ĉ val Ġjar Root Ġ= Ġjar FileSystem Instance . get Jar Root For Local File ( source VF ) ?: Ġjar FileSystem Instance . get Jar Root For Local File ( Objects . requireNonNull < Virtual File >( jar FileSystem Instance . get Virtual File For Jar ( source VF ))) !! Ċĉ ĉ val Ġj dk Rt Jar Ġ Ġ= ĠFile ( ĠSystem Properties . get Java Home (), Ġ" jre / lib / rt . jar ") Ċĉ ĉ val Ġj re Rt Jar Ġ Ġ= ĠFile ( ĠSystem Properties . get Java Home (), Ġ" lib / rt . jar ") Ċĉ ĉ val Ġuse Rt Jar Ġ Ġ= Ġj dk Rt Jar . exists () Ġ|| Ġj re Rt Jar . exists () ĊĊĉ ĉ try Ġ{ Ċĉĉ ĉ tmp Dir Ġ= ĠFile Util . create Temp Directory (" de compiled Temp DIR "," ext ") Ċĉĉ ĉ val Ġtmp Jar File Ġ Ġ= ĠFile ( tmp Dir , Ġsource VF . name Ġ) Ċĉĉ ĉ val Ġsrc Jar Ġ= ĠFile ( jar Root . canonical Path !!. drop Last ( 2 )) ĊĊĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ val Ġf ern Logger Ġ= ĠDe compile WithOptions Logger () Ċĉĉĉ ĉ // val Ġf ern Logger Ġ= ĠPrint Stream Logger ( System . out ) Ċĉĉĉ ĉ val Ġengine Ġ= ĠF ern flower ( this , Ġthis , Ġde compiler Options , Ġf ern Logger ) Ċĉĉĉ ĉ if ( use Rt Jar ) Ġ{ Ċĉĉĉĉ ĉ val Ġrt Jar : File Ġ= Ġif ( Ġj dk Rt Jar . exists () Ġ) Ġj dk Rt Jar Ġelse Ġj re Rt Jar Ċĉĉĉĉ ĉ engine . add Library ( rt Jar ); Ċĉĉĉ ĉ } Ċĉĉĉ ĉ engine . add Source ( src Jar ) Ċĉĉĉ ĉ try Ġ{ Ċĉĉĉĉ ĉ engine . de compile Context () Ċĉĉĉ ĉ } Ġcatch ( exc : Throwable ) Ġ{ Ċĉĉĉĉ ĉ exc . printStackTrace () Ċĉĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉĉ ĉ engine . clear Context () Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if Ġ( outputFile . exists ()) Ġ{ Ċĉĉĉĉ ĉ File Util . delete With Ren aming ( outputFile ) Ċĉĉĉĉ ĉ outputFile Ġ= ĠFile ( fullPath ) Ċĉĉĉĉ ĉ outputFile . createNew File () Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġcatch Ġ( e : Exception ){ Ċĉĉĉ ĉ Notification (" De compile WithOptions ", Ġ" Jar Ġlib Ġcouldn 't Ġbe Ġde compiled ", Ċĉĉĉĉĉ ĉ " F ern flower Ġargs : Ġ$ de compiler Options Ġ${ src Jar . absolute Path } Ġ${ tmp Dir . absolute Path }", ĠNotification Type . ERROR ). notify ( project ) Ċĉĉĉ ĉ File Util . delete ( tmp Jar File ) Ċĉĉĉ ĉ File Util . delete ( tmp Dir ) Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ if ( tmp Jar File . exists ()){ Ċĉĉĉĉ ĉ File Util . copy ( tmp Jar File , ĠoutputFile ) Ċĉĉĉĉ ĉ if ( is Attach Option ) Ġ{ Ċĉĉĉĉĉ ĉ attach ( project , Ġsource VF , ĠoutputFile ) Ċĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ indicator . fraction Ġ= Ġindicator . fraction Ġ+ Ġfraction Step Ġ* Ġ 3 0 Ġ/ Ġ 1 0 0 Ċĉĉĉĉ ĉ File Util . delete ( tmp Jar File ) Ċĉĉĉĉ ĉ File Util . delete ( tmp Dir ) Ċĉĉĉĉ ĉ Zip File ( outputFile . absolute Path ). use Ġ{ Ġzip Ġ-> Ċĉĉĉĉĉ ĉ zip . entries (). as Sequence (). forEach Ġ{ Ġentry Ġ-> Ċĉĉĉĉĉĉ ĉ if ( entry . isDirectory ){ Ċĉĉĉĉĉĉĉ ĉ val Ġdst Dir Ġ= ĠFile ("$ de compiled Src Dir /${ entry . name }") Ċĉĉĉĉĉĉĉ ĉ if Ġ(! dst Dir . exists ()) Ġ{ Ċĉĉĉĉĉĉĉĉ ĉ dst Dir . parent File . mkdir s () Ċĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉĉ ĉ zip . getInputStream ( entry ). use Ġ{ Ġinput Ġ-> Ċĉĉĉĉĉĉĉĉ ĉ val Ġdst File Ġ= ĠFile ("$ de compiled Src Dir /${ entry . name }") Ċĉĉĉĉĉĉĉĉ ĉ if Ġ(! dst File . exists ()) Ġ{ Ċĉĉĉĉĉĉĉĉĉ ĉ dst File . parent File . mkdir s () Ċĉĉĉĉĉĉĉĉĉ ĉ dst File . createNew File () Ċĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉĉ ĉ if Ġ( dst File . isFile ) Ġ{ Ċĉĉĉĉĉĉĉĉĉ ĉ dst File . output Stream (). use Ġ{ Ġoutput Ġ-> Ċĉĉĉĉĉĉĉĉĉĉ ĉ input . copy To ( output ) Ċĉĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ Notification (" De compile WithOptions ", Ġ" Jar Ġlib Ġcouldn 't Ġbe Ġde compiled ", Ċĉĉĉĉĉĉ ĉ " F ern flower Ġargs : Ġ${ tmp Jar File . absolute Path } Ġwas Ġnot Ġgenerated ", ĠNotification Type . ERROR ). notify ( project ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ġcatch Ġ( e : ĠIOException ) Ġ{ Ċĉĉ ĉ Notification (" De compile WithOptions ", Ġ" Jar Ġlib Ġcouldn 't Ġbe Ġde compiled ", Ċĉĉĉĉ ĉ source VF . name Ġ+ Ġ" Ġ" Ġ+ Ġe . java Class . name Ġ+ Ġ" Ġ" Ġ+ Ġe . toString (), ĠNotification Type . ERROR ). notify ( project ) Ċĉ ĉ } Ċĉ ĉ return ĠoutputFile Ċ ĉ } ĊĊ ĉ private Ġfun Ġattach ( project : ĠProject ?, Ġsource VF : ĠVirtual File , Ġresult Jar : ĠFile ) Ġ{ Ċĉ ĉ Application Manager . getApplication (). invoke And Wait ({ Ċĉĉ ĉ val Ġresult Jar VF Ġ= ĠLocal FileSystem . getInstance (). refresh And Find File By Io File ( result Jar ) !! Ċĉĉ ĉ checkNotNull ( result Jar VF , Ġ" could Ġnot Ġfind ĠVirtual ĠFile Ġof Ġ% s ", Ġresult Jar . absolute Path ) Ċĉĉ ĉ val Ġresult Jar Root Ġ= ĠJar FileSystem . getInstance (). get Jar Root For Local File ( result Jar VF ) !! Ċĉĉ ĉ val Ġroots Ġ= ĠLibrary Source Root Detector Util . scan And Select Detected Java Source Roots ( null , Ċĉĉĉĉ ĉ array Of ( result Jar Root )) Ċĉĉ ĉ write Command Action ( project ). run < RuntimeException > Ġ{ ĊĊĉĉĉ ĉ val Ġcurrent Module Ġ= ĠProject Root Manager . getInstance ( project !! ). file Index Ġ. getModule For File ( source VF , Ġfalse ) ĊĊĉĉĉ ĉ if Ġ( current Module Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ val Ġmodule Lib Ġ= Ġfind Module Dependency ( current Module , Ġsource VF ) Ċĉĉĉĉ ĉ check State ( module Lib . isPresent , Ġ" could Ġnot Ġfind Ġlibrary Ġin Ġmodule Ġdependencies ") Ċĉĉĉĉ ĉ val Ġmodel Ġ= Ġmodule Lib . get (). modifiable Model Ċĉĉĉĉ ĉ for Ġ( root Ġin Ġroots ) Ġ{ Ċĉĉĉĉĉ ĉ model . add Root ( root , ĠOrder Root Type . SOURCES ) Ċĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ model . commit () ĊĊĉĉĉĉ ĉ Notification (" De compile And Attach ", Ġ" Jar ĠS ources ĠAdded ", Ġ" de compiled Ġsources Ġ" Ġ+ Ġresult Jar . name Ċĉĉĉĉĉĉ ĉ + Ġ" Ġwhere Ġadded Ġsuccessfully Ġto Ġdependency Ġof Ġa Ġmodule Ġ'" Ġ+ Ġcurrent Module . name Ġ+ Ġ"'", Ċĉĉĉĉĉĉ ĉ Notification Type . INFORMATION ). notify ( project ) Ċĉĉĉ ĉ } Ġelse Ġif Ġ(" jar " Ġ!= Ġsource VF . extension ) Ġ{ Ċĉĉĉĉ ĉ Notification (" De compile And Attach ", Ġ" Failed Ġget Module ", Ċĉĉĉĉĉĉ ĉ " File Ġis Ġ" Ġ+ Ġsource VF . name , ĠNotification Type . WARNING ). notify ( project ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ }, ĠMod ality State . NON _ MOD AL ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġfind Module Dependency ( module : ĠModule , Ġsource VF : ĠVirtual File ): ĠOptional < Library > Ġ{ Ċĉ ĉ val Ġprocessor Ġ= Ġobject Ġ: ĠCommon Processors . Find Processor < Order Entry >() Ġ{ ĊĊĉĉ ĉ override Ġfun Ġaccept ( order Entry : ĠOrder Entry ): ĠBoolean Ġ{ Ċĉĉĉ ĉ val Ġurls Ġ= Ġorder Entry . get Urls ( Order Root Type . CLASSES ) Ċĉĉĉ ĉ val Ġcontains Ġ= ĠArrays . asList (* urls ). contains (" jar ://" Ġ+ Ġsource VF . path Ġ+ Ġ" !/ ") Ċĉĉĉ ĉ return Ġcontains Ġ&& Ġorder Entry Ġis ĠLibrary Order Entry Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ Module Root Manager . getInstance ( module ). order Entries (). forEach ( processor ) Ċĉ ĉ var Ġresult : ĠLibrary ? Ġ= Ġnull Ċĉ ĉ if Ġ( processor . found Value Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ result Ġ= Ġ( processor . found Value Ġas ĠLibrary Order Entry ). library Ċĉ ĉ } Ċĉ ĉ return ĠOptional . of Nullable ( result ) Ċ ĉ } ĊĊ ĉ private Ġval Ġmap Archive Streams Ġ= ĠHashMap < String , ĠZip OutputStream >() Ċ ĉ private Ġval Ġmap Archive Entries Ġ= ĠHashMap < String , ĠSet < String >>() ĊĊ ĉ // Ġ***************************************************************** ** Ċ ĉ // ĠUtility Ġfunctions Ġused Ġby ĠInterface ĠI Result Saver Ċ ĉ // Ġ***************************************************************** ** Ċ ĉ private Ġfun Ġget AbsolutePath ( path : ĠString ): ĠString Ġ{ Ċĉ ĉ return ĠFile ( tmp Dir , Ġpath ). absolute Path Ċ ĉ } ĊĊ ĉ private Ġfun Ġcheck Entry ( entry Name : ĠString , Ġfile : ĠString ): ĠBoolean Ġ{ Ċĉ ĉ val Ġset : Set < String > Ġ= Ġmap Archive Entries . get Or Put ( file ) Ġ{ ĠHashSet () Ġ} Ċĉ ĉ val Ġadded Ġ= Ġ! set . contains ( entry Name ) Ċĉ ĉ set . plus ( Ġentry Name Ġ) Ċĉ ĉ if Ġ(! added ) Ġ{ Ċĉĉ ĉ val Ġmessage Ġ= Ġ" Zip Ġfile Ġ$ file Ġalready Ġhas Ġentry Ġ$ entry Name " Ċĉĉ ĉ De compiler Context . getLogger (). write Message ( message , ĠIF ern flower Logger . Severity . WARN ) Ċĉ ĉ } Ċĉ ĉ return Ġadded Ċ ĉ } ĊĊ ĉ // Ġ***************************************************************** ** Ċ ĉ // ĠInterface ĠI Byte code Provider Ċ ĉ // Ġ***************************************************************** ** ĊĊ ĉ @ Throws ( IOException :: class ) Ċ ĉ override Ġfun Ġget Byte code ( external Path : ĠString , Ġinternal Path : ĠString ?): ĠByteArray Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( external Path ) Ċĉ ĉ if Ġ( internal Path Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ return ĠInterpreter Util . getBytes ( file ) Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ Zip File ( file ). use Ġ{ Ġarchive Ġ-> Ċĉĉĉ ĉ val Ġentry Ġ= Ġarchive . getEntry ( internal Path ) Ġ?: Ġthrow ĠIOException (" Entry Ġnot Ġfound : Ġ$ internal Path ") Ċĉĉĉ ĉ return ĠInterpreter Util . getBytes ( archive , Ġentry ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ // Ġ***************************************************************** ** Ċ ĉ // ĠInterface ĠI Result Saver Ċ ĉ // Ġ***************************************************************** ** ĊĊ ĉ override Ġfun Ġsave Folder ( path : ĠString ) Ġ{ Ċĉ ĉ val Ġdir Ġ= ĠFile ( getAbsolutePath ( path )) Ċĉ ĉ if Ġ(!( dir . mkdir s () Ġ|| Ġdir . isDirectory )) Ġ{ Ċĉĉ ĉ throw ĠRuntimeException (" Cannot Ġcreate Ġdirectory Ġ$ dir ") Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġclose Archive ( path : ĠString , Ġarchive Name : ĠString ) Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( getAbsolutePath ( path ), Ġarchive Name ). path Ċĉ ĉ try Ġ{ Ċĉĉ ĉ map Archive Entries . remove ( file ) Ċĉĉ ĉ map Archive Streams . remove ( file )?. close () Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ De compiler Context . getLogger (). write Message (" Cannot Ġclose Ġ$ file ", ĠIF ern flower Logger . Severity . WARN ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġcopy File ( source : ĠString , Ġpath : ĠString , Ġentry Name : ĠString ) Ġ{ Ċĉ ĉ try Ġ{ Ċĉĉ ĉ Interpreter Util . copy File ( File ( source ), ĠFile ( getAbsolutePath ( path ), Ġentry Name )) Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ De compiler Context . getLogger (). write Message (" Cannot Ġcopy Ġ$ source Ġto Ġ$ entry Name ", Ġex ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġcopy Entry ( source : ĠString , Ġpath : ĠString , Ġarchive Name : ĠString , Ġentry Name : ĠString ) Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( getAbsolutePath ( path ), Ġarchive Name ). path ĊĊĉ ĉ if Ġ(! check Entry ( entry Name , Ġfile )) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } ĊĊĉ ĉ try Ġ{ Ċĉĉ ĉ Zip File ( File ( source )). use Ġ{ Ġsrc Archive Ġ-> Ċĉĉĉ ĉ val Ġentry Ġ= Ġsrc Archive . getEntry ( entry Name ) Ċĉĉĉ ĉ if Ġ( entry Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ src Archive . getInputStream ( entry ). use Ġ{ Ġ` in ` Ġ-> Ċĉĉĉĉĉ ĉ val Ġout Ġ= Ġmap Archive Streams [ file ] !! Ċĉĉĉĉĉ ĉ out . put Next Entry ( Zip Entry ( entry Name )) Ċĉĉĉĉĉ ĉ Interpreter Util . copy Stream (` in `, Ġout ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ val Ġmessage Ġ= Ġ" Cannot Ġcopy Ġentry Ġ$ entry Name Ġfrom Ġ$ source Ġto Ġ$ file " Ċĉĉ ĉ De compiler Context . getLogger (). write Message ( message , Ġex ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġsave Class Entry ( path : ĠString , Ġarchive Name : ĠString , Ġqualified Name : ĠString ?, Ġentry Name : ĠString , Ġcontent : ĠString ?) Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( getAbsolutePath ( path ), Ġarchive Name ). path ĊĊĉ ĉ if Ġ(! check Entry ( entry Name , Ġfile )) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } ĊĊĉ ĉ try Ġ{ Ċĉĉ ĉ val Ġout Ġ= Ġmap Archive Streams [ file ] !! Ċĉĉ ĉ out . put Next Entry ( Zip Entry ( entry Name )) Ċĉĉ ĉ if Ġ( content Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ out . write ( content . toByteArray ( StandardCharsets . UTF _ 8 )) Ċĉĉ ĉ } Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ val Ġmessage Ġ= Ġ" Cannot Ġwrite Ġentry Ġ$ entry Name Ġto Ġ$ file " Ċĉĉ ĉ De compiler Context . getLogger (). write Message ( message , Ġex ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġcreate Archive ( path : ĠString , Ġarchive Name : ĠString , Ġmanifest : ĠManifest ?) Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( getAbsolutePath ( path ), Ġarchive Name ) Ċĉ ĉ try Ġ{ Ċĉĉ ĉ if Ġ(!( file . createNew File () Ġ|| Ġfile . isFile )) Ġ{ Ċĉĉĉ ĉ throw ĠIOException (" Cannot Ġcreate Ġfile Ġ$ file ") Ċĉĉ ĉ } ĊĊĉĉ ĉ val Ġfile Stream Ġ= ĠFileOutputStream ( file ) Ċĉĉ ĉ val Ġzip Stream Ġ= Ġmanifest ?. let Ġ{ ĠJar OutputStream ( file Stream , Ġit ) Ġ} Ġ?: ĠZip OutputStream ( file Stream ) Ċĉĉ ĉ map Archive Streams [ file . path ] Ġ= Ġzip Stream Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ De compiler Context . getLogger (). write Message (" Cannot Ġcreate Ġarchive Ġ$ file ", Ġex ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġsave Class File ( path : ĠString , Ġqualified Name : ĠString , Ġentry Name : ĠString , Ġcontent : ĠString , Ġmapping : ĠInt Array ) Ġ{ Ċĉ ĉ val Ġfile Ġ= ĠFile ( getAbsolutePath ( path ), Ġentry Name ) Ċĉ ĉ try Ġ{ Ċĉĉ ĉ OutputStream Writer ( File OutputStream ( file ), ĠStandard Charsets . UTF _ 8 ). use Ġ{ Ġout Ġ-> Ġout . write ( content ) Ġ} Ċĉ ĉ } Ġcatch Ġ( ex : ĠIOException ) Ġ{ Ċĉĉ ĉ De compiler Context . getLogger (). write Message (" Cannot Ġwrite Ġclass Ġfile Ġ$ file ", Ġex ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġsave Dir Entry ( path : ĠString , Ġarchive Name : ĠString , Ġentry Name : ĠString ) Ġ{ Ċĉ ĉ save Class Entry ( path , Ġarchive Name , Ġnull , Ġentry Name , Ġnull ) Ċ ĉ } ĊĊ Ċ } Ċ