// Ġ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 Ġcom . intellij . psi . impl . search Ċ Ċ import Ġcom . intellij . model . search . Search Parameters Ċ import Ġcom . intellij . model . search . Searcher Ċ import Ġcom . intellij . model . search . impl .* Ċ import Ġcom . intellij . openapi . progress . Empty Progress Indicator Ċ import Ġcom . intellij . openapi . progress . Progress Indicator Ċ import Ġcom . intellij . openapi . progress . Progress Indicator Provider Ċ import Ġcom . intellij . openapi . progress . Progress Manager Ċ import Ġcom . intellij . openapi . project . D umb Service Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . openapi . util . Class Extension Ċ import Ġcom . intellij . openapi . util . Comp utable Ċ import Ġcom . intellij . psi . Psi Element Ċ import Ġcom . intellij . psi . impl . cache . impl . id . Id Index Entry Ċ import Ġcom . intellij . psi . search . Local Search Scope Ċ import Ġcom . intellij . psi . search . Psi Search Helper Ċ import Ġcom . intellij . psi . search . Search Session Ċ import Ġcom . intellij . util . Processor Ċ import Ġcom . intellij . util . Query Ċ import Ġcom . intellij . util . Smart List Ċ import Ġcom . intellij . util . text . String Searcher Ċ import Ġg nu . tro ve . TH ash Map Ċ import Ġorg . jetbrains . annotations . Api Status . Internal Ċ import Ġjava . util .* Ċ import Ġkotlin . collections . ArrayList Ċ import Ġkotlin . collections . Linked HashMap Ċ import Ġkotlin . collections . component 1 Ċ import Ġkotlin . collections . component 2 Ċ import Ġkotlin . collections . set Ċ Ċ private Ġval Ġsearch ers Extension Ġ= ĠClass Extension < Searcher < *, Ġ* >> (" com . intellij . search er ") Ċ Ċ internal Ġval Ġindicator OrEmpty : ĠProgress Indicator ĊĠ Ġget () Ġ= ĠEmpty Progress Indicator . not N ul lize ( Progress Indicator Provider . getGlobal Progress Indicator ()) ĊĊ Ċ @ Internal Ċ fun Ġ< R > Ġrun Search ( project : ĠProject , Ġquery : ĠQuery < out ĠR >, Ġprocessor : ĠProcessor < in ĠR >): ĠBoolean Ġ{ ĊĠ Ġval Ġprogress Ġ= Ġindicator OrEmpty ĊĠ Ġvar Ġcurrent Queries : ĠCollection < Query < out ĠR >> Ġ= ĠlistOf ( query ) ĊĠ Ġwhile Ġ( current Queries . isNotEmpty ()) Ġ{ ĊĠĠĠ Ġprogress . check Canceled () ĊĠĠĠ Ġval Ġlayer Ġ= Ġbuild Layer ( progress , Ġproject , Ġcurrent Queries ) ĊĠĠĠ Ġwhen Ġ( val Ġlayer Result Ġ= Ġlayer . run Layer ( processor )) Ġ{ ĊĠĠĠĠĠ Ġis ĠLayer Result . Ok Ġ-> Ġcurrent Queries Ġ= Ġlayer Result . sub queries ĊĠĠĠĠĠ Ġis ĠLayer Result . Stop Ġ-> Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĠ Ġreturn Ġtrue Ċ } Ċ Ċ private Ġfun Ġ< R > Ġbuild Layer ( progress : ĠProgress Indicator , Ġproject : ĠProject , Ġqueries : ĠCollection < Query < out ĠR >> ): ĠLayer < out ĠR > Ġ{ ĊĠ Ġval Ġqueue : ĠQueue < Query < out ĠR >> Ġ= ĠArray Deque () ĊĠ Ġqueue . addAll ( queries ) ĊĊĠ Ġval Ġquery Requests Ġ= ĠSmart List < Query Request < *, ĠR >>() ĊĠ Ġval Ġword Requests Ġ= ĠSmart List < Word Request < R >>() ĊĊĠ Ġwhile Ġ( queue . isNotEmpty ()) Ġ{ ĊĠĠĠ Ġprogress . check Canceled () ĊĠĠĠ Ġval Ġquery : ĠQuery < out ĠR > Ġ= Ġqueue . remove () ĊĠĠĠ Ġval Ġprimitives : ĠRequests < R > Ġ= Ġde compose ( query ) ĊĠĠĠ Ġquery Requests . addAll ( primitives . query Requests ) ĊĠĠĠ Ġword Requests . addAll ( primitives . word Requests ) ĊĠĠĠ Ġfor Ġ( parameters Request Ġin Ġprimitives . parameters Requests ) Ġ{ ĊĠĠĠĠĠ Ġprogress . check Canceled () ĊĠĠĠĠĠ Ġhandle Param Request ( progress , Ġparameters Request ) Ġ{ ĊĠĠĠĠĠĠĠ Ġqueue . offer ( it ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġreturn ĠLayer ( project , Ġprogress , Ġquery Requests , Ġword Requests ) Ċ } Ċ Ċ private Ġfun Ġ< B , ĠR > Ġhandle Param Request ( progress : ĠProgress Indicator , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest : ĠParameters Request < B , ĠR >, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġqueue : Ġ( Query < out ĠR >) Ġ-> ĠUnit ) Ġ{ ĊĠ Ġval Ġsearch Requests : ĠCollection < Query < out ĠB >> Ġ= Ġcollect Search Requests ( request . params ) ĊĠ Ġfor Ġ( query : ĠQuery < out ĠB > Ġin Ġsearch Requests ) Ġ{ ĊĠĠĠ Ġprogress . check Canceled () ĊĠĠĠ Ġqueue ( X Query ( query , Ġrequest . transformation )) ĊĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġ< R > Ġcollect Search Requests ( parameters : ĠSearch Parameters < R >): ĠCollection < Query < out ĠR >> Ġ{ ĊĠ Ġreturn ĠD umb Service . getInstance ( parameters . project ). run Read Action In Smart Mode ( Comp utable Ġ{ ĊĠĠĠ Ġif Ġ( parameters . are Valid ()) Ġ{ ĊĠĠĠĠĠ Ġdo Collect Search Requests ( parameters ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġempty List () ĊĠĠĠ Ġ} ĊĠ Ġ}) Ċ } Ċ Ċ private Ġfun Ġ< R > Ġdo Collect Search Requests ( parameters : ĠSearch Parameters < R >): ĠCollection < Query < out ĠR >> Ġ{ ĊĠ Ġval Ġqueries Ġ= ĠArrayList < Query < out ĠR >>() ĊĊĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠ Ġval Ġsearch ers Ġ= Ġsearch ers Extension . for Key ( parameters . java Class ) Ġas ĠList < Searcher < Search Parameters < R >, ĠR >> ĊĠ Ġfor Ġ( search er : ĠSearch er < Search Parameters < R >, ĠR > Ġin Ġsearch ers ) Ġ{ ĊĠĠĠ ĠProgress Manager . check Canceled () ĊĠĠĠ Ġqueries Ġ+= Ġsearch er . collect Search Requests ( parameters ) ĊĠ Ġ} ĊĠ Ġreturn Ġqueries Ċ } Ċ Ċ private Ġsealed Ġclass ĠLayer Result < out ĠT > Ġ{ ĊĠ Ġobject ĠStop Ġ: ĠLayer Result < Nothing >() ĊĠ Ġclass ĠOk < T >( val Ġsub queries : ĠCollection < Query < out ĠT >>) Ġ: ĠLayer Result < T >() Ċ } Ċ Ċ private Ġclass ĠLayer < T >( ĊĠ Ġprivate Ġval Ġproject : ĠProject , ĊĠ Ġprivate Ġval Ġprogress : ĠProgress Indicator , ĊĠ Ġprivate Ġval Ġquery Requests : ĠCollection < Query Request < *, ĠT >>, ĊĠ Ġprivate Ġval Ġword Requests : ĠCollection < Word Request < T >> Ċ ) Ġ{ ĊĊĠ Ġprivate Ġval Ġmy Helper Ġ= ĠPsi Search Helper . getInstance ( project ) Ġas ĠPsi Search Helper Impl ĊĊĠ Ġfun Ġrun Layer ( processor : ĠProcessor < in ĠT >): ĠLayer Result < T > Ġ{ ĊĠĠĠ Ġval Ġsub Queries Ġ= ĠCollections . synchronized List ( ArrayList < Query < out ĠT >> ()) ĊĠĠĠ Ġval Ġx Processor Ġ= ĠProcessor < X Result < T >> Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠ Ġwhen Ġ( result ) Ġ{ ĊĠĠĠĠĠĠĠ Ġis ĠValue Result Ġ-> Ġprocessor . process ( result . value ) ĊĠĠĠĠĠĠĠ Ġis ĠQuery Result Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġsub Queries . add ( result . query ) ĊĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ(! process Query Requests ( progress , Ġquery Requests , Ġx Processor )) Ġ{ ĊĠĠĠĠĠ Ġreturn ĠLayer Result . Stop ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ(! process Word Requests ( x Processor )) Ġ{ ĊĠĠĠĠĠ Ġreturn ĠLayer Result . Stop ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠLayer Result . Ok ( sub Queries ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġprocess Word Requests ( processor : ĠProcessor < in ĠX Result < T >> ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( word Requests . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġall Requests : ĠCollection < Request And Processors > Ġ= Ġdistribute Word Requests ( processor ) ĊĠĠĠ Ġval Ġglobals Ġ= ĠSmart List < Request And Processors >() ĊĠĠĠ Ġval Ġlocals Ġ= ĠSmart List < Request And Processors >() ĊĠĠĠ Ġfor Ġ( request And Processor : ĠRequest And Processors Ġin Ġall Requests ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( request And Processor . request . search Scope Ġis ĠLocal Search Scope ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlocals Ġ+= Ġrequest And Processor ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġglobals Ġ+= Ġrequest And Processor ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġprocess Global Requests ( globals ) ĊĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġprocess Local Requests ( locals ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġdistribute Word Requests ( processor : ĠProcessor < in ĠX Result < T >> ): ĠCollection < Request And Processors > Ġ{ ĊĠĠĠ Ġval Ġthe Map Ġ= ĠLinkedHashMap < ĊĠĠĠĠĠ ĠWord Request Info , ĊĠĠĠĠĠ ĠPair < ĊĠĠĠĠĠĠĠ ĠMutable Collection < Occurrence Processor >, ĊĠĠĠĠĠĠĠ ĠMutable Map < Language Info , ĠMutable Collection < Occurrence Processor >> ĊĠĠĠĠĠĠĠ Ġ> ĊĠĠĠĠĠ Ġ> () ĊĊĠĠĠ Ġfor Ġ( word Request : ĠWord Request < T > Ġin Ġword Requests ) Ġ{ ĊĠĠĠĠĠ Ġprogress . check Canceled () ĊĠĠĠĠĠ Ġval Ġby Request Ġ= Ġthe Map . get Or Put ( word Request . search Word Request ) Ġ{ ĊĠĠĠĠĠĠĠ ĠPair ( Smart List (), ĠLinkedHashMap ()) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġoccurrence Processors : ĠMutable Collection < Occurrence Processor > Ġ= Ġwhen Ġ( val Ġinjection Info Ġ= Ġword Request . injection Info ) Ġ{ ĊĠĠĠĠĠĠĠ ĠInjection Info . No Injection Ġ-> Ġby Request . first ĊĠĠĠĠĠĠĠ Ġis ĠInjection Info . In Injection Ġ-> Ġby Request . second . get Or Put ( injection Info . language Info ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠSmart List () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġoccurrence Processors Ġ+= Ġword Request . occ urrence Processor ( processor ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġthe Map . map Ġ{ Ġ( word Request : ĠWord Request Info , Ġby Request ) Ġ-> ĊĠĠĠĠĠ Ġprogress . check Canceled () ĊĠĠĠĠĠ Ġval Ġ( host Processors , Ġinjection Processors ) Ġ= Ġby Request ĊĠĠĠĠĠ ĠRequest And Processors ( word Request , ĠRequest Processors ( host Processors , Ġinjection Processors )) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġprocess Global Requests ( globals : ĠCollection < Request And Processors >): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( globals . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġif Ġ( globals . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġprocess Single Request ( globals . first ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġglobals Ids : ĠMap < Set < Id Index Entry >, ĠList < Word Request Info >> Ġ= Ġglobals . groupBy ( ĊĠĠĠĠĠ Ġ{ Ġ( request : ĠWord Request Info , Ġ_) Ġ-> ĠPsi Search Helper Impl . get Word Entries ( request . word , Ġrequest . is Case Sensitive ). toSet () Ġ}, ĊĠĠĠĠĠ Ġ{ Ġ( request : ĠWord Request Info , Ġ_) Ġ-> Ġprogress . check Canceled (); Ġrequest Ġ} ĊĠĠĠ Ġ) ĊĠĠĠ Ġreturn Ġmy Helper . process Global Requests ( globals Ids , Ġprogress , Ġscope Processors ( globals )) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġscope Processors ( globals : ĠCollection < Request And Processors >): ĠMap < Word Request Info , ĠProcessor < in ĠPsi Element >> Ġ{ ĊĠĠĠ Ġval Ġresult Ġ= ĠT HashMap < Word Request Info , ĠProcessor < in ĠPsi Element >>() ĊĠĠĠ Ġfor Ġ( request And Processors : ĠRequest And Processors Ġin Ġglobals ) Ġ{ ĊĠĠĠĠĠ Ġprogress . check Canceled () ĊĠĠĠĠĠ Ġresult [ request And Processors . request ] Ġ= Ġscope Processor ( request And Processors ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġscope Processor ( request And Processors : ĠRequest And Processors ): ĠProcessor < in ĠPsi Element > Ġ{ ĊĠĠĠ Ġval Ġ( request : ĠWord Request Info , Ġprocessors : ĠRequest Processors ) Ġ= Ġrequest And Processors ĊĠĠĠ Ġval Ġsearch er Ġ= ĠString Searcher ( request . word , Ġrequest . is Case Sensitive , Ġtrue , Ġfalse ) ĊĠĠĠ Ġval Ġadapted Ġ= ĠMy Bulk Occurrence Processor ( project , Ġprocessors ) ĊĠĠĠ Ġreturn ĠPsi Search Helper Impl . local Processor ( search er , Ġadapted ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġprocess Local Requests ( locals : ĠCollection < Request And Processors >): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( locals . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġfor Ġ( request And Processors : ĠRequest And Processors Ġin Ġlocals ) Ġ{ ĊĠĠĠĠĠ Ġprogress . check Canceled () ĊĠĠĠĠĠ Ġif Ġ(! process Single Request ( request And Processors )) Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġprocess Single Request ( request And Processors : ĠRequest And Processors ): ĠBoolean Ġ{ ĊĠĠĠ Ġval Ġ( request : ĠWord Request Info , Ġprocessors : ĠRequest Processors ) Ġ= Ġrequest And Processors ĊĠĠĠ Ġval Ġoptions Ġ= ĠEnum Set . of ( Psi Search Helper Impl . Options . PROCESS _ ONLY _ JAVA _ IDENT IFI ERS _ IF _ PO SS IBLE ) ĊĠĠĠ Ġif Ġ( request . is Case Sensitive ) Ġoptions . add ( Psi Search Helper Impl . Options . CASE _ S ENS ITIVE _ SEARCH ) ĊĊĠĠĠ Ġreturn Ġmy Helper . bulk Process Elements With Word ( ĊĠĠĠĠĠ Ġrequest . search Scope , ĊĠĠĠĠĠ Ġrequest . word , ĊĠĠĠĠĠ Ġrequest . search Context , ĊĠĠĠĠĠ Ġoptions , ĊĠĠĠĠĠ Ġrequest . container Name , ĊĠĠĠĠĠ ĠSearch Session (), ĊĠĠĠĠĠ ĠMy Bulk Occurrence Processor ( project , Ġprocessors ) ĊĠĠĠ Ġ) ĊĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġ< R > Ġprocess Query Requests ( progress : ĠProgress Indicator , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequests : ĠCollection < Query Request < *, ĠR >>, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocessor : ĠProcessor < in ĠX Result < R >> ): ĠBoolean Ġ{ ĊĠ Ġif Ġ( requests . isEmpty ()) Ġ{ ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĠ Ġval Ġmap : ĠMap < Query <* >, ĠList < X Transformation < *, ĠR >>> Ġ= Ġrequests . groupBy ({ Ġit . query Ġ}, Ġ{ Ġit . transformation Ġ}) ĊĠ Ġfor Ġ(( query : ĠQuery <* >, Ġtransforms : ĠList < X Transformation < *, ĠR >>) Ġin Ġmap . iterator ()) Ġ{ ĊĠĠĠ Ġprogress . check Canceled () ĊĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠ Ġif Ġ(! run Query Request ( query Ġas ĠQuery < Any >, Ġtransforms Ġas ĠCollection < X Transformation < Any , ĠR >>, Ġprocessor )) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĠ Ġreturn Ġtrue Ċ } Ċ Ċ private Ġfun Ġ< B , ĠR > Ġrun Query Request ( query : ĠQuery < out ĠB >, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransformations : ĠCollection < Transformation < B , ĠR >>, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocessor : ĠProcessor < in ĠR >): ĠBoolean Ġ{ ĊĠ Ġreturn Ġquery . forEach ( fun ( base Value : ĠB ): ĠBoolean Ġ{ ĊĠĠĠ Ġfor Ġ( transformation : ĠTransformation < B , ĠR > Ġin Ġtransformations ) Ġ{ ĊĠĠĠĠĠ Ġfor Ġ( result Value : ĠR Ġin Ġtransformation ( base Value )) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! processor . process ( result Value )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ}) Ċ } Ċ Ċ private Ġdata Ġclass ĠRequest And Processors ( ĊĠ Ġval Ġrequest : ĠWord Request Info , ĊĠ Ġval Ġprocessors : ĠRequest Processors Ċ ) Ċ Ċ internal Ġclass ĠRequest Processors ( ĊĠ Ġval Ġhost Processors : ĠCollection < Occurrence Processor >, ĊĠ Ġval Ġinjection Processors : ĠMap < Language Info , ĠCollection < Occurrence Processor >> Ċ ) Ċ