@@ -57,6 +57,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
57
57
58
58
private var roots : Set [SymDenotation ] = null
59
59
60
+ private var ownerTree : OwnerTree = _
61
+
60
62
private def registerSym (addr : Addr , sym : Symbol ) = {
61
63
symAtAddr(addr) = sym
62
64
unpickledSyms += sym
@@ -118,6 +120,45 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
118
120
def skipParams (): Unit =
119
121
while (nextByte == PARAMS || nextByte == TYPEPARAM ) skipTree()
120
122
123
+ /** Record all directly nested definitions and templates in current tree
124
+ * as `OwnerTree`s in `buf`
125
+ */
126
+ def scanTree (buf : ListBuffer [OwnerTree ]): Unit = {
127
+ val start = currentAddr
128
+ val tag = readByte()
129
+ // println(s"scan tree at $currentAddr, tag = $tag")
130
+ tag match {
131
+ case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | TEMPLATE =>
132
+ val end = readEnd()
133
+ for (i <- 0 until numRefs(tag)) readNat()
134
+ buf += new OwnerTree (start, fork, end)
135
+ case tag =>
136
+ if (tag >= firstLengthTreeTag) {
137
+ val end = readEnd()
138
+ var nrefs = numRefs(tag)
139
+ if (nrefs < 0 ) {
140
+ for (i <- nrefs until 0 ) scanTree(buf)
141
+ goto(end)
142
+ }
143
+ else {
144
+ for (i <- 0 until nrefs) readNat()
145
+ scanTrees(buf, end)
146
+ }
147
+ }
148
+ else if (tag >= firstNatASTTreeTag) { readNat(); scanTree(buf) }
149
+ else if (tag >= firstASTTreeTag) scanTree(buf)
150
+ else if (tag >= firstNatTreeTag) readNat()
151
+ }
152
+ }
153
+
154
+ /** Record all directly nested definitions and templates between current address and `end`
155
+ * as `OwnerTree`s in `buf`
156
+ */
157
+ def scanTrees (buf : ListBuffer [OwnerTree ], end : Addr ): Unit = {
158
+ while (currentAddr.index < end.index) scanTree(buf)
159
+ assert(currentAddr.index == end.index)
160
+ }
161
+
121
162
/** The next tag, following through SHARED tags */
122
163
def nextUnsharedTag : Int = {
123
164
val tag = nextByte
@@ -197,8 +238,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
197
238
case SUPERtype =>
198
239
SuperType (readType(), readType())
199
240
case REFINEDtype =>
200
- val parent = readType()
201
241
var name : Name = readName()
242
+ val parent = readType()
202
243
val ttag = nextUnsharedTag
203
244
if (ttag == TYPEBOUNDS || ttag == TYPEALIAS ) name = name.toTypeName
204
245
RefinedType (parent, name, rt => registeringType(rt, readType()))
@@ -437,7 +478,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
437
478
}
438
479
439
480
/** Read modifier list into triplet of flags, annotations and a privateWithin
440
- * boindary symbol.
481
+ * boundary symbol.
441
482
*/
442
483
def readModifiers (end : Addr )(implicit ctx : Context ): (FlagSet , List [Annotation ], Symbol ) = {
443
484
var flags : FlagSet = EmptyFlags
@@ -664,6 +705,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
664
705
else NoType
665
706
setClsInfo(Nil , assumedSelfType)
666
707
val localDummy = ctx.newLocalDummy(cls)
708
+ registerSym(start, localDummy)
667
709
assert(readByte() == TEMPLATE )
668
710
val end = readEnd()
669
711
val tparams = readIndexedParams[TypeDef ](TYPEPARAM )
@@ -716,12 +758,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
716
758
}
717
759
718
760
def readTopLevel ()(implicit ctx : Context ): List [Tree ] = {
761
+ ownerTree = new OwnerTree (NoAddr , fork, reader.endAddr)
719
762
@ tailrec def read (acc : ListBuffer [Tree ]): List [Tree ] = nextByte match {
720
763
case IMPORT | PACKAGE =>
721
764
acc += readIndexedStat(NoSymbol )
722
- if (! isAtEnd)
723
- read(acc)
724
- else acc.toList
765
+ if (! isAtEnd) read(acc) else acc.toList
725
766
case _ => // top-level trees which are not imports or packages are not part of tree
726
767
acc.toList
727
768
}
@@ -968,4 +1009,33 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
968
1009
res
969
1010
}
970
1011
}
1012
+
1013
+ class OwnerTree (val addr : Addr , reader : TreeReader , val end : Addr ) {
1014
+ lazy val children : List [OwnerTree ] = {
1015
+ val buf = new ListBuffer [OwnerTree ]
1016
+ reader.scanTrees(buf, end)
1017
+ buf.toList
1018
+ }
1019
+ def findOwner (addr : Addr )(implicit ctx : Context ): Symbol = {
1020
+ // println(s"find owner $addr")
1021
+ def search (cs : List [OwnerTree ], current : Symbol ): Symbol = cs match {
1022
+ case ot :: cs1 =>
1023
+ if (ot.addr.index == addr.index) {
1024
+ // println(i"search ok $addr, owner = $current")
1025
+ current
1026
+ }
1027
+ else if (ot.addr.index < addr.index && addr.index < ot.end.index) {
1028
+ val encl = reader.symbolAt(ot.addr)
1029
+ // println(s"search $addr in ${ot.children} with $encl")
1030
+ search(ot.children, encl)
1031
+ }
1032
+ else
1033
+ search(cs1, current)
1034
+ case Nil =>
1035
+ throw new Error (" unattached tree" )
1036
+ }
1037
+ search(children, NoSymbol )
1038
+ }
1039
+ override def toString = s " OwnerTree( ${addr.index}, ${end.index}"
1040
+ }
971
1041
}
0 commit comments