@@ -5,8 +5,8 @@ import dotty.tools.dotc.{semanticdb => s}
55import scala .collection .mutable
66import dotty .tools .dotc .semanticdb .Scala3 .{_ , given }
77import SymbolInformation .Kind ._
8-
9- class SymbolInfomationPrinter (symtab : PrinterSymtab ):
8+ import dotty . tools . dotc . util . SourceFile
9+ class SymbolInformationPrinter (symtab : PrinterSymtab ):
1010 val notes = InfoNotes ()
1111 val infoPrinter = InfoPrinter (notes)
1212
@@ -28,8 +28,9 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
2828 val displayName = if sym.isGlobal then sym.desc.value else sym
2929 SymbolInformation (symbol = sym, displayName = displayName)
3030 }
31+ end InfoNotes
3132
32- class InfoPrinter (notes : InfoNotes ) {
33+ class InfoPrinter (notes : InfoNotes ):
3334 private enum SymbolStyle :
3435 case Reference , Definition
3536 def pprint (info : SymbolInformation ): String =
@@ -81,7 +82,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
8182 private def pprintDef (info : SymbolInformation ) =
8283 notes.enter(info)
8384 pprint(info.symbol, SymbolStyle .Definition )
84- private def pprintRef (sym : String ): String = pprint(sym, SymbolStyle .Reference )
85+ def pprintRef (sym : String ): String = pprint(sym, SymbolStyle .Reference )
8586 private def pprintDef (sym : String ): String = pprint(sym, SymbolStyle .Definition )
8687 private def pprint (sym : String , style : SymbolStyle ): String =
8788 val info = notes.visit(sym)
@@ -137,7 +138,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
137138 case _ =>
138139 " <?>"
139140
140- private def pprint (tpe : Type ): String = {
141+ protected def pprint (tpe : Type ): String = {
141142 def prefix (tpe : Type ): String = tpe match
142143 case TypeRef (pre, sym, args) =>
143144 val preStr = pre match {
@@ -204,7 +205,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
204205 case tpe => s " @ ${pprint(tpe)}"
205206 }
206207
207- private def pprint (const : Constant ): String = const match {
208+ protected def pprint (const : Constant ): String = const match {
208209 case Constant .Empty =>
209210 " <?>"
210211 case UnitConstant () =>
@@ -245,7 +246,6 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
245246 s " private[ ${ssym}] "
246247 case ProtectedWithinAccess (ssym) =>
247248 s " protected[ ${ssym}] "
248-
249249 extension (scope : Scope )
250250 private def infos : List [SymbolInformation ] =
251251 if (scope.symlinks.nonEmpty)
@@ -258,8 +258,8 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
258258 case Some (s) => s.infos
259259 case None => Nil
260260 }
261- }
262- end SymbolInfomationPrinter
261+ end InfoPrinter
262+ end SymbolInformationPrinter
263263
264264extension (info : SymbolInformation )
265265 def prefixBeforeTpe : String = {
@@ -280,3 +280,110 @@ object PrinterSymtab:
280280 new PrinterSymtab {
281281 override def info (symbol : String ): Option [SymbolInformation ] = map.get(symbol)
282282 }
283+
284+ def processRange (sb : StringBuilder , range : Range ): Unit =
285+ sb.append('[' )
286+ .append(range.startLine).append(':' ).append(range.startCharacter)
287+ .append(" .." )
288+ .append(range.endLine).append(':' ).append(range.endCharacter)
289+ .append(" ):" )
290+
291+
292+
293+ class SyntheticPrinter (symtab : PrinterSymtab , source : SourceFile ) extends SymbolInformationPrinter (symtab):
294+
295+ def pprint (synth : Synthetic ): String =
296+ val sb = new StringBuilder ()
297+ val notes = InfoNotes ()
298+ val treePrinter = TreePrinter (source, synth.range, notes)
299+
300+ synth.range match
301+ case Some (range) =>
302+ processRange(sb, range)
303+ sb.append(source.substring(range))
304+ case None =>
305+ sb.append(" [):" )
306+ sb.append(" => " )
307+ sb.append(treePrinter.pprint(synth.tree))
308+ sb.toString
309+
310+ extension (source : SourceFile )
311+ private def substring (range : Option [s.Range ]): String =
312+ range match
313+ case Some (range) => source.substring(range)
314+ case None => " "
315+ private def substring (range : s.Range ): String =
316+ /** get the line length of a given line */
317+ def lineLength (line : Int ): Int =
318+ val isLastLine = source.lineToOffsetOpt(line).nonEmpty && source.lineToOffsetOpt(line + 1 ).isEmpty
319+ if isLastLine then source.content.length - source.lineToOffset(line) - 1
320+ else source.lineToOffset(line + 1 ) - source.lineToOffset(line) - 1 // -1 for newline char
321+
322+ val start = source.lineToOffset(range.startLine) +
323+ math.min(range.startCharacter, lineLength(range.startLine))
324+ val end = source.lineToOffset(range.endLine) +
325+ math.min(range.endCharacter, lineLength(range.endLine))
326+ new String (source.content, start, end - start)
327+
328+
329+ // def pprint(tree: s.Tree, range: Option[Range]): String =
330+ class TreePrinter (source : SourceFile , originalRange : Option [Range ], notes : InfoNotes ) extends InfoPrinter (notes):
331+ def pprint (tree : Tree ): String =
332+ val sb = new StringBuilder ()
333+ processTree(tree)(using sb)
334+ sb.toString
335+
336+
337+ private def rep [T ](xs : Seq [T ], seq : String )(f : T => Unit )(using sb : StringBuilder ): Unit =
338+ xs.zipWithIndex.foreach { (x, i) =>
339+ if i != 0 then sb.append(seq)
340+ f(x)
341+ }
342+
343+ private def processTree (tree : Tree )(using sb : StringBuilder ): Unit =
344+ tree match {
345+ case tree : ApplyTree =>
346+ processTree(tree.function)
347+ sb.append(" (" )
348+ rep(tree.arguments, " , " )(processTree)
349+ sb.append(" )" )
350+ case tree : FunctionTree =>
351+ sb.append(" {" )
352+ sb.append(" (" )
353+ rep(tree.parameters, " , " )(processTree)
354+ sb.append(" ) =>" )
355+ processTree(tree.body)
356+ sb.append(" }" )
357+ case tree : IdTree =>
358+ sb.append(pprintRef(tree.symbol))
359+ case tree : LiteralTree =>
360+ sb.append(pprint(tree.constant))
361+ case tree : MacroExpansionTree =>
362+ sb.append(" (`macro-expandee` : `" )
363+ sb.append(pprint(tree.tpe))
364+ sb.append(" )" )
365+ case tree : OriginalTree =>
366+ if (tree.range == originalRange && originalRange.nonEmpty) then
367+ sb.append(" *" )
368+ else
369+ sb.append(" orig(" )
370+ sb.append(source.substring(tree.range))
371+ sb.append(" )" )
372+ case tree : SelectTree =>
373+ processTree(tree.qualifier)
374+ sb.append(" ." )
375+ tree.id match
376+ case Some (tree) => processTree(tree)
377+ case None => ()
378+ case tree : TypeApplyTree =>
379+ processTree(tree.function)
380+ sb.append(" [" )
381+ rep(tree.typeArguments, " , " )((t) => sb.append(pprint(t)))
382+ sb.append(" ]" )
383+
384+ case _ =>
385+ sb.append(" <?>" )
386+ }
387+
388+
389+ end SyntheticPrinter
0 commit comments