@@ -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 =
@@ -78,7 +79,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
7879 private def pprintDef (info : SymbolInformation ) =
7980 notes.enter(info)
8081 pprint(info.symbol, SymbolStyle .Definition )
81- private def pprintRef (sym : String ): String = pprint(sym, SymbolStyle .Reference )
82+ def pprintRef (sym : String ): String = pprint(sym, SymbolStyle .Reference )
8283 private def pprintDef (sym : String ): String = pprint(sym, SymbolStyle .Definition )
8384 private def pprint (sym : String , style : SymbolStyle ): String =
8485 val info = notes.visit(sym)
@@ -134,7 +135,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
134135 case _ =>
135136 " <?>"
136137
137- private def pprint (tpe : Type ): String = {
138+ protected def pprint (tpe : Type ): String = {
138139 def prefix (tpe : Type ): String = tpe match
139140 case TypeRef (pre, sym, args) =>
140141 val preStr = pre match {
@@ -201,7 +202,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
201202 case tpe => s " @ ${pprint(tpe)}"
202203 }
203204
204- private def pprint (const : Constant ): String = const match {
205+ protected def pprint (const : Constant ): String = const match {
205206 case Constant .Empty =>
206207 " <?>"
207208 case UnitConstant () =>
@@ -242,7 +243,6 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
242243 s " private[ ${ssym}] "
243244 case ProtectedWithinAccess (ssym) =>
244245 s " protected[ ${ssym}] "
245-
246246 extension (scope : Scope )
247247 private def infos : List [SymbolInformation ] =
248248 if (scope.symlinks.nonEmpty)
@@ -255,8 +255,8 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab):
255255 case Some (s) => s.infos
256256 case None => Nil
257257 }
258- }
259- end SymbolInfomationPrinter
258+ end InfoPrinter
259+ end SymbolInformationPrinter
260260
261261extension (info : SymbolInformation )
262262 def prefixBeforeTpe : String = {
@@ -277,3 +277,110 @@ object PrinterSymtab:
277277 new PrinterSymtab {
278278 override def info (symbol : String ): Option [SymbolInformation ] = map.get(symbol)
279279 }
280+
281+ def processRange (sb : StringBuilder , range : Range ): Unit =
282+ sb.append('[' )
283+ .append(range.startLine).append(':' ).append(range.startCharacter)
284+ .append(" .." )
285+ .append(range.endLine).append(':' ).append(range.endCharacter)
286+ .append(" ):" )
287+
288+
289+
290+ class SyntheticPrinter (symtab : PrinterSymtab , source : SourceFile ) extends SymbolInformationPrinter (symtab):
291+
292+ def pprint (synth : Synthetic ): String =
293+ val sb = new StringBuilder ()
294+ val notes = InfoNotes ()
295+ val treePrinter = TreePrinter (source, synth.range, notes)
296+
297+ synth.range match
298+ case Some (range) =>
299+ processRange(sb, range)
300+ sb.append(source.substring(range))
301+ case None =>
302+ sb.append(" [):" )
303+ sb.append(" => " )
304+ sb.append(treePrinter.pprint(synth.tree))
305+ sb.toString
306+
307+ extension (source : SourceFile )
308+ private def substring (range : Option [s.Range ]): String =
309+ range match
310+ case Some (range) => source.substring(range)
311+ case None => " "
312+ private def substring (range : s.Range ): String =
313+ /** get the line length of a given line */
314+ def lineLength (line : Int ): Int =
315+ val isLastLine = source.lineToOffsetOpt(line).nonEmpty && source.lineToOffsetOpt(line + 1 ).isEmpty
316+ if isLastLine then source.content.length - source.lineToOffset(line) - 1
317+ else source.lineToOffset(line + 1 ) - source.lineToOffset(line) - 1 // -1 for newline char
318+
319+ val start = source.lineToOffset(range.startLine) +
320+ math.min(range.startCharacter, lineLength(range.startLine))
321+ val end = source.lineToOffset(range.endLine) +
322+ math.min(range.endCharacter, lineLength(range.endLine))
323+ new String (source.content, start, end - start)
324+
325+
326+ // def pprint(tree: s.Tree, range: Option[Range]): String =
327+ class TreePrinter (source : SourceFile , originalRange : Option [Range ], notes : InfoNotes ) extends InfoPrinter (notes):
328+ def pprint (tree : Tree ): String =
329+ val sb = new StringBuilder ()
330+ processTree(tree)(using sb)
331+ sb.toString
332+
333+
334+ private def rep [T ](xs : Seq [T ], seq : String )(f : T => Unit )(using sb : StringBuilder ): Unit =
335+ xs.zipWithIndex.foreach { (x, i) =>
336+ if i != 0 then sb.append(seq)
337+ f(x)
338+ }
339+
340+ private def processTree (tree : Tree )(using sb : StringBuilder ): Unit =
341+ tree match {
342+ case tree : ApplyTree =>
343+ processTree(tree.function)
344+ sb.append(" (" )
345+ rep(tree.arguments, " , " )(processTree)
346+ sb.append(" )" )
347+ case tree : FunctionTree =>
348+ sb.append(" {" )
349+ sb.append(" (" )
350+ rep(tree.parameters, " , " )(processTree)
351+ sb.append(" ) =>" )
352+ processTree(tree.body)
353+ sb.append(" }" )
354+ case tree : IdTree =>
355+ sb.append(pprintRef(tree.symbol))
356+ case tree : LiteralTree =>
357+ sb.append(pprint(tree.constant))
358+ case tree : MacroExpansionTree =>
359+ sb.append(" (`macro-expandee` : `" )
360+ sb.append(pprint(tree.tpe))
361+ sb.append(" )" )
362+ case tree : OriginalTree =>
363+ if (tree.range == originalRange && originalRange.nonEmpty) then
364+ sb.append(" *" )
365+ else
366+ sb.append(" orig(" )
367+ sb.append(source.substring(tree.range))
368+ sb.append(" )" )
369+ case tree : SelectTree =>
370+ processTree(tree.qualifier)
371+ sb.append(" ." )
372+ tree.id match
373+ case Some (tree) => processTree(tree)
374+ case None => ()
375+ case tree : TypeApplyTree =>
376+ processTree(tree.function)
377+ sb.append(" [" )
378+ rep(tree.typeArguments, " , " )((t) => sb.append(pprint(t)))
379+ sb.append(" ]" )
380+
381+ case _ =>
382+ sb.append(" <?>" )
383+ }
384+
385+
386+ end SyntheticPrinter
0 commit comments