/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 2 2 Ġ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 Ċ Ċ import Ġcom . intellij . openapi . editor . Document Ċ import Ġcom . intellij . psi . Psi File Ċ import Ġjava . io . InputStream Reader Ċ Ċ interface ĠK t SourceFile Lines Mapping Ġ{ ĊĠĠĠ Ġfun Ġget Line Start Offset ( line : ĠInt ): ĠInt ĊĠĠĠ Ġfun Ġget Line And Column By Offset ( offset : ĠInt ): ĠPair < Int , ĠInt > ĊĠĠĠ Ġfun Ġget Line By Offset ( offset : ĠInt ): ĠInt ĊĊĠĠĠ Ġval Ġlast Offset : ĠInt ĊĠĠĠ Ġval Ġlines Count : ĠInt Ċ } Ċ Ċ class ĠK t Psi SourceFile Lines Mapping ( val Ġpsi File : ĠPsi File ) Ġ: ĠK t SourceFile Lines Mapping Ġ{ ĊĠĠĠ Ġprivate Ġval Ġdocument : ĠDocument ? Ġby Ġlazy Ġ{ Ġpsi File . view Provider . document Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Line Start Offset ( line : ĠInt ): ĠInt Ġ= ĊĠĠĠĠĠĠĠ Ġdocument ?. getLine Start Offset ( line ) Ġ?: Ġ- 1 ĊĊĠĠĠ Ġoverride Ġfun Ġget Line And Column By Offset ( offset : ĠInt ): ĠPair < Int , ĠInt > Ġ= ĊĠĠĠĠĠĠĠ Ġdocument ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠlineNumber Ġ= Ġit . get LineNumber ( offset ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġline Start Offset Ġ= Ġit . getLine Start Offset ( line Number ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlineNumber Ġto Ġoffset Ġ- Ġline Start Offset ĊĠĠĠĠĠĠĠ Ġ} Ġ?: Ġ(- 1 Ġto Ġ- 1 ) ĊĊĠĠĠ Ġoverride Ġfun Ġget Line By Offset ( offset : ĠInt ): ĠInt Ġ= ĊĠĠĠĠĠĠĠ Ġdocument ?. get LineNumber ( offset ) Ġ?: Ġ- 1 ĊĊĠĠĠ Ġoverride Ġval Ġlast Offset : ĠInt ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġdocument ?. text Length Ġ?: Ġ- 1 ĊĊĠĠĠ Ġoverride Ġval Ġlines Count : ĠInt ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġdocument ?. line Count Ġ?: Ġ 0 Ċ } Ċ Ċ open Ġclass ĠK t SourceFile Lines Mapping From Line Start Offsets ( ĊĠĠĠ Ġval Ġline Start Offsets : ĠInt Array , Ġoverride Ġval Ġlast Offset : ĠInt Ċ ) Ġ: ĠK t SourceFile Lines Mapping Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġget Line Start Offset ( line : ĠInt ): ĠInt Ġ= Ġline Start Offsets [ line ] ĊĊĠĠĠ Ġoverride Ġfun Ġget Line And Column By Offset ( offset : ĠInt ): ĠPair < Int , ĠInt > Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠlineNumber Ġ= Ġget Line By Offset ( offset ) ĊĠĠĠĠĠĠĠ Ġif Ġ( line Number Ġ< Ġ 0 ) Ġreturn Ġ- 1 Ġto Ġ- 1 ĊĠĠĠĠĠĠĠ Ġval Ġline Start Offset Ġ= Ġline Start Offsets [ line Number ] ĊĠĠĠĠĠĠĠ Ġreturn ĠlineNumber Ġto Ġoffset Ġ- Ġline Start Offset ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Line By Offset ( offset : ĠInt ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġindex Ġ= Ġline Start Offsets . binary Search ( offset ) ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( index Ġ>= Ġ 0 ) Ġindex Ġelse Ġ- index Ġ- Ġ 2 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġval Ġlines Count : ĠInt ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġline Start Offsets . size Ċ } Ċ Ċ /** Ċ Ġ* Ġ ĠReads Ġfile Ġcontents Ġfrom Ġreader , Ġconverts Ġline Ġsepar ators Ġand Ġcalculates Ġsource Ġlines Ġto Ġfile Ġoffsets Ġmapping Ċ Ġ* Ċ Ġ* Ġ ĠReturns ĠK t SourceFile Lines Mapping Ġand Ġchar Ġsequence Ġ( StringBuilder Ġto Ġavoid Ġprem ature Ġcopying ) Ġcontaining Ġconverted Ġtext Ċ Ġ* Ġ ĠThe Ġsepar ators Ġare Ġconverted Ġsimilar ly Ġto Ġthe Ġcom . intellij . openapi . util . text . StringUtil Rt Ġalgorithms Ċ Ġ*/ Ċ fun ĠInputStreamReader . read SourceFile With Mapping (): ĠPair < CharSequence , ĠK t SourceFile Lines Mapping > Ġ{ ĊĠĠĠ Ġval Ġbuffer Ġ= ĠChar Array ( 2 5 5 ) ĊĠĠĠ Ġvar Ġbuf Length Ġ= Ġ- 1 ĊĠĠĠ Ġvar Ġbuf Pos Ġ= Ġ 0 ĊĠĠĠ Ġvar Ġskip Next Lf Ġ= Ġfalse ĊĊĠĠĠ Ġvar Ġchars Read Ġ= Ġ 0 ĊĊĠĠĠ Ġval Ġline Offsets Ġ= Ġmutable ListOf ( 0 ) Ġ// ĠTODO : Ġconsider Ġusing Ġimplicit Ġfirst Ġline Ġoffset Ġ( needs Ġto Ġbe Ġhandled Ġproperly Ġin ĠIR ) ĊĠĠĠ Ġval Ġsb Ġ= ĠStringBuilder () ĊĊĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( buf Pos Ġ>= Ġbuf Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuf Length Ġ= Ġread ( buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuf Pos Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( buf Length Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġc Ġ= Ġbuffer [ buf Pos ++] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchars Read ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġc Ġ== Ġ'\ n ' Ġ&& Ġskip Next Lf Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline Offsets [ line Offsets . size Ġ- Ġ 1 ] Ġ= Ġchars Read ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġskip Next Lf Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġc Ġ== Ġ'\ n ' Ġ|| Ġc Ġ== Ġ'\ r ' Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb . append ('\ n ') ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline Offsets . add ( chars Read ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġskip Next Lf Ġ= Ġc Ġ== Ġ'\ r ' ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsb . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġskip Next Lf Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġsb Ġto ĠK t SourceFile Lines Mapping From Line Start Offsets ( line Offsets . to IntArray (), Ġchars Read ) Ċ } Ċ Ċ /** Ċ Ġ* ĠExtract s Ġsource Ġlines Ġto Ġoffsets Ġmapping Ġfrom Ġtext Ċ Ġ* Ċ Ġ* Ġintended Ġfor Ġusing Ġmainly Ġin Ġtests , Ġso Ġno Ġcare Ġis Ġtaken Ġabout Ġperformance Ġor Ġpossible Ġcorner Ġcases Ċ Ġ*/ Ċ fun ĠCharSequence . to Source Lines Mapping (): ĠK t SourceFile Lines Mapping Ġ{ ĊĠĠĠ Ġval Ġline Offsets Ġ= Ġmutable ListOf ( 0 ) ĊĠĠĠ Ġvar Ġoffset Ġ= Ġ 0 ĊĠĠĠ Ġfor Ġ( c Ġin Ġthis ) Ġ{ ĊĠĠĠĠĠĠĠ Ġoffset ++ ĊĠĠĠĠĠĠĠ Ġif Ġ( c Ġ== Ġ'\ n ') Ġline Offsets . add ( offset ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠK t SourceFile Lines Mapping From Line Start Offsets ( line Offsets . to IntArray (), Ġoffset ) Ċ } Ċ