@@ -13,16 +13,21 @@ import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSec
1313import java .nio .file .{Files , Paths }
1414import dotty .tools .io .{JarArchive , Path }
1515import dotty .tools .tasty .TastyFormat .header
16+ import scala .collection .immutable .BitSet
1617
1718import scala .compiletime .uninitialized
1819import dotty .tools .tasty .TastyBuffer .Addr
20+ import dotty .tools .dotc .core .Names .TermName
1921
2022object TastyPrinter :
2123
2224 def showContents (bytes : Array [Byte ], noColor : Boolean ): String =
25+ showContents(bytes, noColor, testPickler = false )
26+
27+ def showContents (bytes : Array [Byte ], noColor : Boolean , testPickler : Boolean = false ): String =
2328 val printer =
24- if noColor then new TastyPrinter (bytes)
25- else new TastyAnsiiPrinter (bytes)
29+ if noColor then new TastyPrinter (bytes, testPickler )
30+ else new TastyAnsiiPrinter (bytes, testPickler )
2631 printer.showContents()
2732
2833 def main (args : Array [String ]): Unit = {
@@ -62,7 +67,9 @@ object TastyPrinter:
6267 println(line)
6368 }
6469
65- class TastyPrinter (bytes : Array [Byte ]) {
70+ class TastyPrinter (bytes : Array [Byte ], val testPickler : Boolean ) {
71+
72+ def this (bytes : Array [Byte ]) = this (bytes, testPickler = false )
6673
6774 class TastyPrinterUnpickler extends TastyUnpickler (bytes) {
6875 var namesStart : Addr = uninitialized
@@ -77,39 +84,53 @@ class TastyPrinter(bytes: Array[Byte]) {
7784 private val unpickler : TastyPrinterUnpickler = new TastyPrinterUnpickler
7885 import unpickler .{nameAtRef , unpickle }
7986
80- private def nameToString (name : Name ): String = name.debugString
81-
82- private def nameRefToString (ref : NameRef ): String = nameToString(nameAtRef(ref))
83-
8487 private def printHeader (sb : StringBuilder ): Unit =
8588 val header = unpickler.header
8689 sb.append(" Header:\n " )
87- sb.append(s " version: ${header.majorVersion}. ${header.minorVersion}. ${header.experimentalVersion}\n " )
88- sb.append(" tooling: " ).append(header.toolingVersion).append(" \n " )
89- sb.append(" UUID: " ).append(header.uuid).append(" \n " )
90- sb.append(" \n " )
90+ if testPickler then
91+ // these fields are not stable when the TASTy/compiler versions change, so not useful for testing
92+ sb.append(" version: <elided>\n " )
93+ sb.append(" tooling: <elided>\n " )
94+ sb.append(" UUID: <elided>\n " )
95+ else
96+ sb.append(s " version: ${header.majorVersion}. ${header.minorVersion}. ${header.experimentalVersion}\n " )
97+ sb.append(" tooling: " ).append(header.toolingVersion).append(" \n " )
98+ sb.append(" UUID: " ).append(header.uuid).append(" \n " )
99+ end if
91100
92- private def printNames (sb : StringBuilder ): Unit =
93- sb.append(s " Names ( ${unpickler.namesEnd.index - unpickler.namesStart.index} bytes, starting from ${unpickler.namesStart.index}): \n " )
101+ private def printNames (sb : StringBuilder )(using refs : NameRefs ): Unit =
102+ sb.append(sectionHeader(
103+ name = " Names" ,
104+ count = (unpickler.namesEnd.index - unpickler.namesStart.index).toString,
105+ base = showBase(unpickler.namesStart.index),
106+ lineEnd = true
107+ ))
94108 for ((name, idx) <- nameAtRef.contents.zipWithIndex) {
95109 val index = nameStr(" %6d" .format(idx))
96- sb.append(index).append(" : " ).append(nameToString(name )).append(" \n " )
110+ sb.append(index).append(" : " ).append(refs.nameRefToString( NameRef (idx) )).append(" \n " )
97111 }
98112
99113 def showContents (): String = {
100114 val sb : StringBuilder = new StringBuilder
115+ given NameRefs = unpickle0(new SourceFileUnpickler )(using NameRefs .empty).getOrElse(NameRefs .empty)
101116 printHeader(sb)
102117 printNames(sb)
103- unpickle (new TreeSectionUnpickler (sb))
104- unpickle (new PositionSectionUnpickler (sb))
105- unpickle (new CommentSectionUnpickler (sb))
106- unpickle (new AttributesSectionUnpickler (sb))
118+ unpickle0 (new TreeSectionUnpickler (sb))
119+ unpickle0 (new PositionSectionUnpickler (sb))
120+ unpickle0 (new CommentSectionUnpickler (sb))
121+ unpickle0 (new AttributesSectionUnpickler (sb))
107122 sb.result
108123 }
109124
110- class TreeSectionUnpickler (sb : StringBuilder ) extends SectionUnpickler [Unit ](ASTsSection ) {
125+ def unpickle0 [R ](sec : PrinterSectionUnpickler [R ])(using NameRefs ): Option [R ] =
126+ unpickle(new SectionUnpickler [R ](sec.name) {
127+ def unpickle (reader : TastyReader , nameAtRef : NameTable ): R =
128+ sec.unpickle0(reader.subReader(reader.startAddr, reader.endAddr)) // fork so we can visit multiple times
129+ })
130+
131+ class TreeSectionUnpickler (sb : StringBuilder ) extends PrinterSectionUnpickler [Unit ](ASTsSection ) {
111132 import dotty .tools .tasty .TastyFormat .*
112- def unpickle (reader : TastyReader , tastyName : NameTable ): Unit = {
133+ def unpickle0 (reader : TastyReader )( using refs : NameRefs ): Unit = {
113134 import reader .*
114135 var indent = 0
115136 def newLine () = {
@@ -119,7 +140,7 @@ class TastyPrinter(bytes: Array[Byte]) {
119140 def printNat () = sb.append(treeStr(" " + readNat()))
120141 def printName () = {
121142 val idx = readNat()
122- sb.append(nameStr(" " + idx + " [" + nameRefToString(NameRef (idx)) + " ]" ))
143+ sb.append(nameStr(" " + idx + " [" + refs. nameRefToString(NameRef (idx)) + " ]" ))
123144 }
124145 def printTree (): Unit = {
125146 newLine()
@@ -170,19 +191,20 @@ class TastyPrinter(bytes: Array[Byte]) {
170191 }
171192 indent -= 2
172193 }
173- sb.append(s " \n\n Trees ( ${endAddr.index - startAddr.index} bytes, starting from $base ): " )
194+ sb.append(sectionHeader( " Trees " , reader, lineEnd = false ) )
174195 while (! isAtEnd) {
175196 printTree()
176197 newLine()
177198 }
199+ sb.append(" \n " )
178200 }
179201 }
180202
181- class PositionSectionUnpickler (sb : StringBuilder ) extends SectionUnpickler [Unit ](PositionsSection ) {
182- def unpickle (reader : TastyReader , tastyName : NameTable ): Unit = {
203+ class PositionSectionUnpickler (sb : StringBuilder ) extends PrinterSectionUnpickler [Unit ](PositionsSection ) {
204+ def unpickle0 (reader : TastyReader )( using tastyName : NameRefs ): Unit = {
183205 import reader .*
184206 val posUnpickler = new PositionUnpickler (reader, tastyName)
185- sb.append(s " \n\n Positions ( ${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base ): \n " )
207+ sb.append(sectionHeader( " Positions " , reader) )
186208 val lineSizes = posUnpickler.lineSizes
187209 sb.append(s " lines: ${lineSizes.length}\n " )
188210 sb.append(s " line sizes: \n " )
@@ -210,12 +232,12 @@ class TastyPrinter(bytes: Array[Byte]) {
210232 }
211233 }
212234
213- class CommentSectionUnpickler (sb : StringBuilder ) extends SectionUnpickler [Unit ](CommentsSection ) {
214- def unpickle (reader : TastyReader , tastyName : NameTable ): Unit = {
235+ class CommentSectionUnpickler (sb : StringBuilder ) extends PrinterSectionUnpickler [Unit ](CommentsSection ) {
236+ def unpickle0 (reader : TastyReader )( using NameRefs ): Unit = {
215237 import reader .*
216238 val comments = new CommentUnpickler (reader).comments
217239 if ! comments.isEmpty then
218- sb.append(s " \n\n Comments ( ${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base ): \n " )
240+ sb.append(sectionHeader( " Comments " , reader) )
219241 val sorted = comments.toSeq.sortBy(_._1.index)
220242 for ((addr, cmt) <- sorted) {
221243 sb.append(treeStr(" %6d" .format(addr.index)))
@@ -224,12 +246,14 @@ class TastyPrinter(bytes: Array[Byte]) {
224246 }
225247 }
226248
227- class AttributesSectionUnpickler (sb : StringBuilder ) extends SectionUnpickler [Unit ](AttributesSection ) {
249+ class AttributesSectionUnpickler (sb : StringBuilder ) extends PrinterSectionUnpickler [Unit ](AttributesSection ) {
228250 import dotty .tools .tasty .TastyFormat .*
229- def unpickle (reader : TastyReader , tastyName : NameTable ): Unit = {
251+ def unpickle0 (reader : TastyReader )( using nameAtRef : NameRefs ): Unit = {
230252 import reader .*
231- sb.append(s " \n\n Attributes ( ${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base ): \n " )
253+ sb.append(sectionHeader( " Attributes " , reader) )
232254 while ! isAtEnd do
255+ // TODO: Should we elide attributes under testPickler? (i.e.
256+ // if we add new attributes many check files will need to be updated)
233257 val tag = readByte()
234258 sb.append(" " ).append(attributeTagToString(tag))
235259 if isBooleanAttrTag(tag) then ()
@@ -242,6 +266,50 @@ class TastyPrinter(bytes: Array[Byte]) {
242266 }
243267 }
244268
269+ class NameRefs (sourceFileRefs : Set [NameRef ]) extends (NameRef => TermName ):
270+ private val isSourceFile = sourceFileRefs.map(_.index).to(BitSet )
271+
272+ def nameRefToString (ref : NameRef ): String = this (ref).debugString
273+
274+ def apply (ref : NameRef ): TermName =
275+ if isSourceFile(ref.index) then NameRefs .elidedSourceFile
276+ else nameAtRef(ref)
277+
278+ object NameRefs :
279+ import dotty .tools .dotc .core .Names .termName
280+
281+ private val elidedSourceFile = termName(" <elided source file name>" )
282+ val empty = NameRefs (Set .empty)
283+
284+
285+ class SourceFileUnpickler extends PrinterSectionUnpickler [NameRefs ](PositionsSection ) {
286+ def unpickle0 (reader : TastyReader )(using nameAtRef : NameRefs ): NameRefs = {
287+ if ! testPickler then return NameRefs .empty
288+ val buf = Set .newBuilder[NameRef ]
289+ val posUnpickler = new PositionUnpickler (reader, nameAtRef)
290+ val sources = posUnpickler.sourceNameRefs
291+ for ((_, nameRef) <- sources.iterator) {
292+ buf += nameRef
293+ }
294+ NameRefs (buf.result)
295+ }
296+ }
297+
298+ private final def showBase (index : Int ): String =
299+ if testPickler then " <elided base index>" else index.toString()
300+
301+ private final def sectionHeader (name : String , reader : TastyReader , lineEnd : Boolean = true ): String =
302+ val count = reader.endAddr.index - reader.startAddr.index
303+ sectionHeader(name, count.toString, {showBase(reader.base)}, lineEnd)
304+
305+ private final def sectionHeader (name : String , count : String , base : String , lineEnd : Boolean ): String =
306+ val suffix = if lineEnd then " \n " else " "
307+ s " \n $name ( $count bytes, starting from $base): $suffix"
308+
309+ abstract class PrinterSectionUnpickler [T ](val name : String ) {
310+ def unpickle0 (reader : TastyReader )(using refs : NameRefs ): T
311+ }
312+
245313 protected def nameStr (str : String ): String = str
246314 protected def treeStr (str : String ): String = str
247315 protected def lengthStr (str : String ): String = str
0 commit comments