Skip to content

Commit 2a81c3e

Browse files
Kordyjananatoliykmetyuk
authored andcommitted
Refactor InlinedsPositioner into InlinedSourceMap
1 parent 780e25c commit 2a81c3e

File tree

3 files changed

+132
-125
lines changed

3 files changed

+132
-125
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import dotty.tools.dotc.util.Spans._
2424
import dotty.tools.dotc.report
2525
import dotty.tools.dotc.transform.SymUtils._
2626

27+
import InlinedSourceMaps._
28+
2729
/*
2830
*
2931
* @author Miguel Garcia, http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
@@ -91,7 +93,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
9193
var isCZParcelable = false
9294
var isCZStaticModule = false
9395

94-
var inlinedsPositioner: InlinedsPositioner = null
96+
var sourceMap: InlinedSourceMap = null
9597

9698
/* ---------------- idiomatic way to ask questions to typer ---------------- */
9799

@@ -279,8 +281,8 @@ trait BCodeSkelBuilder extends BCodeHelpers {
279281
superClass, interfaceNames.toArray)
280282

281283
if (emitSource) {
282-
inlinedsPositioner = InlinedsPositioner(cunit)
283-
cnode.visitSource(cunit.source.file.name, inlinedsPositioner.debugExtension.orNull)
284+
sourceMap = sourceMapFor(cunit)
285+
cnode.visitSource(cunit.source.file.name, sourceMap.debugExtension.orNull)
284286
}
285287

