/* Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠMIT Ġlicense Ġthat Ġcan Ġbe Ċ Ġ* Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . rust . lang . core . stubs Ċ Ċ import Ġcom . intellij . openapi . vfs . V fs Util Core Ċ import Ġcom . intellij . openapi . vfs . Virtual File Ċ import Ġcom . intellij . openapi . vfs . Virtual File Visitor Ċ import Ġcom . intellij . psi . Psi File Ċ import Ġcom . intellij . psi . Psi File Factory Ċ import Ġcom . intellij . psi . Stub Based Psi Element Ċ import Ġcom . intellij . psi . Syntax Tra verser Ċ import Ġcom . intellij . psi . impl . Debug Util Ċ import Ġcom . intellij . psi . impl . source . tree . Lazy Parse ableElement Ċ import Ġcom . intellij . psi . impl . source . tree . Tree Util Ċ import Ġcom . intellij . psi . stubs . Psi File Stub Ċ import Ġcom . intellij . psi . stubs . Stub Tree Ċ import Ġcom . intellij . util . Local Time Counter Ċ import Ġjunit . framework . TestCase Ċ import Ġorg . rust . Rs TestBase Ċ import Ġorg . rust . Rust Project Descriptor Base Ċ import Ġorg . rust . cargo . util . parse Sem Ver Ċ import Ġorg . rust . lang . Rs FileType Ċ import Ġorg . rust . lang . core . psi .* Ċ import Ġorg . rust . lang . core . psi . ext . Rs Attr Proc Macro Owner Ċ import Ġorg . rust . lang . core . psi . ext . desc endants OfType Ċ import Ġorg . rust . lang . core . psi . ext . with Flatten Cfg Attrs Attributes Ċ import Ġorg . rust Performance Tests . fully Refresh Directory In UnitTests Ċ Ċ /** Ċ Ġ* ĠBase Ġclass Ġfor Ġtests Ġto Ġcheck Ġthat Ġblock Ġelements Ġare Ġnot Ġparsed Ġif Ġthey Ġdon 't Ġcontain Ġstub Ġelements Ċ Ġ*/ Ċ abstract Ġclass ĠRs Lazy Block Stub Creation TestBase Ġ: ĠRs TestBase () Ġ{ ĊĊĠĠĠ Ġprotected Ġfun Ġcheck Rust Files ( directory : ĠVirtual File , Ġignored : ĠCollection < String >) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfiles Ġ= Ġcollect Rust Files ( directory , Ġignored ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġnum Blocks Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġnum Parsed Blocks Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġstub bed Proc Macros Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( file Ġin Ġfiles ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġcheck ( value : ĠBoolean , Ġlazy Message : Ġ() Ġ-> ĠAny ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkotlin . check ( value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" file : Ġ$ file \ n ${ lazy Message () }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpsi Ġ= Ġfile . to InMemory Psi File () Ġas ? ĠRs File Ġ?: Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparse File ( psi ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblocks Ġ= ĠSyntax Tra verser . psi Tra verser ( psi ). expand Ġ{ Ġit Ġ! is ĠRs Block Ġ}. filter Is Instance < Rs Block >() ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġblocks . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( it . parent Ġ! is ĠRs Function Ġ|| Ġ! it . is Parsed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Expected ĠNOT Ġparsed Ġblock : Ġ`${ it . text }` " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstub Builder Ġ= ĠRs File Stub . Type . builder ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstub 1 Ġ= Ġstub Builder . build Stub Tree ( psi ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( block Ġin Ġblocks ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block . parent Ġ! is ĠRs Function ) Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnum Blocks ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġskip Child Processing Ġ= Ġstub Builder . skip Child Processing When Building Stub s ( block . node . tree Parent , Ġblock . node ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock Is Parsed Ġ= Ġblock . is Parsed ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( skip Child Processing Ġ== Ġ! block Is Parsed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" San ity Ġcheck Ġfailed ; Ġskip Child Processing Ġ= Ġ$ skip Child Processing , Ġblock Is Parsed Ġ= Ġ$ block Is Parsed " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparse Block ( block ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblock Is Stub bed Ġ= Ġblock . elementType . should Create Stub ( block . node ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstub bed Elements Ġ= Ġblock . desc endants OfType < Stub Based Psi Element <* >>() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . elementType . should Create Stub ( it . node ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcontains Stub bed Elements Ġ= Ġstub bed Elements . isNotEmpty () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠMac ros Ġcan Ġcontain Ġany Ġtokens , Ġso Ġour Ġhe uristic Ġcan Ġgive Ġfalse - posit ives ; Ġallow Ġthem ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparsing Allowed Ġ= Ġcontains Stub bed Elements Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock . desc endants OfType < Rs Macro Call >(). isNotEmpty () Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock . desc endants OfType < Rs Macro >(). isNotEmpty () Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock . desc endants OfType < Rs Macro 2 >(). isNotEmpty () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block Is Parsed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnum Parsed Blocks ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( parsing Allowed ) Ġ{ Ġ" Expected ĠNOT Ġparsed Ġblock Ġafter Ġstub Ġtree Ġbuilding : Ġ`${ block . text }` " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( contains Stub bed Elements ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( block Is Stub bed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Expected Ġ` block . elementType . should Create Stub ` Ġreturning Ġ` true ` Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"( b / c Ġthe Ġblock Ġcontains Ġstub bed Ġelements ), Ġgot Ġ` false ` Ġfor Ġblock : Ġ`${ block . text }` " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck (! contains Stub bed Elements ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Expected ĠPAR SED Ġblock Ġafter Ġstub Ġtree Ġbuilding : Ġ`${ block . text }` \ n " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Because Ġit Ġcontains Ġelements Ġthat Ġshould Ġbe Ġstub bed : Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstub bed Elements . join ToString Ġ{ Ġ"` ${ it . text }` " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck (! block Is Stub bed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Expected Ġ` block . elementType . should Create Stub ` Ġreturning Ġ` false ` Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"( b / c Ġthe Ġblock Ġis Ġnot Ġparsed ), Ġgot Ġ` true ` Ġfor Ġblock : Ġ`${ block . text }` " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCheck Ġstub s Ġare Ġthe Ġsame Ġafter Ġfull Ġre parse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstub 2 Ġ= Ġstub Builder . build Stub Tree ( psi ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTestCase . assertEquals ( Debug Util . stub Tree ToString ( stub 1 ), ĠDebug Util . stub Tree ToString ( stub 2 )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠChecks Ġfor Ġproc Ġmacros : ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( item Ġin Ġpsi . desc endants OfType < Rs Attr Proc Macro Owner >()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( item . proc Macro Attribute Ġ! is ĠProc Macro Attribute . Attr ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"` ${ item . text }` " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstub Tree Ġ= ĠStub Tree ( stub 1 Ġas ĠPsi File Stub <* >) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( stub Ġin Ġstub Tree . plain List ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( stub Ġis ĠRs Attr Proc Macro Owner Stub Base < *> Ġ&& Ġstub . proc Macro Info Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln ( stub . raw Meta Items . with Flatten Cfg Attrs Attributes ( false ). map Ġ{ Ġit . path !!. reference Name Ġ}. toList ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln ( stub . proc Macro Info !!. stub bed Text ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstub bed Proc Macros ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġrustc Version Ġ= Ġ( project Descriptor Ġas ? ĠRust Project Descriptor Base )?. rustc Info ?. version ?. semver ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġdetect Ġsome Ġunexpected Ġproc Ġmacros Ġin Ġstdlib Ġsources Ġfor ĠRust Ġbefore Ġ 1 . 4 3 . ĊĠĠĠĠĠĠĠ Ġ// ĠIgnore Ġthem Ġfor Ġnow ĊĠĠĠĠĠĠĠ Ġval Ġignore Proc Macro Number Check Ġ= Ġrustc Version Ġ!= Ġnull Ġ&& Ġrustc Version Ġ< ĠR UST _ 1 _ 4 3 ĊĠĠĠĠĠĠĠ Ġif Ġ( stub bed Proc Macros Ġ> Ġ 2 0 0 Ġ&& Ġ! ignore Proc Macro Number Check ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerror (" Found Ġtoo Ġlarge Ġnumber Ġof Ġattr Ġproc Ġmacros Ġin Ġstdlib : Ġ$ stub bed Proc Macros . Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" This Ġlikely Ġmeans Ġthat Ġsome Ġnew Ġbuilt - in Ġattrs Ġshould Ġbe Ġadded Ġto Ġ` RS _ BUIL TIN _ ATTRIBUTES ` Ġlist ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprintln (" Blocks : Ġ$ num Blocks , Ġparsed : Ġ$ num Parsed Blocks Ġ(${ ( num Parsed Blocks Ġ* Ġ 1 0 0 0 Ġ/ Ġnum Blocks )/ 1 0 . 0 }% )") ĊĠĠĠĠĠĠĠ Ġprintln (" Stub bed Ġproc Ġmacros : Ġ$ stub bed Proc Macros ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġparse File ( psi : ĠRs File ) Ġ{ Ġ// Ġprofiler Ġhint ĊĠĠĠĠĠĠĠ ĠTree Util . ensure Parsed ( psi . node ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġparse Block ( psi : ĠRs Block ) Ġ{ Ġ// Ġprofiler Ġhint ĊĠĠĠĠĠĠĠ ĠTree Util . ensure Parsed ( psi . node ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcollect Rust Files ( directory : ĠVirtual File , Ġignored : ĠCollection < String >): ĠList < Virtual File > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfiles Ġ= Ġmutable ListOf < Virtual File >() ĊĠĠĠĠĠĠĠ Ġfully Refresh Directory In UnitTests ( directory ) ĊĠĠĠĠĠĠĠ ĠV fs Util Core . visit Children Re cursively ( directory , Ġobject Ġ: ĠVirtual File Visitor < Void >() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġvisit File Ex ( file : ĠVirtual File ): ĠResult Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( file . isDirectory Ġ&& Ġfile . name Ġin Ġignored ) Ġreturn ĠSKIP _ CHILD REN ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( file . fileType Ġ!= ĠRs FileType ) Ġreturn ĠCONTINUE ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfiles Ġ+= Ġfile ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠCONTINUE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ Ġreturn Ġfiles ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠVirtual File . to InMemory Psi File (): ĠPsi File Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠPsi File Factory . getInstance ( project ). create File FromText ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġname , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠfileType , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠString ( contents To ByteArray ()), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLocal Time Counter . currentTime (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval ĠRs Block . is Parsed Ġget () Ġ= Ġ( node Ġas ĠLazy Parse ableElement ). is Parsed ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠBACK COMPAT : ĠRust Ġ 1 . 4 2 ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠR UST _ 1 _ 4 3 Ġ= Ġ" 1 . 4 3 . 0 ". parse Sem Ver () ĊĠĠĠ Ġ} Ċ } Ċ