Skip to content

Commit a7a8203

Browse files
committed
Optimize initialPos in Positioned
Single traversal to set id and span.
1 parent 29c8f45 commit a7a8203

File tree

1 file changed

+32
-51
lines changed

1 file changed

+32
-51
lines changed

compiler/src/dotty/tools/dotc/ast/Positioned.scala

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod
1818
/** A unique identifier. Among other things, used for determining the source file
1919
* component of the position.
2020
*/
21-
private var myUniqueId: Int = _
22-
private[this] var mySpan: Span = _
21+
private var myUniqueId: Int = -1
22+
private[this] var mySpan: Span = NoSpan
2323

2424
/** The span part of the item's position */
2525
def span: Span = mySpan
@@ -30,8 +30,8 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod
3030
def source: SourceFile = SourceFile.fromId(uniqueId)
3131
def sourcePos(implicit ctx: Context): SourcePosition = source.atSpan(span)
3232

33-
setId(initialSource(src).nextId)
34-
setPos(initialSpan(), source)
33+
//setId(initialSource(src).nextId)
34+
setPos(initialSpan(src), source)
3535

3636
protected def setId(id: Int): Unit = {
3737
myUniqueId = id
@@ -155,66 +155,49 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod
155155
newpd
156156
}
157157

158-
/** The source of the first element of this node that has a position */
159-
def elemsSource: SourceFile = {
160-
def firstSource(x: Any): SourceFile = x match {
161-
case x: Positioned if x.span.exists =>
162-
x.source
163-
case x1 :: xs1 =>
164-
val f = firstSource(x1)
165-
if (f.exists) f else firstSource(xs1)
166-
case _ =>
167-
NoSource
168-
}
169-
def firstElemSource(n: Int): SourceFile =
170-
if (n == productArity) NoSource
171-
else {
172-
val f = firstSource(productElement(n))
173-
if (f.exists) f else firstElemSource(n + 1)
174-
}
175-
firstElemSource(0)
176-
}
177-
178-
/** The source file to use for the `id` of this node. This is
179-
* `elemsSource` if it exists, or the source file indicated by
180-
* `src` otherwise
181-
*/
182-
private def initialSource(src: SourceInfo): SourceFile = {
183-
val f = elemsSource
184-
if (f.exists) f else src.source
185-
}
186-
187158
/** The initial, synthetic span. This is usually the union of all positioned children's spans.
188-
* @param ignoreTypeTrees If true, TypeTree children are not counted for the span.
189-
* This is important for predicting whether a position entry is
190-
* needed for pickling, since TypeTrees are pickled as types, so
191-
* their position is lost.
192159
*/
193-
def initialSpan(ignoreTypeTrees: Boolean = false): Span = {
160+
def initialSpan(si: SourceInfo): Span = {
194161

195-
def include(p1: Span, p2: Positioned) = p2 match {
196-
case _: Trees.TypeTree[_] if ignoreTypeTrees => p1
197-
case _ => p1.union(p2.span)
162+
def include(span1: Span, p2: Positioned): Span = {
163+
val span2 = p2.span
164+
if (span2.exists) {
165+
var src = if (uniqueId == -1) NoSource else source
166+
val src2 = p2.source
167+
if (src `eq` src2) span1.union(span2)
168+
else if (!src.exists) {
169+
setId(src2.nextId)
170+
if (span1.exists) initialSpan(si) // we might have some mis-classified children; re-run everything
171+
else span2
172+
}
173+
else span1 // sources differ: ignore child span
174+
}
175+
else span1
198176
}
199177

200178
def includeAll(span: Span, xs: List[_]): Span = xs match {
201-
case (p: Positioned) :: xs1 if sameSource(p) => includeAll(include(span, p), xs1)
179+
case Nil => span
180+
case (p: Positioned) :: xs1 => includeAll(include(span, p), xs1)
202181
case (xs0: List[_]) :: xs1 => includeAll(includeAll(span, xs0), xs1)
203182
case _ :: xs1 => includeAll(span, xs1)
204-
case _ => span
205183
}
206184

207-
var n = productArity
185+
val limit = relevantElemCount
186+
var n = 0
208187
var span = NoSpan
209-
while (n > 0) {
210-
n -= 1
188+
while (n < limit) {
211189
productElement(n) match {
212-
case p: Positioned if sameSource(p) => span = include(span, p)
213-
case m: untpd.Modifiers => span = includeAll(includeAll(span, m.mods), m.annotations)
214-
case xs: List[_] => span = includeAll(span, xs)
190+
case p: Positioned =>
191+
span = include(span, p)
192+
case m: untpd.Modifiers =>
193+
span = includeAll(includeAll(span, m.mods), m.annotations)
194+
case xs: ::[_] =>
195+
span = includeAll(span, xs)
215196
case _ =>
216197
}
198+
n += 1
217199
}
200+
if (uniqueId == -1) setId(si.source.nextId)
218201
span.toSynthetic
219202
}
220203

@@ -223,8 +206,6 @@ abstract class Positioned(implicit @transientParam src: SourceInfo) extends Prod
223206
*/
224207
def relevantElemCount = productArity
225208

226-
private def sameSource(that: Positioned) = source `eq` that.source
227-
228209
def contains(that: Positioned): Boolean = {
229210
def isParent(x: Any): Boolean = x match {
230211
case x: Positioned =>

0 commit comments

Comments
 (0)