Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TASTy source position printer #19105

Merged
merged 2 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions compiler/src/dotty/tools/dotc/core/tasty/PositionUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {

private var myLineSizes: Array[Int] = uninitialized
private var mySpans: util.HashMap[Addr, Span] = uninitialized
private var mySourcePaths: util.HashMap[Addr, String] = uninitialized
private var mySourceNameRefs: util.HashMap[Addr, NameRef] = uninitialized
private var isDefined = false

def ensureDefined(): Unit = {
Expand All @@ -31,15 +31,14 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {
i += 1

mySpans = util.HashMap[Addr, Span]()
mySourcePaths = util.HashMap[Addr, String]()
mySourceNameRefs = util.HashMap[Addr, NameRef]()
var curIndex = 0
var curStart = 0
var curEnd = 0
while (!isAtEnd) {
val header = readInt()
if (header == SOURCE) {
val path = nameAtRef(readNameRef()).toString
mySourcePaths(Addr(curIndex)) = path
mySourceNameRefs(Addr(curIndex)) = readNameRef()
}
else {
val addrDelta = header >> 3
Expand All @@ -64,9 +63,9 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {
mySpans
}

private[tasty] def sourcePaths: util.ReadOnlyMap[Addr, String] = {
private[tasty] def sourceNameRefs: util.ReadOnlyMap[Addr, NameRef] = {
ensureDefined()
mySourcePaths
mySourceNameRefs
}

private[tasty] def lineSizes: Array[Int] = {
Expand All @@ -75,5 +74,5 @@ class PositionUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName) {
}

def spanAt(addr: Addr): Span = spans.getOrElse(addr, NoSpan)
def sourcePathAt(addr: Addr): String = sourcePaths.getOrElse(addr, "")
def sourcePathAt(addr: Addr): String = sourceNameRefs.get(addr).fold("")(nameAtRef(_).toString)
}
81 changes: 53 additions & 28 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import util.Spans.offsetToInt
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}
import java.nio.file.{Files, Paths}
import dotty.tools.io.{JarArchive, Path}
import dotty.tools.tasty.TastyFormat.header

import scala.compiletime.uninitialized
import dotty.tools.tasty.TastyBuffer.Addr

object TastyPrinter:

Expand Down Expand Up @@ -62,26 +66,43 @@ class TastyPrinter(bytes: Array[Byte]) {

private val sb: StringBuilder = new StringBuilder

private val unpickler: TastyUnpickler = new TastyUnpickler(bytes)
class TastyPrinterUnpickler extends TastyUnpickler(bytes) {
var namesStart: Addr = uninitialized
var namesEnd: Addr = uninitialized
override def readNames() = {
namesStart = reader.currentAddr
super.readNames()
namesEnd = reader.currentAddr
}
}

private val unpickler: TastyPrinterUnpickler = new TastyPrinterUnpickler
import unpickler.{nameAtRef, unpickle}

private def nameToString(name: Name): String = name.debugString

private def nameRefToString(ref: NameRef): String = nameToString(nameAtRef(ref))

private def printHeader(): Unit =
val header = unpickler.header
sb.append("Header:\n")
sb.append(s" version: ${header.majorVersion}.${header.minorVersion}.${header.experimentalVersion}\n")
sb.append(" tooling: ").append(header.toolingVersion).append("\n")
sb.append(" UUID: ").append(header.uuid).append("\n")
sb.append("\n")

private def printNames(): Unit =
sb.append(s"Names (${unpickler.namesEnd.index - unpickler.namesStart.index} bytes, starting from ${unpickler.namesStart.index}):\n")
for ((name, idx) <- nameAtRef.contents.zipWithIndex) {
val index = nameStr("%4d".format(idx))
val index = nameStr("%6d".format(idx))
sb.append(index).append(": ").append(nameToString(name)).append("\n")
}

def showContents(): String = {
sb.append("Names:\n")
printHeader()
printNames()
sb.append("\n")
sb.append("Trees:\n")
unpickle(new TreeSectionUnpickler) match {
case Some(s) => sb.append(s)
case Some(s) => sb.append("\n\n").append(s)
case _ =>
}
unpickle(new PositionSectionUnpickler) match {
Expand All @@ -108,8 +129,8 @@ class TastyPrinter(bytes: Array[Byte]) {
import reader.*
var indent = 0
def newLine() = {
val length = treeStr("%5d".format(index(currentAddr) - index(startAddr)))
sb.append(s"\n $length:" + " " * indent)
val length = treeStr("%6d".format(index(currentAddr) - index(startAddr)))
sb.append(s"\n$length:" + " " * indent)
}
def printNat() = sb.append(treeStr(" " + readNat()))
def printName() = {
Expand Down Expand Up @@ -165,8 +186,7 @@ class TastyPrinter(bytes: Array[Byte]) {
}
indent -= 2
}
sb.append(s"start = ${reader.startAddr}, base = $base, current = $currentAddr, end = $endAddr\n")
sb.append(s"${endAddr.index - startAddr.index} bytes of AST, base = $currentAddr\n")
sb.append(s"Trees (${endAddr.index - startAddr.index} bytes, starting from $base):")
while (!isAtEnd) {
printTree()
newLine()
Expand All @@ -180,26 +200,30 @@ class TastyPrinter(bytes: Array[Byte]) {
private val sb: StringBuilder = new StringBuilder

def unpickle(reader: TastyReader, tastyName: NameTable): String = {
import reader.*
val posUnpickler = new PositionUnpickler(reader, tastyName)
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
sb.append(" position bytes:\n")
sb.append(s"Positions (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n")
val lineSizes = posUnpickler.lineSizes
sb.append(s" lines: ${lineSizes.length}\n")
sb.append(posUnpickler.lineSizes.mkString(" line sizes: ", ", ", "\n"))
sb.append(" positions:\n")
sb.append(s" lines: ${lineSizes.length}\n")
sb.append(s" line sizes:\n")
val windowSize = 20
for window <-posUnpickler.lineSizes.sliding(windowSize, windowSize) do
sb.append(" ").append(window.mkString(", ")).append("\n")
// sb.append(posUnpickler.lineSizes.mkString(" line sizes: ", ", ", "\n"))
sb.append(" positions:\n")
val spans = posUnpickler.spans
val sorted = spans.toSeq.sortBy(_._1.index)
for ((addr, pos) <- sorted) {
sb.append(treeStr("%10d".format(addr.index)))
sb.append(treeStr("%6d".format(addr.index)))
sb.append(s": ${offsetToInt(pos.start)} .. ${pos.end}\n")
}

val sources = posUnpickler.sourcePaths
sb.append(s"\n source paths:\n")
val sources = posUnpickler.sourceNameRefs
sb.append(s"\n source paths:\n")
val sortedPath = sources.toSeq.sortBy(_._1.index)
for ((addr, path) <- sortedPath) {
sb.append(treeStr("%10d: ".format(addr.index)))
sb.append(path)
for ((addr, nameRef) <- sortedPath) {
sb.append(treeStr("%6d: ".format(addr.index)))
Copy link
Member

@bishabosha bishabosha Dec 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolasstucki actually this : should not be highlighted as anything, small thing but it is inconsistent with the rest of the document

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I will fix it in #19139

sb.append(nameStr(s"${nameRef.index} [${tastyName(nameRef)}]"))
sb.append("\n")
}

Expand All @@ -212,14 +236,15 @@ class TastyPrinter(bytes: Array[Byte]) {
private val sb: StringBuilder = new StringBuilder

def unpickle(reader: TastyReader, tastyName: NameTable): String = {
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
import reader.*
val comments = new CommentUnpickler(reader).comments
sb.append(s" comment bytes:\n")
val sorted = comments.toSeq.sortBy(_._1.index)
for ((addr, cmt) <- sorted) {
sb.append(treeStr("%10d".format(addr.index)))
sb.append(s": ${cmt.raw} (expanded = ${cmt.isExpanded})\n")
}
if !comments.isEmpty then
sb.append(s"Comments (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n")
val sorted = comments.toSeq.sortBy(_._1.index)
for ((addr, cmt) <- sorted) {
sb.append(treeStr("%6d".format(addr.index)))
sb.append(s": ${cmt.raw} (expanded = ${cmt.isExpanded})\n")
}
sb.result
}
}
Expand Down
13 changes: 10 additions & 3 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import TastyBuffer.NameRef
import scala.collection.mutable
import Names.{TermName, termName, EmptyTermName}
import NameKinds.*
import dotty.tools.tasty.TastyHeader
import dotty.tools.tasty.TastyBuffer.Addr

object TastyUnpickler {

Expand Down Expand Up @@ -61,7 +63,7 @@ object TastyUnpickler {

import TastyUnpickler.*

class TastyUnpickler(reader: TastyReader) {
class TastyUnpickler(protected val reader: TastyReader) {
import reader.*

def this(bytes: Array[Byte]) = this(new TastyReader(bytes))
Expand Down Expand Up @@ -121,17 +123,22 @@ class TastyUnpickler(reader: TastyReader) {
result
}

val header = new TastyHeaderUnpickler(scala3CompilerConfig, reader).readFullHeader()
val header: TastyHeader =
new TastyHeaderUnpickler(scala3CompilerConfig, reader).readFullHeader()

locally {
def readNames(): Unit =
until(readEnd()) { nameAtRef.add(readNameContents()) }

def loadSections(): Unit = {
while (!isAtEnd) {
val secName = readString()
val secEnd = readEnd()
sectionReader(secName) = new TastyReader(bytes, currentAddr.index, secEnd.index, currentAddr.index)
goto(secEnd)
}
}
readNames()
loadSections()

def unpickle[R](sec: SectionUnpickler[R]): Option[R] =
for (reader <- sectionReader.get(sec.name)) yield
Expand Down
2 changes: 1 addition & 1 deletion project/scripts/cmdTests
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ echo "testing sbt scalac -print-tasty"
clear_out "$OUT"
"$SBT" ";scalac $SOURCE -d $OUT ;scalac -print-tasty -color:never $TASTY" > "$tmp"
grep -qe "0: ASTs" "$tmp"
grep -qe "0: tests/pos/HelloWorld.scala" "$tmp"
grep -qe "0: 41 \[tests/pos/HelloWorld.scala\]" "$tmp"

echo "testing that paths SourceFile annotations are relativized"
clear_out "$OUT"
Expand Down
Loading