@@ -81,43 +81,53 @@ object InlinedSourceMaps:
81
81
b ++= " *E\n "
82
82
end Stratum
83
83
84
+ // targetPos is the position of the inlined call inlined(5)
85
+ // origPos is the position of the inlined code inline def inlined(arg) { ... }
84
86
def sourceMapFor (cunit : CompilationUnit )(internalNameProvider : Symbol => String )(using Context ): InlinedSourceMap =
85
87
val requests = mutable.ListBuffer .empty[(SourcePosition , SourcePosition )]
86
88
var internalNames = Map .empty[SourceFile , String ]
87
89
88
90
class RequestCollector (enclosingFile : SourceFile ) extends TreeTraverser :
89
91
override def traverse (tree : Tree )(using Context ): Unit =
90
- if tree.source != enclosingFile && tree.source != cunit.source then
92
+ if tree.hasAttachment( InliningPosition ) then
91
93
tree.getAttachment(InliningPosition ) match
92
- case Some (InliningPosition (targetPos, cls)) =>
93
- requests += (targetPos -> tree.sourcePos)
94
-
95
- cls match
96
- case Some (symbol) if ! internalNames.isDefinedAt(tree.source) =>
97
- internalNames += (tree.source -> internalNameProvider(symbol))
98
- // We are skipping any internal name info if we already have one stored in our map
99
- // because a debugger will use internal name only to localize matching source.
100
- // Both old and new internal names are associated with the same source file
101
- // so it doesn't matter if internal name is not matching used symbol.
102
- case _ => ()
103
- RequestCollector (tree.source).traverseChildren(tree)
94
+ case Some (InliningPosition (l)) =>
95
+ l.foreach {
96
+ (targetPos, cls) =>
97
+ if tree.source != enclosingFile && tree.source != cunit.source then
98
+ requests += (targetPos -> tree.sourcePos)
99
+
100
+ cls match
101
+ case Some (symbol) if ! internalNames.isDefinedAt(tree.source) =>
102
+ internalNames += (tree.source -> internalNameProvider(symbol))
103
+ // We are skipping any internal name info if we already have one stored in our map
104
+ // because a debugger will use internal name only to localize matching source.
105
+ // Both old and new internal names are associated with the same source file
106
+ // so it doesn't matter if internal name is not matching used symbol.
107
+ case _ => ()
108
+ }
109
+ traverseChildren(tree)
104
110
case None =>
105
111
// Not exactly sure in which cases it is happening. Should we report warning?
106
- RequestCollector (tree.source).traverseChildren(tree)
107
- else traverseChildren(tree)
112
+ traverseChildren(tree)
113
+ else
114
+ traverseChildren(tree)
108
115
end RequestCollector
109
116
110
117
// Don't generate mappings for the quotes compiled at runtime by the staging compiler
111
118
if cunit.source.file.isVirtual then InlinedSourceMap (cunit, Nil , Map .empty[SourceFile , String ])
112
119
else
113
120
var lastLine = cunit.tpdTree.sourcePos.endLine
121
+ // returns the first fake line (starting from 0)
114
122
def allocate (origPos : SourcePosition ): Int =
115
123
val line = lastLine + 1
116
124
lastLine += origPos.lines.length
117
125
line
118
126
119
127
RequestCollector (cunit.source).traverse(cunit.tpdTree)
120
- val allocated = requests.sortBy(_._1.start).map(r => Request (r._1, r._2, allocate(r._2)))
128
+
129
+ val allocated = requests.map(r => Request (r._1, r._2, allocate(r._2)))
130
+
121
131
InlinedSourceMap (cunit, allocated.toList, internalNames)
122
132
end sourceMapFor
123
133
@@ -153,13 +163,26 @@ object InlinedSourceMaps:
153
163
b.toString
154
164
}
155
165
156
- def lineFor (sourcePos : SourcePosition , lastRealNr : Int ): Option [Int ] =
157
- requests.find(r => r.origPos.contains(sourcePos) && r.targetPos.endLine + 1 >= lastRealNr) match
166
+ var lastNestedInlineLine = - 1
167
+
168
+ def lineFor (sourcePos : SourcePosition , lastRealNr : Int , attachement : Option [InliningPosition ]): Option [Int ] =
169
+
170
+ if attachement.isDefined then
171
+ attachement.get.targetPos.find(p => p._1.source == sourcePos.source) match
172
+ case Some ((pos, _)) =>
173
+ lastNestedInlineLine = pos.startLine
174
+ case None => ()
175
+
176
+ requests.find(r =>
177
+ r.origPos.contains(sourcePos) &&
178
+ (if r.targetPos.source == cunit.source then r.targetPos.endLine + 1 >= lastRealNr
179
+ else r.targetPos.startLine >= lastNestedInlineLine
180
+ )
181
+ ) match
158
182
case Some (request) =>
159
183
val offset = sourcePos.startLine - request.origPos.startLine
160
- Some (request.firstFakeLine + offset + 1 )
184
+ val virtualLine = request.firstFakeLine + offset
185
+ Some (virtualLine + 1 ) // + 1 because the first line is 1 in the LineNumberTable
161
186
case None =>
162
187
// report.warning(s"${sourcePos.show} was inlined in ${cunit.source} but its inlining position was not recorded.")
163
- None
164
-
165
-
188
+ None
0 commit comments