// ĠCopyright Ġ 2 0 0 0 - 2 0 2 0 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ package Ġorg . jetbrains . intellij . build . dev Server Ċ Ċ import Ġcom . intellij . openapi . util . Pair Ċ import Ġcom . intellij . util . concurrency . App Executor Util Ċ import Ġorg . jetbrains . intellij . build . BuildContext Ċ import Ġorg . jetbrains . intellij . build . impl . Distribution JAR s Builder Ċ import Ġorg . jetbrains . intellij . build . impl . Layout Builder Ċ import Ġorg . jetbrains . intellij . build . impl . Plugin Layout Ċ import Ġorg . jetbrains . intellij . build . impl . project Structure Mapping . Project Structure Mapping Ċ import Ġjava . io . File Ċ import Ġjava . nio . file . Path Ċ import Ġjava . util . concurrent . Executor Ċ import Ġjava . util . concurrent . ExecutorService Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . concurrent . atomic . Atomic Reference Ċ Ċ data Ġclass ĠBuild Item ( val Ġdir : ĠPath , Ġval Ġlayout : ĠPlugin Layout ) Ċ Ċ class ĠPlugin Builder ( private Ġval Ġbuilder : ĠDistribution JAR s Builder , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuild Context : ĠBuild Context , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġout Dir : ĠPath ) Ġ{ ĊĠ Ġprivate Ġval Ġdirty Plugins Ġ= ĠHashSet < Build Item >() ĊĊĠ Ġ@ Synchron ized ĊĠ Ġfun Ġadd Dirty Plugin Dir ( item : ĠBuild Item , Ġreason : ĠAny ) Ġ{ ĊĠĠĠ Ġif Ġ( dirty Plugins . add ( item )) Ġ{ ĊĠĠĠĠĠ ĠLOG . info ("${ item . dir . fileName } Ġis Ġchanged Ġ( at Ġleast Ġ${ if Ġ( reason Ġis ĠPath ) Ġout Dir . rel ativ ize ( reason ) Ġelse Ġreason } Ġis Ġchanged )") ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Synchron ized ĊĠ Ġprivate Ġfun Ġget Dirty Plugins And Clear (): ĠCollection < Build Item > Ġ{ ĊĠĠĠ Ġif Ġ( dirty Plugins . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġempty List () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġresult Ġ= Ġdirty Plugins . toList () ĊĠĠĠ Ġdirty Plugins . clear () ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} ĊĊĠ Ġfun Ġbuild Changed (): ĠString Ġ{ ĊĠĠĠ Ġval Ġdirty Plugin Ġ= Ġget Dirty Plugins And Clear () ĊĠĠĠ Ġif Ġ( dirty Plugin . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġ" All Ġplugins Ġare Ġup Ġto Ġdate " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġlayout Builder Ġ= ĠLayout Builder ( build Context , Ġfalse ) ĊĠĠĠ Ġfor Ġ( plugin Ġin Ġdirty Plugin ) Ġ{ ĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġclear Dir Content ( plugin . dir ) ĊĠĠĠĠĠĠĠ Ġbuild Plugin ( plugin , Ġbuild Context , Ġbuilder , Ġlayout Builder ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġput Ġback Ġ( that 's Ġok Ġto Ġadd Ġalready Ġprocessed Ġplugins Ġ- Ġdoesn 't Ġmatter , Ġno Ġneed Ġto Ġcomp lic ate ) ĊĠĠĠĠĠĠĠ Ġdirty Plugin . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġadd Dirty Plugin Dir ( it , Ġ"< internal Ġerror >") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġ" Plugins Ġ${ dirty Plugin . join ToString Ġ{ Ġit . dir . fileName . toString () Ġ}} Ġwere Ġupdated " ĊĠ Ġ} Ċ } Ċ Ċ fun Ġbuild Plugins (@ Suppress (" Same Parameter Value ") Ġparallel Count : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Context : ĠBuild Context , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplugins : ĠList < Build Item >, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder : ĠDistribution JAR s Builder ) Ġ{ ĊĠ Ġval Ġexecutor : ĠExecutor Ġ= Ġif Ġ( parallel Count Ġ== Ġ 1 ) Ġ{ ĊĠĠĠ ĠExecutor ( Runnable :: run ) ĊĠ Ġ} ĊĠ Ġelse Ġ{ ĊĠĠĠ ĠApp Executor Util . create Bounded Application Pool Executor (" Building ĠPlugins ", Ġparallel Count , Ġfalse ) ĊĠ Ġ} ĊĠ Ġval Ġerror Ref Ġ= ĠAtomic Reference < Throwable >() ĊĊĠ Ġvar Ġshared Layout Builder : ĠLayout Builder ? Ġ= Ġnull ĊĠ Ġfor Ġ( plugin Ġin Ġplugins ) Ġ{ ĊĠĠĠ Ġif Ġ( error Ref . get () Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġbreak ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġbuild Context For Plugin Ġ= Ġif Ġ( parallel Count Ġ== Ġ 1 ) Ġbuild Context Ġelse Ġbuild Context . fork For Parallel Task (" Build Ġ${ plugin . layout . main Module }") ĊĠĠĠ Ġexecutor . execute ( Runnable Ġ{ ĊĠĠĠĠĠ Ġif Ġ( error Ref . get () Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn @ Runnable ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlayout Builder : ĠLayout Builder ĊĠĠĠĠĠĠĠ Ġif Ġ( parallel Count Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( shared Layout Builder Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshared Layout Builder Ġ= ĠLayout Builder ( build Context , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġlayout Builder Ġ= Ġshared Layout Builder !! ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġlayout Builder Ġ= ĠLayout Builder ( build Context For Plugin , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġbuild Plugin ( plugin , Ġbuild Context For Plugin , Ġbuilder , Ġlayout Builder ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( error Ref . compare AndSet ( null , Ġe )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}) ĊĠ Ġ} ĊĊĠ Ġif Ġ( executor Ġis ĠExecutor Service ) Ġ{ ĊĠĠĠ Ġexecutor . shutdown () ĊĠĠĠ Ġexecutor . await Termination ( 5 , ĠTimeUnit . MIN UTES ) ĊĠ Ġ} ĊĊĠ Ġerror Ref . get ()?. let Ġ{ ĊĠĠĠ Ġthrow Ġit ĊĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġbuild Plugin ( plugin : ĠBuild Item , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild Context : ĠBuild Context , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder : ĠDistribution JAR s Builder , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlayout Builder : ĠLayout Builder ) Ġ{ ĊĠ Ġval Ġmain Module Ġ= Ġplugin . layout . main Module ĊĠ Ġif Ġ( skipped Plugin Modules . contains ( main Module )) Ġ{ ĊĠĠĠ Ġreturn ĊĠ Ġ} ĊĊĠ Ġbuild Context . messages . info (" Build Ġ${ main Module }") ĊĠ Ġval Ġgenerated Resources Ġ= Ġget Generated Resources ( plugin . layout , Ġbuild Context ) ĊĊĠ Ġif Ġ( main Module Ġ!= Ġ" intellij . platform . built In Help ") Ġ{ ĊĠĠĠ Ġbuilder . check Output Of Plugin Modules ( main Module , Ġplugin . layout . module J ars , Ġplugin . layout . module Exclude s ) ĊĠ Ġ} ĊĊĠ Ġval Ġmapping Ġ= ĠProject Structure Mapping () ĊĠ Ġbuilder . process Layout ( layout Builder , Ġplugin . layout , Ġplugin . dir . toString (), Ġmapping , Ġtrue , Ġplugin . layout . module J ars , Ġgenerated Resources ) Ċ } Ċ Ċ private Ġfun Ġget Generated Resources ( plugin : ĠPlugin Layout , Ġbuild Context : ĠBuild Context ): ĠList < Pair < File , ĠString >> Ġ{ ĊĠ Ġif Ġ( plugin . resource Generators . isEmpty ()) Ġ{ ĊĠĠĠ Ġreturn Ġempty List () ĊĠ Ġ} ĊĊĠ Ġval Ġgenerated Resources Ġ= ĠArrayList < Pair < File , ĠString >>( plugin . resource Generators . size ) ĊĠ Ġfor Ġ( resource Generator Ġin Ġplugin . resource Generators ) Ġ{ ĊĠĠĠ Ġval ĠclassName Ġ= Ġresource Generator . first :: class . java . name ĊĠĠĠ Ġif Ġ( className Ġ== Ġ" org . jetbrains . intellij . build . shared Indexes . Pre Shared Indexes Generator " Ġ|| ĠclassName . endsWith (" Pre built Indices Resources Generator ")) Ġ{ ĊĠĠĠĠĠ Ġcontinue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġresource File Ġ= Ġresource Generator . first . generate Resources ( build Context ) ĊĠĠĠ Ġif Ġ( resource File Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġgenerated Resources . add ( Pair ( resource File , Ġresource Generator . second )) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĠ Ġreturn Ġgenerated Resources . take If Ġ{ Ġit . isNotEmpty () Ġ} Ġ?: Ġempty List () Ċ }