@@ -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=" 
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  "  " 
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