@@ -16,17 +16,76 @@ import dotty.tools.dotc.core.StdNames
1616import  dotty .tools .dotc .core .Symbols .Symbol 
1717import  dotty .tools .dotc .interactive .Interactive 
1818import  dotty .tools .dotc .interactive .InteractiveDriver 
19+ import  dotty .tools .dotc .util .SourceFile 
1920import  dotty .tools .dotc .util .SourcePosition 
2021import  dotty .tools .pc .utils .InteractiveEnrichments .* 
2122import  dotty .tools .pc .IndexedContext .Result 
2223
2324import  org .eclipse .lsp4j  as  l 
2425
25- final  class  PcInlineValueProviderImpl (
26+ final  class  PcInlineValueProvider (
2627    driver : InteractiveDriver ,
2728    val  params :  OffsetParams 
28- ) extends  WithSymbolSearchCollector [Option [Occurence ]](driver, params)
29-     with  InlineValueProvider : 
29+ ) extends  WithSymbolSearchCollector [Option [Occurence ]](driver, params): 
30+ 
31+   //  We return a result or an error
32+   def  getInlineTextEdits ():  Either [String , List [l.TextEdit ]] = 
33+     defAndRefs() match  {
34+       case  Right ((defn, refs)) => 
35+         val  edits  = 
36+           if  (defn.shouldBeRemoved) {
37+             val  defEdit  =  definitionTextEdit(defn)
38+             val  refsEdits  =  refs.map(referenceTextEdit(defn))
39+             defEdit ::  refsEdits
40+           } else  refs.map(referenceTextEdit(defn))
41+         Right (edits)
42+       case  Left (error) =>  Left (error)
43+     }
44+ 
45+   private  def  referenceTextEdit (
46+       definition : Definition 
47+   )(ref : Reference ):  l.TextEdit  = 
48+     if  (definition.requiresBrackets &&  ref.requiresBrackets)
49+       new  l.TextEdit (
50+         ref.range,
51+         s """ ( ${ref.rhs}) """ 
52+       )
53+     else  new  l.TextEdit (ref.range, ref.rhs)
54+ 
55+   private  def  definitionTextEdit (definition : Definition ):  l.TextEdit  = 
56+     new  l.TextEdit (
57+       extend(
58+         definition.rangeOffsets.start,
59+         definition.rangeOffsets.end,
60+         definition.range
61+       ),
62+       " " 
63+     )
64+ 
65+   private  def  extend (
66+       startOffset : Int ,
67+       endOffset : Int ,
68+       range : l.Range 
69+   ):  l.Range  =  {
70+     val  (startWithSpace, endWithSpace):  (Int , Int ) = 
71+       extendRangeToIncludeWhiteCharsAndTheFollowingNewLine(
72+         text
73+       )(startOffset, endOffset)
74+     val  startPos  =  new  l.Position (
75+       range.getStart.getLine,
76+       range.getStart.getCharacter -  (startOffset -  startWithSpace)
77+     )
78+     val  endPos  = 
79+       if  (endWithSpace -  1  >=  0  &&  text(endWithSpace -  1 ) ==  '\n ' )
80+         new  l.Position (range.getEnd.getLine +  1 , 0 )
81+       else 
82+         new  l.Position (
83+           range.getEnd.getLine,
84+           range.getEnd.getCharacter +  endWithSpace -  endOffset
85+         )
86+ 
87+     new  l.Range (startPos, endPos)
88+   }
3089
3190  val  position :  l.Position  =  pos.toLsp.getStart().nn
3291
@@ -41,7 +100,7 @@ final class PcInlineValueProviderImpl(
41100        Some (Occurence (tree, parent, adjustedPos))
42101      case  _ =>  None 
43102
44-   override   def  defAndRefs ():  Either [String , (Definition , List [Reference ])] = 
103+   def  defAndRefs ():  Either [String , (Definition , List [Reference ])] = 
45104    val  newctx  =  driver.currentCtx.fresh.setCompilationUnit(unit)
46105    val  allOccurences  =  result().flatten
47106    for 
@@ -60,7 +119,6 @@ final class PcInlineValueProviderImpl(
60119      val  defPos  =  definition.tree.sourcePos
61120      val  defEdit  =  Definition (
62121        defPos.toLsp,
63-         adjustRhs(definition.tree.rhs.sourcePos),
64122        RangeOffset (defPos.start, defPos.end),
65123        definitionRequiresBrackets(definition.tree.rhs)(using  newctx),
66124        deleteDefinition
@@ -70,6 +128,18 @@ final class PcInlineValueProviderImpl(
70128    end for 
71129  end  defAndRefs 
72130
131+   private  def  stripIndentPrefix (rhs : String , refIndent : String , defIndent : String ):  String  = 
132+     val  rhsLines  =  rhs.split(" \n " 
133+     rhsLines match 
134+       case  h ::  Nil  =>  rhs
135+       case  h ::  t => 
136+         val  noPrefixH  =  h.stripPrefix(refIndent)
137+         if  noPrefixH.startsWith(" {" then 
138+           noPrefixH ++  t.map(refIndent ++  _.stripPrefix(defIndent)).mkString(" \n " " \n " " " 
139+         else 
140+           (("   " ++  h) ::  t).map(refIndent ++  _.stripPrefix(defIndent)).mkString(" \n " " \n " " " 
141+       case  Nil  =>  rhs
142+ 
73143  private  def  definitionRequiresBrackets (tree : Tree )(using  Context ):  Boolean  = 
74144    NavigateAST 
75145      .untypedPath(tree.span)
@@ -102,12 +172,12 @@ final class PcInlineValueProviderImpl(
102172
103173  end  referenceRequiresBrackets 
104174
105-   private  def  adjustRhs (pos : SourcePosition ) = 
175+   private  def  extendWithSurroundingParens (pos : SourcePosition ) = 
176+     /**  Move `point` by `step` as long as the character at `point` is `acceptedChar` */  
106177    def  extend (point : Int , acceptedChar : Char , step : Int ):  Int  = 
107178      val  newPoint  =  point +  step
108-       if  newPoint >  0  &&  newPoint <  text.length &&  text(
109-           newPoint
110-         ) ==  acceptedChar
179+       if  newPoint >  0  &&  newPoint <  text.length && 
180+         text(newPoint) ==  acceptedChar
111181      then  extend(newPoint, acceptedChar, step)
112182      else  point
113183    val  adjustedStart  =  extend(pos.start, '(' , - 1 )
@@ -139,7 +209,7 @@ final class PcInlineValueProviderImpl(
139209      .exists(e =>  e.isTerm)
140210    def  allreferences  =  allOccurences.filterNot(_.isDefn)
141211    def  inlineAll () = 
142-       makeRefsEdits(allreferences, symbols).map((true , _))
212+       makeRefsEdits(allreferences, symbols, definition ).map((true , _))
143213    if  definition.tree.sourcePos.toLsp.encloses(position)
144214    then  if  defIsLocal then  inlineAll() else  Left (Errors .notLocal)
145215    else 
@@ -150,14 +220,28 @@ final class PcInlineValueProviderImpl(
150220            ref <-  list
151221              .find(_.pos.toLsp.encloses(position))
152222              .toRight(Errors .didNotFindReference)
153-             refEdits <-  makeRefsEdits(List (ref), symbols)
223+             refEdits <-  makeRefsEdits(List (ref), symbols, definition )
154224          yield  (false , refEdits)
155225    end if 
156226  end  getReferencesToInline 
157227
228+   extension  (pos : SourcePosition )
229+     def  startColumnIndentPadding :  String  =  {
230+       val  source  =  pos.source
231+       val  offset  =  pos.start
232+       var  idx  =  source.startOfLine(offset)
233+       val  pad  =  new  StringBuilder 
234+       while  (idx !=  offset &&  idx <  source.content().length &&  source.content()(idx).isWhitespace) {
235+         pad.append(if  (idx <  source.content().length &&  source.content()(idx) ==  '\t ' ) '\t '  else  ' ' )
236+         idx +=  1 
237+       }
238+       pad.result()
239+     }
240+ 
158241  private  def  makeRefsEdits (
159242      refs : List [Occurence ],
160-       symbols : Set [Symbol ]
243+       symbols : Set [Symbol ],
244+       definition : DefinitionTree 
161245  ):  Either [String , List [Reference ]] = 
162246    val  newctx  =  driver.currentCtx.fresh.setCompilationUnit(unit)
163247    def  buildRef (occurrence : Occurence ):  Either [String , Reference ] = 
@@ -178,6 +262,11 @@ final class PcInlineValueProviderImpl(
178262        Right (
179263          Reference (
180264            occurrence.pos.toLsp,
265+             stripIndentPrefix(
266+               extendWithSurroundingParens(definition.tree.rhs.sourcePos),
267+               occurrence.tree.startPos.startColumnIndentPadding,
268+               definition.tree.startPos.startColumnIndentPadding
269+             ),
181270            occurrence.parent.map(p => 
182271              RangeOffset (p.sourcePos.start, p.sourcePos.end)
183272            ),
@@ -196,7 +285,7 @@ final class PcInlineValueProviderImpl(
196285    )
197286  end  makeRefsEdits 
198287
199- end  PcInlineValueProviderImpl 
288+ end  PcInlineValueProvider 
200289
201290case  class  Occurence (tree : Tree , parent : Option [Tree ], pos : SourcePosition ): 
202291  def  isDefn  = 
@@ -205,3 +294,19 @@ case class Occurence(tree: Tree, parent: Option[Tree], pos: SourcePosition):
205294      case  _ =>  false 
206295
207296case  class  DefinitionTree (tree : ValDef , pos : SourcePosition )
297+ 
298+ case  class  RangeOffset (start : Int , end : Int )
299+ 
300+ case  class  Definition (
301+     range : l.Range ,
302+     rangeOffsets : RangeOffset ,
303+     requiresBrackets : Boolean ,
304+     shouldBeRemoved : Boolean 
305+ )
306+ 
307+ case  class  Reference (
308+     range : l.Range ,
309+     rhs : String ,
310+     parentOffsets : Option [RangeOffset ],
311+     requiresBrackets : Boolean 
312+ )
0 commit comments