@@ -30,11 +30,6 @@ trait MessageRendering {
3030 def stripColor (str : String ): String =
3131 str.replaceAll(" \u001b\\ [.*?m" , " " )
3232
33- /** List of all the inline calls that surround the position */
34- def inlinePosStack (pos : SourcePosition ): List [SourcePosition ] =
35- if pos.outer != null && pos.outer.exists then pos :: inlinePosStack(pos.outer)
36- else Nil
37-
3833 /** Get the sourcelines before and after the position, as well as the offset
3934 * for rendering line numbers
4035 *
@@ -236,17 +231,27 @@ trait MessageRendering {
236231 if origin.nonEmpty then
237232 addHelp(" origin=" )(origin)
238233
239- /** The whole message rendered from `msg` */
240- def messageAndPos (dia : Diagnostic )(using Context ): String = {
241- import dia .*
242- val pos1 = pos.nonInlined
243- val inlineStack = inlinePosStack(pos).filter(_ != pos1)
244- val maxLineNumber =
245- if pos.exists then (pos1 :: inlineStack).map(_.endLine).max + 1
246- else 0
247- given Level = Level (level)
248- given Offset = Offset (maxLineNumber.toString.length + 2 )
249- val sb = StringBuilder ()
234+ /** The whole message rendered from `dia.msg`.
235+ *
236+ * For a position in an inline expansion, choose `pos1`
237+ * which is the most specific position in the call written
238+ * by the user. For a diagnostic at EOF, where the last char
239+ * of source text is a newline, adjust the position to render
240+ * before the newline, at the end of the last line of text.
241+ *
242+ * The rendering begins with a label and position (`posString`).
243+ * Then `sourceLines` with embedded caret `positionMarker`
244+ * and rendered message.
245+ *
246+ * Then an `Inline stack trace` showing context for inlined code.
247+ * Inlined positions are taken which don't contain `pos1`.
248+ * (That should probably be positions not contained by outermost.)
249+ * Note that position equality includes `outer` position;
250+ * usually we intend to test `contains` or `coincidesWith`.
251+ *
252+ */
253+ def messageAndPos (dia : Diagnostic )(using Context ): String =
254+ // adjust a pos at EOF if preceded by newline
250255 def adjust (pos : SourcePosition ): SourcePosition =
251256 if pos.span.isSynthetic
252257 && pos.span.isZeroExtent
@@ -257,54 +262,57 @@ trait MessageRendering {
257262 pos.withSpan(pos.span.shift(- 1 ))
258263 else
259264 pos
260- val adjusted = adjust(pos)
261- val posString = posStr(adjusted, msg, diagnosticLevel(dia))
262- if (posString.nonEmpty) sb.append(posString).append(EOL )
263- if (pos.exists) {
264- val pos1 = pos.nonInlined
265- if (pos1.exists && pos1.source.file.exists) {
266- val readjusted =
267- if pos1 == pos then adjusted
268- else adjust(pos1)
269- val (srcBefore, srcAfter, offset) = sourceLines(readjusted)
270- val marker = positionMarker(readjusted)
271- val err = errorMsg(readjusted, msg.message)
272- sb.append((srcBefore ::: marker :: err :: srcAfter).mkString(EOL ))
273-
274- if inlineStack.nonEmpty then
275- sb.append(EOL ).append(newBox())
276- sb.append(EOL ).append(offsetBox).append(i " Inline stack trace " )
277- for inlinedPos <- inlineStack if inlinedPos != pos1 do
278- sb.append(EOL ).append(newBox(soft = true ))
279- sb.append(EOL ).append(offsetBox).append(i " This location contains code that was inlined from $pos" )
280- if inlinedPos.source.file.exists then
281- val (srcBefore, srcAfter, _) = sourceLines(inlinedPos)
282- val marker = positionMarker(inlinedPos)
283- sb.append(EOL ).append((srcBefore ::: marker :: srcAfter).mkString(EOL ))
284- sb.append(EOL ).append(endBox)
285- }
286- else sb.append(msg.message)
287- }
265+ val msg = dia.msg
266+ val pos = dia.pos
267+ val pos1 = adjust(pos.nonInlined) // innermost pos contained by call.pos
268+ val outermost = pos.outermost // call.pos
269+ val inlineStack = pos.inlinePosStack.filterNot(outermost.contains(_))
270+ given Level = Level (dia.level)
271+ given Offset =
272+ val maxLineNumber =
273+ if pos.exists then (pos1 :: inlineStack).map(_.endLine).max + 1
274+ else 0
275+ Offset (maxLineNumber.toString.length + 2 )
276+ val sb = StringBuilder ()
277+ val posString = posStr(pos1, msg, diagnosticLevel(dia))
278+ if posString.nonEmpty then sb.append(posString).append(EOL )
279+ if pos.exists && pos1.exists && pos1.source.file.exists then
280+ val (srcBefore, srcAfter, offset) = sourceLines(pos1)
281+ val marker = positionMarker(pos1)
282+ val err = errorMsg(pos1, msg.message)
283+ sb.append((srcBefore ::: marker :: err :: srcAfter).mkString(EOL ))
284+
285+ if inlineStack.nonEmpty then
286+ sb.append(EOL ).append(newBox())
287+ sb.append(EOL ).append(offsetBox).append(i " Inline stack trace " )
288+ for inlinedPos <- inlineStack do
289+ sb.append(EOL ).append(newBox(soft = true ))
290+ sb.append(EOL ).append(offsetBox).append(i " This location contains code that was inlined from $pos" )
291+ if inlinedPos.source.file.exists then
292+ val (srcBefore, srcAfter, _) = sourceLines(inlinedPos)
293+ val marker = positionMarker(inlinedPos)
294+ sb.append(EOL ).append((srcBefore ::: marker :: srcAfter).mkString(EOL ))
295+ sb.append(EOL ).append(endBox)
296+ end if
288297 else sb.append(msg.message)
289- if ( dia.isVerbose)
298+ if dia.isVerbose then
290299 appendFilterHelp(dia, sb)
291300
292301 if Diagnostic .shouldExplain(dia) then
293302 sb.append(EOL ).append(newBox())
294303 sb.append(EOL ).append(offsetBox).append(" Explanation (enabled by `-explain`)" )
295304 sb.append(EOL ).append(newBox(soft = true ))
296- dia.msg.explanation.split(raw " \R " ).foreach { line =>
305+ dia.msg.explanation.split(raw " \R " ).foreach: line =>
297306 sb.append(EOL ).append(offsetBox).append(if line.isEmpty then " " else " " ).append(line)
298- }
299307 sb.append(EOL ).append(endBox)
300308 else if dia.msg.canExplain then
301309 sb.append(EOL ).append(offsetBox)
302310 sb.append(EOL ).append(offsetBox).append(" longer explanation available when compiling with `-explain`" )
303311
304312 sb.toString
305- }
313+ end messageAndPos
306314
307- private def hl (str : String )(using Context , Level ): String =
315+ private def hl (str : String )(using Context , Level ): String =
308316 summon[Level ].value match
309317 case interfaces.Diagnostic .ERROR => Red (str).show
310318 case interfaces.Diagnostic .WARNING => Yellow (str).show
0 commit comments