terminal,api: move PrintStack function (#2537)
Commit 30cdedae6910f5e9af6739845bacfd5b8778e745 introduced a dependency from service/dap to pkg/terminal to call a stack printing function, it's weird to have code that implements the DAP protocol depend on the code for the JSON-RPC client. Move PrintStack to a different package that can be called by both.
This commit is contained in:
parent
1ecdb3be05
commit
29825d41a6
@ -2331,71 +2331,8 @@ func digits(n int) int {
|
||||
return int(math.Floor(math.Log10(float64(n)))) + 1
|
||||
}
|
||||
|
||||
const stacktraceTruncatedMessage = "(truncated)"
|
||||
|
||||
func printStack(t *Term, out io.Writer, stack []api.Stackframe, ind string, offsets bool) {
|
||||
PrintStack(t.formatPath, out, stack, ind, offsets, func(api.Stackframe) bool { return true })
|
||||
}
|
||||
|
||||
func PrintStack(formatPath func(string) string, out io.Writer, stack []api.Stackframe, ind string, offsets bool, include func(api.Stackframe) bool) {
|
||||
if len(stack) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
extranl := offsets
|
||||
for i := range stack {
|
||||
if extranl {
|
||||
break
|
||||
}
|
||||
extranl = extranl || (len(stack[i].Defers) > 0) || (len(stack[i].Arguments) > 0) || (len(stack[i].Locals) > 0)
|
||||
}
|
||||
|
||||
d := digits(len(stack) - 1)
|
||||
fmtstr := "%s%" + strconv.Itoa(d) + "d 0x%016x in %s\n"
|
||||
s := ind + strings.Repeat(" ", d+2+len(ind))
|
||||
|
||||
for i := range stack {
|
||||
if !include(stack[i]) {
|
||||
continue
|
||||
}
|
||||
if stack[i].Err != "" {
|
||||
fmt.Fprintf(out, "%serror: %s\n", s, stack[i].Err)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, fmtstr, ind, i, stack[i].PC, stack[i].Function.Name())
|
||||
fmt.Fprintf(out, "%sat %s:%d\n", s, formatPath(stack[i].File), stack[i].Line)
|
||||
|
||||
if offsets {
|
||||
fmt.Fprintf(out, "%sframe: %+#x frame pointer %+#x\n", s, stack[i].FrameOffset, stack[i].FramePointerOffset)
|
||||
}
|
||||
|
||||
for j, d := range stack[i].Defers {
|
||||
deferHeader := fmt.Sprintf("%s defer %d: ", s, j+1)
|
||||
s2 := strings.Repeat(" ", len(deferHeader))
|
||||
if d.Unreadable != "" {
|
||||
fmt.Fprintf(out, "%s(unreadable defer: %s)\n", deferHeader, d.Unreadable)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, "%s%#016x in %s\n", deferHeader, d.DeferredLoc.PC, d.DeferredLoc.Function.Name())
|
||||
fmt.Fprintf(out, "%sat %s:%d\n", s2, formatPath(d.DeferredLoc.File), d.DeferredLoc.Line)
|
||||
fmt.Fprintf(out, "%sdeferred by %s at %s:%d\n", s2, d.DeferLoc.Function.Name(), formatPath(d.DeferLoc.File), d.DeferLoc.Line)
|
||||
}
|
||||
|
||||
for j := range stack[i].Arguments {
|
||||
fmt.Fprintf(out, "%s %s = %s\n", s, stack[i].Arguments[j].Name, stack[i].Arguments[j].SinglelineString())
|
||||
}
|
||||
for j := range stack[i].Locals {
|
||||
fmt.Fprintf(out, "%s %s = %s\n", s, stack[i].Locals[j].Name, stack[i].Locals[j].SinglelineString())
|
||||
}
|
||||
|
||||
if extranl {
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
}
|
||||
|
||||
if len(stack) > 0 && !stack[len(stack)-1].Bottom {
|
||||
fmt.Fprintf(out, "%s"+stacktraceTruncatedMessage+"\n", ind)
|
||||
}
|
||||
api.PrintStack(t.formatPath, out, stack, ind, offsets, func(api.Stackframe) bool { return true })
|
||||
}
|
||||
|
||||
func printcontext(t *Term, state *api.DebuggerState) {
|
||||
|
@ -943,6 +943,7 @@ func TestOptimizationCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTruncateStacktrace(t *testing.T) {
|
||||
const stacktraceTruncatedMessage = "(truncated)"
|
||||
withTestTerminal("stacktraceprog", t, func(term *FakeTerminal) {
|
||||
term.MustExec("break main.stacktraceme")
|
||||
term.MustExec("continue")
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -493,3 +494,73 @@ func byteArrayToUInt64(buf []byte, isLittleEndian bool) uint64 {
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
const stacktraceTruncatedMessage = "(truncated)"
|
||||
|
||||
func digits(n int) int {
|
||||
if n <= 0 {
|
||||
return 1
|
||||
}
|
||||
return int(math.Floor(math.Log10(float64(n)))) + 1
|
||||
}
|
||||
|
||||
func PrintStack(formatPath func(string) string, out io.Writer, stack []Stackframe, ind string, offsets bool, include func(Stackframe) bool) {
|
||||
if len(stack) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
extranl := offsets
|
||||
for i := range stack {
|
||||
if extranl {
|
||||
break
|
||||
}
|
||||
extranl = extranl || (len(stack[i].Defers) > 0) || (len(stack[i].Arguments) > 0) || (len(stack[i].Locals) > 0)
|
||||
}
|
||||
|
||||
d := digits(len(stack) - 1)
|
||||
fmtstr := "%s%" + strconv.Itoa(d) + "d 0x%016x in %s\n"
|
||||
s := ind + strings.Repeat(" ", d+2+len(ind))
|
||||
|
||||
for i := range stack {
|
||||
if !include(stack[i]) {
|
||||
continue
|
||||
}
|
||||
if stack[i].Err != "" {
|
||||
fmt.Fprintf(out, "%serror: %s\n", s, stack[i].Err)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, fmtstr, ind, i, stack[i].PC, stack[i].Function.Name())
|
||||
fmt.Fprintf(out, "%sat %s:%d\n", s, formatPath(stack[i].File), stack[i].Line)
|
||||
|
||||
if offsets {
|
||||
fmt.Fprintf(out, "%sframe: %+#x frame pointer %+#x\n", s, stack[i].FrameOffset, stack[i].FramePointerOffset)
|
||||
}
|
||||
|
||||
for j, d := range stack[i].Defers {
|
||||
deferHeader := fmt.Sprintf("%s defer %d: ", s, j+1)
|
||||
s2 := strings.Repeat(" ", len(deferHeader))
|
||||
if d.Unreadable != "" {
|
||||
fmt.Fprintf(out, "%s(unreadable defer: %s)\n", deferHeader, d.Unreadable)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, "%s%#016x in %s\n", deferHeader, d.DeferredLoc.PC, d.DeferredLoc.Function.Name())
|
||||
fmt.Fprintf(out, "%sat %s:%d\n", s2, formatPath(d.DeferredLoc.File), d.DeferredLoc.Line)
|
||||
fmt.Fprintf(out, "%sdeferred by %s at %s:%d\n", s2, d.DeferLoc.Function.Name(), formatPath(d.DeferLoc.File), d.DeferLoc.Line)
|
||||
}
|
||||
|
||||
for j := range stack[i].Arguments {
|
||||
fmt.Fprintf(out, "%s %s = %s\n", s, stack[i].Arguments[j].Name, stack[i].Arguments[j].SinglelineString())
|
||||
}
|
||||
for j := range stack[i].Locals {
|
||||
fmt.Fprintf(out, "%s %s = %s\n", s, stack[i].Locals[j].Name, stack[i].Locals[j].SinglelineString())
|
||||
}
|
||||
|
||||
if extranl {
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
}
|
||||
|
||||
if len(stack) > 0 && !stack[len(stack)-1].Bottom {
|
||||
fmt.Fprintf(out, "%s"+stacktraceTruncatedMessage+"\n", ind)
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import (
|
||||
"github.com/go-delve/delve/pkg/locspec"
|
||||
"github.com/go-delve/delve/pkg/logflags"
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/terminal"
|
||||
"github.com/go-delve/delve/service"
|
||||
"github.com/go-delve/delve/service/api"
|
||||
"github.com/go-delve/delve/service/debugger"
|
||||
@ -2475,7 +2474,7 @@ func (s *Server) onExceptionInfoRequest(request *dap.ExceptionInfoRequest) {
|
||||
fmt.Fprintln(&buf, "Stack:")
|
||||
userLoc := g.UserCurrent()
|
||||
userFuncPkg := fnPackageName(&userLoc)
|
||||
terminal.PrintStack(s.toClientPath, &buf, apiFrames, "\t", false, func(s api.Stackframe) bool {
|
||||
api.PrintStack(s.toClientPath, &buf, apiFrames, "\t", false, func(s api.Stackframe) bool {
|
||||
// Include all stack frames if the stack trace is for a system goroutine,
|
||||
// otherwise, skip runtime stack frames.
|
||||
if userFuncPkg == "runtime" {
|
||||
|
Loading…
Reference in New Issue
Block a user