/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . Ġand ĠKotlin ĠProgramming ĠLanguage Ġcontributors . Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe Ġlicense / LICENSE . txt Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . fir Ċ Ċ import Ġcom . intellij . openapi . util . Text Range Ċ import Ġorg . jetbrains . kotlin . diagnostics . Diagnostic Utils Ċ import Ġorg . jetbrains . kotlin . fir . analysis . diagnostics . F ir Diagnostic Ċ import Ġorg . jetbrains . kotlin . fir . analysis . diagnostics . F ir Light Diagnostic Ċ import Ġorg . jetbrains . kotlin . fir . declarations . F ir File Ċ import Ġorg . jetbrains . kotlin . psi . Kt File Ċ import Ġorg . jetbrains . kotlin . test . In Text Directives Utils Ċ import Ġorg . jetbrains . kotlin . test . Kotlin TestUtils Ċ import Ġjava . io . File Ċ import Ġkotlin . math . abs Ċ Ċ abstract Ġclass ĠAbstract F ir Diagnostics With Light Tree Test Ġ: ĠAbstract F ir Diagnostics Test () Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġdo Test ( filePath : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= Ġcreate Test File From Path ( filePath ) ĊĠĠĠĠĠĠĠ Ġval Ġexpected Text Ġ= ĠKotlin TestUtils . do Load File ( file ) ĊĠĠĠĠĠĠĠ Ġif Ġ( In Text Directives Utils . is Directive Defined ( expected Text , Ġ"// ĠIG NORE _ LIGHT _ TREE ")) Ġreturn ĊĊĠĠĠĠĠĠĠ Ġsuper . do Test ( filePath ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġval Ġuse Light Tree : ĠBoolean ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġtrue ĊĊĠĠĠ Ġoverride Ġfun Ġcheck Diagnostics ( file : ĠFile , Ġtest Files : ĠList < Test File >, Ġfir Files : ĠList < F ir File >) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfile To Diagnostics Ġ= Ġcollect Diagnostics ( fir Files ) ĊĠĠĠĠĠĠĠ Ġval Ġmissing Diagnostics Ġ= Ġmutable ListOf < Missing Diagnostic >() ĊĠĠĠĠĠĠĠ Ġfor Ġ( test File Ġin Ġtest Files ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfir File Ġ= Ġfir Files . first OrNull Ġ{ Ġit . name Ġ== Ġtest File . name Ġ} Ġ?: Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkt File Ġ= Ġtest File . kt File !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbasic Diagnostics Ġ= Ġfile To Diagnostics [ fir File ] Ġ?: Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdebug Info Diagnostics : ĠList < F ir Diagnostic <* >> Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcollect Debug Info Diagnostics ( fir File , Ġtest File . diag no sed Ranges To Diagnostic Names ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdiagnostics Ġ= Ġbasic Diagnostics Ġ+ Ġdebug Info Diagnostics ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Diagnostics Ġ= Ġdiagnostics . groupBy Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequire ( it Ġis ĠF ir Light Diagnostic ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . element . start Offset ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. map Values Ġ{ Ġ(_, Ġdiagnostics ) Ġ-> Ġdiagnostics . map Ġ{ Ġit . factory . name Ġ}. count Entries () Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexisting Diagnostics Ġ= Ġtest File . diag no sed Ranges . groupBy Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . start ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. map Values Ġ{ Ġ(_, Ġranges ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġranges . flatMap Ġ{ Ġdiag no sed Range Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdiag no sed Range . get Diagnostics (). filter Not Ġ{ Ġit . name . contains (" DEBUG _ INFO _ ") Ġ}. map Ġ{ Ġit . name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. count Entries () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( start Offset Ġin Ġactual Diagnostics . keys Ġ+ Ġexisting Diagnostics . keys ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexpected Ġ= Ġexisting Diagnostics [ start Offset ] Ġ?: Ġempty Map () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Ġ= Ġactual Diagnostics [ start Offset ] Ġ?: Ġempty Map () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( name Ġin Ġexpected . keys Ġ+ Ġactual . keys ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexpected Count Ġ= Ġexpected [ name ] Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual Count Ġ= Ġactual [ name ] Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( expected Count Ġ!= Ġactual Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmissing Diagnostics Ġ+= ĠMissing Diagnostic ( start Offset , Ġname , Ġexpected Count Ġ- Ġactual Count , Ġkt File ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( missing Diagnostics . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġwas Expected Ġ= Ġmissing Diagnostics . filter Ġ{ Ġit . kind Ġ== ĠMissing Diagnostic . Kind . Was Expected Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Actual Ġ= Ġmissing Diagnostics . filter Ġ{ Ġit . kind Ġ== ĠMissing Diagnostic . Kind . Is Actual Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( was Expected . sum By Ġ{ Ġit . count Ġ} Ġ== Ġis Actual . sum By Ġ{ Ġit . count Ġ}) Ġreturn ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġbuild String Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfun ĠMissing Diagnostic . errorMessage (): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġposition Ġ= ĠDiagnostic Utils . getLine And Column In Psi File ( kt File , ĠText Range ( start Offset , Ġstart Offset Ġ+ Ġ 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠI Ġdon 't Ġknow Ġwhy Ġbut Ġsomehow Ġline Ġis Ġgreater Ġfor Ġ 3 Ġthan Ġline Ġin Ġreal Ġfile ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ" Ġ Ġ$ count Ġof Ġ$ name Ġat Ġ${ position . line Ġ- Ġ 3 }:${ position . column }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( was Expected . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ln (" Some Ġdiagnostics Ġwas Ġexpected :") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwas Expected . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ln ( it . errorMessage ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Actual . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ln (" Some Ġnew Ġdiagnostics :") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Actual . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ln ( it . errorMessage ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkotlin . test . fail ( message ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġ< T > ĠList < T >. count Entries (): ĠMap < T , ĠInt > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġgroup By Ġ{ Ġit Ġ}. map Values Ġ{ Ġ(_, Ġvalue ) Ġ-> Ġvalue . size Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠMissing Diagnostic ( val Ġstart Offset : ĠInt , Ġval Ġname : ĠString , Ġdiff : ĠInt , Ġkt File : ĠK t File ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġkind : ĠKind Ġ= Ġif Ġ( diff Ġ> Ġ 0 ) ĠKind . Was Expected Ġelse ĠKind . Is Actual ĊĠĠĠĠĠĠĠ Ġval Ġcount : ĠInt Ġ= Ġabs ( diff ) ĊĊĠĠĠĠĠĠĠ Ġenum Ġclass ĠKind Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWas Expected , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠIs Actual ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