From cf6d87c703d7899df5b7ee4cfda032001b145600 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Fri, 9 Jul 2021 20:00:03 +1200 Subject: [PATCH 1/2] WIP: make Literate print stacktrace --- src/Literate.jl | 55 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/Literate.jl b/src/Literate.jl index 496f5cbb..567f9d9a 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -782,16 +782,55 @@ function execute_block(sb::Module, block::String; inputfile::String="") end popdisplay(disp) # IOCapture.capture has a try-catch so should always end up here if c.error - error(""" - $(sprint(showerror, c.value)) - when executing the following code block in file `$(Base.contractuser(inputfile))` - - ```julia - $block - ``` - """) + # if c.value isa LoadError + # @info "..." c.value.file c.value.line + # bt = remove_common_backtrace(c.backtrace, backtrace()) + # st = stacktrace(bt) + # @assert length(bt) >= length(st) + # idx = findlast(sf -> sf.func === :eval, st) + # display(st) + # @show idx st[idx] + # bt_ptr = Ptr{Nothing}(st[idx-1].pointer) + # idx = findfirst(isequal(bt_ptr), bt) + # @show idx + # display(stacktrace(bt[1:idx])) + # throw(EvalException(Base.contractuser(inputfile), block, c.value.error, bt[1:idx])) + # else + # throw(EvalException(Base.contractuser(inputfile), block, c.value, remove_common_backtrace(c.backtrace, backtrace()))) + # end + throw(EvalException(Base.contractuser(inputfile), block, c.value, remove_common_backtrace(c.backtrace, backtrace()))) end return c.value, c.output, disp.data end +struct EvalException <: Exception + file :: AbstractString + codeblock :: AbstractString + error :: Any + backtrace :: Any +end + +function Base.showerror(io::IO, e::EvalException) + println(io, "Literate.EvalException: $(typeof(e.error)) when executing code in: $(e.file)") + showerror(io, e.error, e.backtrace) + println(io) +end + +# Stolen from Documenter +function remove_common_backtrace(bt, reference_bt) + cutoff = nothing + # We'll start from the top of the backtrace (end of the array) and go down, checking + # if the backtraces agree + for ridx in 1:length(bt) + # Cancel search if we run out the reference BT or find a non-matching one frames: + if ridx > length(reference_bt) || bt[length(bt) - ridx + 1] != reference_bt[length(reference_bt) - ridx + 1] + cutoff = length(bt) - ridx + 1 + break + end + end + # It's possible that the loop does not find anything, i.e. that all BT elements are in + # the reference_BT too. In that case we'll just return an empty BT. + bt[1:(cutoff === nothing ? 0 : cutoff)] +end + end # module From 3db0d4b2c36b5b6d27403d7db71e3e230ef6f310 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sat, 10 Jul 2021 14:23:10 +1200 Subject: [PATCH 2/2] Also print code blocks --- src/Literate.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Literate.jl b/src/Literate.jl index 567f9d9a..15a27ec6 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -812,8 +812,11 @@ end function Base.showerror(io::IO, e::EvalException) println(io, "Literate.EvalException: $(typeof(e.error)) when executing code in: $(e.file)") + println(io, "While executing the following code block:") + println(io, "```") + println(io, e.codeblock) + println(io, "```") showerror(io, e.error, e.backtrace) - println(io) end # Stolen from Documenter