Skip to content

Commit

Permalink
Support pinpointing in stacktrace
Browse files Browse the repository at this point in the history
  • Loading branch information
liufengyun committed Apr 26, 2021
1 parent 9f9f944 commit b70f63c
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
15 changes: 11 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/init/CycleChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class CycleChecker(cache: Cache) {
val ctor = obj.moduleClass.primaryConstructor
var trace = state.trace.dropWhile(_.symbol != ctor) :+ dep

val pinpointOpt = trace.find(_.isInstanceOf[InstanceUsage])
val traceSuppress = trace.size > traceNumberLimit
if traceSuppress then
// truncate trace up to the first escape of object
Expand All @@ -159,10 +160,16 @@ class CycleChecker(cache: Cache) {
trace = trace :+ elem

val locations = trace.flatMap(_.source)
if cycle.size > 1 then
CyclicObjectInit(cycle, locations, traceSuppress) :: Nil
else
ObjectLeakDuringInit(obj, locations, traceSuppress) :: Nil
val warning =
if cycle.size > 1 then
CyclicObjectInit(cycle, locations, traceSuppress)
else
ObjectLeakDuringInit(obj, locations, traceSuppress)

if pinpointOpt.nonEmpty then
warning.pinpoint(pinpointOpt.get.source.last, "Leaking the object may cause initialization problems")

warning :: Nil
else
val constr = obj.moduleClass.primaryConstructor
state.visitObject(dep) {
Expand Down
32 changes: 30 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/init/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import ast.tpd._
import core._
import Decorators._, printing.SyntaxHighlighting
import Types._, Symbols._, Contexts._
import util.{ SimpleIdentityMap, SourcePosition }

import reporting.MessageRendering

import Effects._, Potentials._

Expand All @@ -30,10 +33,31 @@ object Errors {

def toErrors: Errors = this :: Nil

/** pinpoints in stacktrace */
private var pinpoints: SimpleIdentityMap[Tree, String] = SimpleIdentityMap.empty

def pinpoint(tree: Tree, msg: String): this.type =
this.pinpoints = this.pinpoints.updated(tree, msg)
this

private def stacktracePrefix: String =
val str = if traceSuppressed then "suppressed" else "full"
" Calling trace (" + str + "):\n"

private val render = new MessageRendering {}

private def pinpointText(pos: SourcePosition, msg: String, offset: Int)(using Context): String =
val carets = render.hl("Warning") {
if (pos.startLine == pos.endLine)
"^" * math.max(1, pos.endColumn - pos.startColumn)
else "^"
}

val padding = pos.startColumnPadding + (" " * offset)
val marker = padding + carets
val textline = padding + msg
"\n" + marker + "\n" + textline

def stacktrace(using Context): String = if (trace.isEmpty) "" else stacktracePrefix + {
var indentCount = 0
var last: String = ""
Expand All @@ -45,8 +69,12 @@ object Errors {
val line =
if pos.source.exists then
val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
val code = SyntaxHighlighting.highlight(pos.lineContent.trim)
i"$code\t$loc"
val code = SyntaxHighlighting.highlight(pos.lineContent.stripLineEnd)
val pinpoint =
if !pinpoints.contains(tree) then ""
else pinpointText(pos, pinpoints(tree), indentCount + 3)

i"$code\t$loc" + pinpoint
else
tree.show

Expand Down

0 comments on commit b70f63c

Please sign in to comment.