/* Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠMIT Ġlicense Ġthat Ġcan Ġbe Ċ Ġ* Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . rust . ide . utils Ċ Ċ import Ġcom . intellij . psi . Psi Comment Ċ import Ġcom . intellij . psi . Psi Element Ċ import Ġcom . intellij . psi . Psi File Ċ import Ġcom . intellij . psi . Psi WhiteSpace Ċ import Ġcom . intellij . psi . util . Psi Tree Util Ċ import Ġcom . intellij . psi . util . Psi Util Core Ċ import Ġorg . rust . lang . core . psi . Rs Block Ċ import Ġorg . rust . lang . core . psi . Rs Expr Ċ import Ġorg . rust . lang . core . psi . Rs File Ċ import Ġorg . rust . lang . core . psi . Rs Stmt Ċ import Ġorg . rust . lang . core . psi . ext . ancestor Or Self Ċ import Ġorg . rust . lang . core . psi . ext . end Offset Ċ import Ġorg . rust . lang . core . psi . ext . start Offset Ċ Ċ fun Ġfind Expression At Caret ( file : ĠRs File , Ġoffset : ĠInt ): ĠRs Expr ? Ġ{ ĊĠĠĠ Ġval Ġexpr Ġ= Ġfile . expression At Offset ( offset ) ĊĠĠĠ Ġval Ġexpr Before Ġ= Ġfile . expression At Offset ( offset Ġ- Ġ 1 ) ĊĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġexpr Ġ== Ġnull Ġ-> Ġexpr Before ĊĠĠĠĠĠĠĠ Ġexpr Before Ġ== Ġnull Ġ-> Ġexpr ĊĠĠĠĠĠĠĠ ĠPsi Tree Util . is Ancestor ( expr , Ġexpr Before , Ġfalse ) Ġ-> Ġexpr Before ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġexpr ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun ĠRs File . expression At Offset ( offset : ĠInt ): ĠRs Expr ? Ġ= ĊĠĠĠ Ġfind ElementAt ( offset )?. ancestor Or Self () ĊĊ Ċ /** Ċ Ġ* ĠFinds Ġtop - most Ġ[ Rs Expr ] Ġwithin Ġselected Ġrange . Ċ Ġ* ĠSupports Ġsuch Ġcases : Ġ` ident & lt ; if & gt ; ier ` Ġ( or Ġkeyword Ġif Ġapplicable ), Ċ Ġ* Ġ`& lt ;& nbsp ;& nbsp ;& nbsp ; expression & nbsp ;& nbsp ;& nbsp ;& gt ; `. Ċ Ġ*/ Ċ fun Ġfind Expression InRange ( file : ĠPsi File , Ġstart Offset : ĠInt , Ġend Offset : ĠInt ): ĠRs Expr ? Ġ{ ĊĠĠĠ Ġval Ġ( element 1 , Ġelement 2 ) Ġ= Ġfile . getElement Range ( start Offset , Ġend Offset ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠ Ġ// ĠGet Ġcommon Ġexpression Ġparent . ĊĠĠĠ Ġvar Ġparent Ġ= ĠPsi Tree Util . find Common Parent ( element 1 , Ġelement 2 ) Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġparent Ġ= Ġparent . ancestor Or Self < Rs Expr >() Ġ?: Ġreturn Ġnull ĊĊĠĠĠ Ġ// ĠIf Ġour Ġparent 's Ġdee pe st Ġfirst Ġchild Ġis Ġelement 1 Ġand Ġdee pe st Ġlast Ġ- Ġelement Ġ 2 , ĊĠĠĠ Ġ// Ġthen Ġis Ġis Ġcompletely Ġwithin Ġselection , Ġso Ġthis Ġis Ġour Ġs ought Ġexpression . ĊĠĠĠ Ġif Ġ( element 1 Ġ== ĠPsi Tree Util . get Dee pe st First ( parent ) Ġ&& Ġelement 2 Ġ== ĠPsi Tree Util . get Dee pe st Last ( element 2 )) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġparent ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġnull Ċ } Ċ Ċ // ĠFIXME : ĠMaybe Ġitems Ġare Ġok ? Ċ // ĠFIXME : ĠWhat Ġabout Ġmacros ? Ċ /** Ċ Ġ* ĠFinds Ġstatements Ġ( most ly Ġ[ Rs Stmt ] s , Ġ[ Psi Comment ] s Ġand Ġ[ Rs Expr ] Ċ Ġ* Ġas Ġreturn Ġexpression , Ġdoesn 't Ġallow Ġattrs Ġand Ġitems ) Ġwithin Ġselected Ġrange . Ċ Ġ*/ Ċ fun Ġfind Statements InRange ( file : ĠPsi File , Ġstart Offset : ĠInt , Ġend Offset : ĠInt ): ĠArray < out ĠPsi Element > Ġ{ ĊĠĠĠ Ġvar Ġ( element 1 , Ġelement 2 ) Ġ= Ġfile . getElement Range ( start Offset , Ġend Offset ) Ġ?: Ġreturn Ġempty Array () ĊĊĠĠĠ Ġ// ĠFind Ġparent Ġof Ġselected Ġstatement Ġlist Ġ( synt act ically Ġonly ĠRs Block Ġis Ġpossible ) ĊĠĠĠ Ġval Ġparent Ġ= ĠPsi Tree Util . find Common Parent ( element 1 , Ġelement 2 ) ĊĠĠĠĠĠĠĠ Ġ? . ancestor Or Self < Rs Block >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġempty Array () ĊĊĠĠĠ Ġ// ĠFind Ġedge Ġdirect Ġchildren Ġof Ġparent Ġwithin Ġselection . ĊĠĠĠ Ġ// Ġelement 1 Ġhas Ġto Ġbe Ġfirst Ġleaf Ġof Ġleft Ġchild , Ġand Ġelement 2 Ġ- Ġlast Ġleaf Ġof Ġright Ġchild ĊĠĠĠ Ġval Ġreal Start Offset Ġ= Ġelement 1 . start Offset ĊĠĠĠ Ġval Ġreal End Offset Ġ= Ġelement 2 . end Offset ĊĊĠĠĠ Ġelement 1 Ġ= Ġelement 1 . get Top most Parent Inside ( parent ) ĊĠĠĠ Ġif Ġ( real Start Offset Ġ!= Ġelement 1 . start Offset ) Ġreturn Ġempty Array () ĊĊĠĠĠ Ġelement 2 Ġ= Ġelement 2 . get Top most Parent Inside ( parent ) ĊĠĠĠ Ġif Ġ( real End Offset Ġ!= Ġelement 2 . end Offset ) Ġreturn Ġempty Array () ĊĊĠĠĠ Ġ// ĠNow Ġcollect Ġnon - whitespace Ġchildren Ġof Ġparent Ġbetween Ġ( inclusive ) Ġelement 1 Ġand Ġelement 2 ĊĠĠĠ Ġval Ġelements Ġ= Ġcollect Elements ( element 1 , Ġelement 2 . next Sibling ) Ġ{ Ġit Ġ! is ĠPsi WhiteSpace Ġ} ĊĊĠĠĠ Ġ// ĠFinally Ġcheck Ġif Ġfound Ġelements Ġmeet Ġrequirements , Ġand Ġreturn Ġresult ĊĠĠĠ Ġelements . forEach Indexed Ġ{ Ġidx , Ġelement Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ(!( element Ġis ĠRs Stmt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġ( idx Ġ== Ġelements . size Ġ- Ġ 1 Ġ&& Ġelement Ġis ĠRs Expr ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġelement Ġis ĠPsi Comment ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ)) Ġreturn Ġempty Array () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġelements Ċ } ĊĊ Ċ /** Ċ Ġ* ĠFinds Ġtwo Ġedge Ġleaf ĠP SI Ġelements Ġwithin Ġgiven Ġrange . Ċ Ġ*/ Ċ fun ĠPsi File . getElement Range ( start Offset : ĠInt , Ġend Offset : ĠInt ): ĠPair < Psi Element , ĠPsi Element >? Ġ{ ĊĠĠĠ Ġval Ġelement 1 Ġ= Ġfind ElementAt Ignore Whitespace Before ( start Offset ) Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġelement 2 Ġ= Ġfind ElementAt Ignore Whitespace After ( end Offset Ġ- Ġ 1 ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠ Ġ// ĠElements Ġhave Ġcros sed Ġ( for Ġinstance Ġwhen Ġselection Ġwas Ġinside Ġsingle Ġwhitespace Ġblock ) ĊĠĠĠ Ġif Ġ( element 1 . start Offset Ġ>= Ġelement 2 . end Offset ) Ġreturn Ġnull ĊĊĠĠĠ Ġreturn Ġelement 1 Ġto Ġelement 2 Ċ } Ċ Ċ /** Ċ Ġ* ĠFinds Ġa Ġleaf ĠP SI Ġelement Ġat Ġthe Ġspecified Ġoffset Ġfrom Ġthe Ġstart Ġof Ġthe Ġtext Ġrange Ġof Ġthis Ġnode . Ċ Ġ* ĠIf Ġfound Ġelement Ġis Ġwhitespace , Ġreturns Ġits Ġnext Ġnon - whitespace Ġsibling . Ċ Ġ*/ Ċ fun ĠPsi File . findElement At Ignore Whitespace Before ( offset : ĠInt ): ĠPsi Element ? Ġ{ ĊĠĠĠ Ġval Ġelement Ġ= Ġfind ElementAt ( offset ) ĊĠĠĠ Ġif Ġ( element Ġis ĠPsi WhiteSpace ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfind ElementAt ( element . getText Range (). end Offset ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġelement Ċ } Ċ Ċ /** Ċ Ġ* ĠFinds Ġa Ġleaf ĠP SI Ġelement Ġat Ġthe Ġspecified Ġoffset Ġfrom Ġthe Ġstart Ġof Ġthe Ġtext Ġrange Ġof Ġthis Ġnode . Ċ Ġ* ĠIf Ġfound Ġelement Ġis Ġwhitespace , Ġreturns Ġits Ġprevious Ġnon - whitespace Ġsibling . Ċ Ġ*/ Ċ fun ĠPsi File . findElement At Ignore Whitespace After ( offset : ĠInt ): ĠPsi Element ? Ġ{ ĊĠĠĠ Ġval Ġelement Ġ= Ġfind ElementAt ( offset ) ĊĠĠĠ Ġif Ġ( element Ġis ĠPsi WhiteSpace ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfind ElementAt ( element . getText Range (). start Offset Ġ- Ġ 1 ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġelement Ċ } Ċ Ċ /** Ċ Ġ* ĠFinds Ġchild Ġof Ġ[ parent ] Ġof Ġwhich Ġgiven Ġelement Ġis Ġdesc endant . Ċ Ġ*/ Ċ private Ġfun ĠPsi Element . get Top most Parent Inside ( parent : ĠPsi Element ): ĠPsi Element Ġ{ ĊĠĠĠ Ġif Ġ( parent Ġ== Ġthis ) Ġreturn Ġthis ĊĊĠĠĠ Ġvar Ġelement Ġ= Ġthis ĊĠĠĠ Ġwhile Ġ( parent Ġ!= Ġelement . parent ) Ġ{ ĊĠĠĠĠĠĠĠ Ġelement Ġ= Ġelement . parent ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġelement Ċ } Ċ Ċ private Ġfun Ġcollect Elements ( start : ĠPsi Element , Ġstop : ĠPsi Element ?, Ġpred : Ġ( Psi Element ) Ġ-> ĠBoolean ): ĠArray < out ĠPsi Element > Ġ{ ĊĠĠĠ Ġcheck ( stop Ġ== Ġnull Ġ|| Ġstart . parent Ġ== Ġstop . parent ) ĊĊĠĠĠ Ġval Ġpsi Seq Ġ= Ġgenerate Sequence ( start ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( it . next Sibling Ġ== Ġstop ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . next Sibling ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn ĠPsi Util Core . to Psi Element Array ( psi Seq . filter ( pred ). toList ()) Ċ } Ċ