286288
enclosingMethodAttribute(claszSymbol, internalName, asmMethodType(_).descriptor) match {
@@ -552,7 +554,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
552554
}
553555
def lineNumber(tree: Tree): Unit = {
554556
if (!emitLines || !tree.span.exists) return;
555-
val nr = if (tree.source != cunit.source) inlinedsPositioner.lineFor(tree.sourcePos) else Some(ctx.source.offsetToLine(tree.span.point) + 1)
557+
val nr = if (tree.source != cunit.source) sourceMap.lineFor(tree.sourcePos) else Some(ctx.source.offsetToLine(tree.span.point) + 1)
556558
nr match
557559
case Some(nr) if nr != lastEmittedLineNr =>
558560
lastEmittedLineNr = nr

compiler/src/dotty/tools/backend/jvm/InlinedPositioner.scala

Lines changed: 0 additions & 121 deletions
This file was deleted.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package dotty.tools
2+
package backend
3+
package jvm
4+
5+
import dotc.CompilationUnit
6+
import dotc.ast.tpd._
7+
import dotc.util.{ SourcePosition, SourceFile }
8+
import dotc.core.Contexts._
9+
import dotc.report
10+
import dotc.typer.Inliner.InliningPosition
11+
import collection.mutable
12+
13+
import scala.collection.mutable.StringBuilder
14+
15+
object InlinedSourceMaps:
16+
private case class Request(targetPos: SourcePosition, origPos: SourcePosition, firstFakeLine: Int)
17+
18+
private class File(id: Int, name: String, path: Option[String]):
19+
def write(b: mutable.StringBuilder): Unit =
20+
if path.isDefined then b ++= "+ "
21+
b append id
22+
b += ' '
23+
b ++= name
24+
b += '\n'
25+
path.foreach { p =>
26+
b ++= p
27+
b += '\n'
28+
}
29+
end File
30+
31+
private class Mapping(
32+
inputStartLine: Int,
33+
fileId: Int,
34+
repeatCount: Int,
35+
outputStartLine: Int,
36+
increment: Int
37+
):
38+
extension (b: mutable.StringBuilder) def appendNotDefault(prefix: Char, value: Int): Unit =
39+
if value != 1 then
40+
b += prefix
41+
b append value
42+
43+
def write(b: mutable.StringBuilder): Unit =
44+
b append (inputStartLine + 1)
45+
b.appendNotDefault('#', fileId)
46+
b.appendNotDefault(',', repeatCount)
47+
b += ':'
48+
b append (outputStartLine + 1)
49+
b.appendNotDefault(',', increment)
50+
b += '\n'
51+
end Mapping
52+
53+
private class Stratum(name: String, files: List[File], mappings: List[Mapping]):
54+
def write(b: mutable.StringBuilder): Unit =
55+
b ++= "*S "
56+
b ++= name
57+
b ++= "\n*F\n"
58+
files.foreach(_.write(b))
59+
b ++= "*L\n"
60+
mappings.foreach(_.write(b))
61+
b ++= "*E\n"
62+
end Stratum
63+
64+
def sourceMapFor(cunit: CompilationUnit)(using Context): InlinedSourceMap =
65+
val requests = mutable.ListBuffer.empty[Request]
66+
var lastLine = cunit.tpdTree.sourcePos.endLine
67+
68+
class RequestCollector(enclosingFile: SourceFile) extends TreeTraverser:
69+
override def traverse(tree: Tree)(using Context): Unit =
70+
if tree.source != enclosingFile then
71+
tree.getAttachment(InliningPosition) match
72+
case Some(targetPos) =>
73+
val firstFakeLine = allocate(tree.sourcePos)
74+
requests += Request(targetPos, tree.sourcePos, firstFakeLine)
75+
RequestCollector(tree.source).traverseChildren(tree)
76+
case None =>
77+
// Not exactly sure in which cases it is happening. Should we report warning?
78+
RequestCollector(tree.source).traverseChildren(tree)
79+
else traverseChildren(tree)
80+
end RequestCollector
81+
82+
def allocate(origPos: SourcePosition): Int =
83+
val line = lastLine + 1
84+
lastLine += origPos.lines.length
85+
line
86+
87+
RequestCollector(cunit.source).traverse(cunit.tpdTree)
88+
InlinedSourceMap(cunit, requests.toList)
89+
end sourceMapFor
90+
91+
class InlinedSourceMap private[InlinedSourceMaps] (cunit: CompilationUnit, requests: List[Request])(using Context):
92+
def debugExtension: Option[String] = Option.when(requests.nonEmpty) {
93+
val scalaStratum =
94+
val files = cunit.source :: requests.map(_.origPos.source).distinct.filter(_ != cunit.source)
95+
val mappings = requests.map { case Request(_, origPos, firstFakeLine) =>
96+
Mapping(origPos.startLine, files.indexOf(origPos.source) + 1, origPos.lines.length, firstFakeLine, 1)
97+
}
98+
Stratum("Scala", files.zipWithIndex.map { case (f, n) => File(n + 1, f.name, None) }, Mapping(0, 1, cunit.tpdTree.sourcePos.lines.length, 0, 1) +: mappings)
99+
100+
val debugStratum =
101+
val mappings = requests.map { case Request(targetPos, origPos, firstFakeLine) =>
102+
Mapping(targetPos.startLine, 1, 1, firstFakeLine, origPos.lines.length)
103+
}
104+
Stratum("ScalaDebug", File(1, cunit.source.name, None) :: Nil, mappings)
105+
106+
107+
val b = new StringBuilder
108+
b ++= "SMAP\n"
109+
b ++= cunit.source.name
110+
b += '\n'
111+
b ++= "Scala\n"
112+
scalaStratum.write(b)
113+
debugStratum.write(b)
114+
b.toString
115+
}
116+
117+
def lineFor(sourcePos: SourcePosition): Option[Int] =
118+
requests.find(_.origPos.contains(sourcePos)) match
119+
case Some(request) =>
120+
val offset = sourcePos.startLine - request.origPos.startLine
121+
Some(request.firstFakeLine + offset + 1)
122+
case None =>
123+
report.warning(s"${sourcePos.show} was inlined in ${cunit.source} but its inlining position was not recorded.")
124+
None
125+
126+

0 commit comments

Comments
 (0)