Skip to content

Commit 979699d

Browse files
committed
Store source file in TASTY attributes
1 parent 772be76 commit 979699d

12 files changed

+119
-52
lines changed

compiler/src/dotty/tools/dotc/core/tasty/AttributePickler.scala

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ object AttributePickler:
1414
pickler: TastyPickler,
1515
buf: TastyBuffer
1616
): Unit =
17-
if attributes.scala2StandardLibrary || attributes.explicitNulls then // or any other attribute is set
18-
pickler.newSection(AttributesSection, buf)
19-
// Pickle attributes
20-
if attributes.scala2StandardLibrary then buf.writeNat(TastyFormat.SCALA2STANDARDLIBRARYattr)
21-
if attributes.explicitNulls then buf.writeNat(TastyFormat.EXPLICITNULLSattr)
22-
end if
17+
pickler.newSection(AttributesSection, buf)
18+
19+
for tag <- attributes.booleanTags do
20+
buf.writeByte(tag)
21+
22+
for (tag, value) <- attributes.stringTagValues do
23+
buf.writeByte(tag)
24+
buf.writeUTF8(value)
2325

2426
end pickleAttributes
2527

compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,18 @@ import java.nio.charset.StandardCharsets
1010
class AttributeUnpickler(reader: TastyReader):
1111
import reader._
1212

13-
lazy val attributeTags: List[Int] =
14-
val listBuilder = List.newBuilder[Int]
15-
while !isAtEnd do listBuilder += readNat()
16-
listBuilder.result()
17-
1813
lazy val attributes: Attributes = {
19-
var scala2StandardLibrary = false
20-
var explicitNulls = false
21-
for attributeTag <- attributeTags do
22-
attributeTag match
23-
case TastyFormat.SCALA2STANDARDLIBRARYattr => scala2StandardLibrary = true
24-
case TastyFormat.EXPLICITNULLSattr => explicitNulls = true
25-
case attribute =>
26-
assert(false, "Unexpected attribute value: " + attribute)
27-
Attributes(
28-
scala2StandardLibrary,
29-
explicitNulls,
30-
)
14+
val booleanTags = List.newBuilder[Int]
15+
val stringTagValue = List.newBuilder[(Int, String)]
16+
17+
while !isAtEnd do
18+
val tag = readByte()
19+
if tag < TastyFormat.firstStringAttrTag then
20+
booleanTags += tag
21+
else
22+
stringTagValue += ((tag, readUTF8()))
23+
24+
new Attributes(booleanTags.result(), stringTagValue.result())
3125
}
3226

3327
end AttributeUnpickler
Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
package dotty.tools.dotc.core.tasty
22

3+
import dotty.tools.tasty.TastyFormat
4+
35
class Attributes(
4-
val scala2StandardLibrary: Boolean,
5-
val explicitNulls: Boolean,
6-
)
6+
val booleanTags: List[Int],
7+
val stringTagValues: List[(Int, String)],
8+
) {
9+
def scala2StandardLibrary: Boolean =
10+
booleanTags.contains(TastyFormat.SCALA2STANDARDLIBRARYattr)
11+
def explicitNulls: Boolean =
12+
booleanTags.contains(TastyFormat.EXPLICITNULLSattr)
13+
def sourceFile: Option[String] =
14+
stringTagValues.find(_._1 == TastyFormat.SOURCEFILEattr).map(_._2)
15+
}
16+
17+
object Attributes:
18+
def apply(
19+
sourceFile: String,
20+
scala2StandardLibrary: Boolean,
21+
explicitNulls: Boolean,
22+
): Attributes =
23+
val booleanTags = List.newBuilder[Int]
24+
if scala2StandardLibrary then booleanTags += TastyFormat.SCALA2STANDARDLIBRARYattr
25+
if explicitNulls then booleanTags += TastyFormat.EXPLICITNULLSattr
26+
27+
val stringTagValues = List(
28+
(TastyFormat.SOURCEFILEattr, sourceFile)
29+
)
30+
31+
new Attributes(booleanTags.result(), stringTagValues)
32+
end apply

compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ object CommentPickler:
2222

2323
def pickleComment(addr: Addr, comment: Comment): Unit =
2424
if addr != NoAddr then
25-
val bytes = comment.raw.getBytes(StandardCharsets.UTF_8).nn
26-
val length = bytes.length
2725
buf.writeAddr(addr)
28-
buf.writeNat(length)
29-
buf.writeBytes(bytes, length)
26+
buf.writeUTF8(comment.raw)
3027
buf.writeLongInt(comment.span.coords)
3128

3229
def traverse(x: Any): Unit = x match

compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ class CommentUnpickler(reader: TastyReader) {
1919
val comments = new HashMap[Addr, Comment]
2020
while (!isAtEnd) {
2121
val addr = readAddr()
22-
val length = readNat()
23-
if (length > 0) {
24-
val bytes = readBytes(length)
22+
val rawComment = readUTF8()
23+
if (rawComment != "") {
2524
val position = new Span(readLongInt())
26-
val rawComment = new String(bytes, StandardCharsets.UTF_8)
2725
comments(addr) = Comment(position, rawComment)
2826
}
2927
}

compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import util.Spans.offsetToInt
1212
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}
1313
import java.nio.file.{Files, Paths}
1414
import dotty.tools.io.{JarArchive, Path}
15+
import java.nio.charset.StandardCharsets
1516

1617
object TastyPrinter:
1718

@@ -225,15 +226,22 @@ class TastyPrinter(bytes: Array[Byte]) {
225226
}
226227

227228
class AttributesSectionUnpickler extends SectionUnpickler[String](AttributesSection) {
228-
import dotty.tools.tasty.TastyFormat.attributeTagToString
229+
import dotty.tools.tasty.TastyFormat.*
230+
229231
private val sb: StringBuilder = new StringBuilder
230232

231233
def unpickle(reader: TastyReader, tastyName: NameTable): String = {
234+
import reader.*
232235
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
233-
val attributeTags = new AttributeUnpickler(reader).attributeTags
236+
val attributes = new AttributeUnpickler(reader).attributes
234237
sb.append(s" attributes bytes:\n")
235-
for attributeTag <- attributeTags do
236-
sb.append(" ").append(attributeTagToString(attributeTag)).append("\n")
238+
239+
for tag <- attributes.booleanTags do
240+
sb.append(" ").append(attributeTagToString(tag)).append("\n")
241+
for (tag, value) <- attributes.stringTagValues do
242+
sb.append(" ").append(attributeTagToString(tag))
243+
.append(" ").append(value).append("\n")
244+
237245
sb.result
238246
}
239247
}

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ class TreeUnpickler(reader: TastyReader,
107107
private val explicitNulls =
108108
attributeUnpicklerOpt.exists(_.attributes.explicitNulls)
109109

110+
/** Source file in the TASTy attributes */
111+
private val sourceFile: Option[String] =
112+
attributeUnpicklerOpt.flatMap(_.attributes.sourceFile)
113+
110114
private def registerSym(addr: Addr, sym: Symbol) =
111115
symAtAddr(addr) = sym
112116

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ class Pickler extends Phase {
108108
pickler, treePkl.buf.addrOfTree, treePkl.docString, tree,
109109
scratch.commentBuffer)
110110

111+
val sourceRelativePath =
112+
val reference = ctx.settings.sourceroot.value
113+
util.SourceFile.relativePath(unit.source, reference)
111114
val attributes = Attributes(
115+
sourceFile = sourceRelativePath,
112116
scala2StandardLibrary = ctx.settings.YcompileScala2Library.value,
113117
explicitNulls = ctx.settings.YexplicitNulls.value,
114118
)

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
418418
em"The type of a class parent cannot refer to constructor parameters, but ${parent.tpe} refers to ${illegalRefs.map(_.name.show).mkString(",")}", parent.srcPos)
419419
// Add SourceFile annotation to top-level classes
420420
if sym.owner.is(Package) then
421+
// TODO do not add SourceFile annotation
421422
if ctx.compilationUnit.source.exists && sym != defn.SourceFileAnnot then
422423
val reference = ctx.settings.sourceroot.value
423424
val relativePath = util.SourceFile.relativePath(ctx.compilationUnit.source, reference)

tasty/src/dotty/tools/tasty/TastyBuffer.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dotty.tools.tasty
22

33
import util.Util.dble
4+
import java.nio.charset.StandardCharsets
45

56
object TastyBuffer {
67

@@ -115,6 +116,14 @@ class TastyBuffer(initialSize: Int) {
115116
writeBytes(bytes, 8)
116117
}
117118

119+
/** Write a UTF8 string encoded as `Length UTF8-CodePoint*` */
120+
def writeUTF8(x: String): Unit = {
121+
val bytes = x.getBytes(StandardCharsets.UTF_8)
122+
val length = bytes.length
123+
writeNat(length)
124+
writeBytes(bytes, length)
125+
}
126+
118127
// -- Address handling --------------------------------------------
119128

120129
/** Write natural number `x` right-adjusted in a field of `width` bytes

tasty/src/dotty/tools/tasty/TastyFormat.scala

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,11 @@ Note: The signature of a SELECTin or TERMREFin node is the signature of the sele
234234
235235
Note: Tree tags are grouped into 5 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
236236
```none
237-
Category 1 (tags 1-59) : tag
238-
Category 2 (tags 60-89) : tag Nat
239-
Category 3 (tags 90-109) : tag AST
240-
Category 4 (tags 110-127): tag Nat AST
241-
Category 5 (tags 128-255): tag Length <payload>
237+
Tree Category 1 (tags 1-59) : tag
238+
Tree Category 2 (tags 60-89) : tag Nat
239+
Tree Category 3 (tags 90-109) : tag AST
240+
Tree Category 4 (tags 110-127): tag Nat AST
241+
Tree Category 5 (tags 128-255): tag Length <payload>
242242
```
243243
244244
Standard-Section: "Positions" LinesSizes Assoc*
@@ -270,8 +270,16 @@ Standard Section: "Comments" Comment*
270270
271271
Standard Section: "Attributes" Attribute*
272272
```none
273-
Attribute = SCALA2STANDARDLIBRARYattr
274-
EXPLICITNULLSattr
273+
Attribute = SOURCEFILEattr UTF8
274+
SOURCEFILEattr
275+
SCALA2STANDARDLIBRARYatt2
276+
EXPLICITNULLSatt3
277+
```
278+
279+
Note: Attribute tags are grouped into 2 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
280+
```none
281+
Attribute Category 1 (tags 1-127) : tag
282+
Attribute Category 2 (tags 128-255): tag UTF8
275283
```
276284
277285
**************************************************************************************/
@@ -436,9 +444,8 @@ object TastyFormat {
436444
final val SOURCE = 4
437445

438446
// AST tags
439-
// Cat. 1: tag
447+
// Tree Cat. 1: tag
440448

441-
final val firstSimpleTreeTag = UNITconst
442449
// final val ??? = 1
443450
final val UNITconst = 2
444451
final val FALSEconst = 3
@@ -486,7 +493,7 @@ object TastyFormat {
486493
final val EMPTYCLAUSE = 45
487494
final val SPLITCLAUSE = 46
488495

489-
// Cat. 2: tag Nat
496+
// Tree Cat. 2: tag Nat
490497

491498
final val SHAREDterm = 60
492499
final val SHAREDtype = 61
@@ -506,7 +513,7 @@ object TastyFormat {
506513
final val IMPORTED = 75
507514
final val RENAMED = 76
508515

509-
// Cat. 3: tag AST
516+
// Tree Cat. 3: tag AST
510517

511518
final val THIS = 90
512519
final val QUALTHIS = 91
@@ -524,7 +531,7 @@ object TastyFormat {
524531
final val EXPLICITtpt = 103
525532

526533

527-
// Cat. 4: tag Nat AST
534+
// Tree Cat. 4: tag Nat AST
528535

529536
final val IDENT = 110
530537
final val IDENTtpt = 111
@@ -537,7 +544,7 @@ object TastyFormat {
537544
final val SELFDEF = 118
538545
final val NAMEDARG = 119
539546

540-
// Cat. 5: tag Length ...
547+
// Tree Cat. 5: tag Length ...
541548

542549
final val PACKAGE = 128
543550
final val VALDEF = 129
@@ -600,17 +607,25 @@ object TastyFormat {
600607

601608
final val HOLE = 255
602609

610+
final val firstSimpleTreeTag = UNITconst
603611
final val firstNatTreeTag = SHAREDterm
604612
final val firstASTTreeTag = THIS
605613
final val firstNatASTTreeTag = IDENT
606614
final val firstLengthTreeTag = PACKAGE
607615

608616

609-
// Attributes tags
617+
// Attributes tags
610618

619+
// Attr Cat. 1: tag
611620
final val SCALA2STANDARDLIBRARYattr = 1
612621
final val EXPLICITNULLSattr = 2
613622

623+
// Attr Cat. 2: tag UTF8
624+
final val SOURCEFILEattr = 128
625+
626+
final val firstBooleanAttrTag = SCALA2STANDARDLIBRARYattr
627+
final val firstStringAttrTag = SOURCEFILEattr
628+
614629
/** Useful for debugging */
615630
def isLegalTag(tag: Int): Boolean =
616631
firstSimpleTreeTag <= tag && tag <= SPLITCLAUSE ||
@@ -829,6 +844,7 @@ object TastyFormat {
829844
def attributeTagToString(tag: Int): String = tag match {
830845
case SCALA2STANDARDLIBRARYattr => "SCALA2STANDARDLIBRARYattr"
831846
case EXPLICITNULLSattr => "EXPLICITNULLSattr"
847+
case SOURCEFILEattr => "SOURCEFILEattr"
832848
}
833849

834850
/** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.

tasty/src/dotty/tools/tasty/TastyReader.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dotty.tools.tasty
33
import collection.mutable
44

55
import TastyBuffer._
6+
import java.nio.charset.StandardCharsets
67

78
/** A byte array buffer that can be filled with bytes or natural numbers in TASTY format,
89
* and that supports reading and patching addresses represented as natural numbers.
@@ -104,6 +105,13 @@ class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int =
104105
x
105106
}
106107

108+
/** Read a UTF8 string encoded as `Length UTF8-CodePoint*` */
109+
def readUTF8(): String = {
110+
val length = readNat()
111+
if (length == 0) ""
112+
else new String(readBytes(length), StandardCharsets.UTF_8)
113+
}
114+
107115
/** Read a natural number and return as a NameRef */
108116
def readNameRef(): NameRef = NameRef(readNat())
109117

0 commit comments

Comments
 (0)