From d739a50df110e91e73f65eff64fe92a677350b18 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 10 Sep 2023 07:41:16 +0200 Subject: [PATCH] service/dap: strip package paths from symbols in callstack This solves the problem that function names with long package paths are hard to read when the callstack window is narrow, because all you see is the beginning of the package path. For example, instead of github.com/some/long/package/path/pkg.(*SomeType).SomeMethod we now display pkg.(*SomeType).SomeMethod --- service/dap/server.go | 12 ++++++- service/dap/server_test.go | 67 +++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/service/dap/server.go b/service/dap/server.go index 5bb38f1b9b..0883ac4bc9 100644 --- a/service/dap/server.go +++ b/service/dap/server.go @@ -1684,7 +1684,17 @@ func fnName(loc *proc.Location) string { if loc.Fn == nil { return "???" } - return loc.Fn.Name + fullSymbol := loc.Fn.Name + packagePath := loc.Fn.PackageName() + lastSlash := strings.LastIndex(packagePath, "/") + if lastSlash >= 0 { + // strip everything until the last slash from the package path + return fullSymbol[lastSlash+1:] + } + + // We either have no package name at all, or it doesn't contain a slash: + // return name unchanged + return fullSymbol } func fnPackageName(loc *proc.Location) string { diff --git a/service/dap/server_test.go b/service/dap/server_test.go index 26b642d733..7c0296e4ff 100644 --- a/service/dap/server_test.go +++ b/service/dap/server_test.go @@ -1269,6 +1269,71 @@ func TestStackTraceRequest(t *testing.T) { }) } +func TestFunctionNameFormattingInStackTrace(t *testing.T) { + runTest(t, "consts", func(client *daptest.Client, fixture protest.Fixture) { + runDebugSessionWithBPs(t, client, "launch", + // Launch + func() { + client.LaunchRequestWithArgs(map[string]interface{}{ + "mode": "exec", "program": fixture.Path, + }) + }, + // Breakpoints are set within the program + fixture.Source, []int{}, + []onBreakpoint{{ + // Stop at line 36 + execute: func() { + if runtime.GOARCH == "386" && goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) { + client.StepInRequest(1) + client.ExpectStepInResponse(t) + client.ExpectStoppedEvent(t) + } + client.StackTraceRequest(1, 0, 20) + stack := client.ExpectStackTraceResponse(t) + checkStackFramesExact(t, stack, "main.main", 36, 1000, 3, 3) + + // Step into pkg.AnotherMethod() + client.StepInRequest(1) + client.ExpectStepInResponse(t) + client.ExpectStoppedEvent(t) + + client.StackTraceRequest(1, 0, 20) + stack = client.ExpectStackTraceResponse(t) + checkStackFramesExact(t, stack, "pkg.(*SomeType).AnotherMethod", 13, 1000, 4, 4) + }, + disconnect: true, + }}) + }) +} + +func Test_fnName(t *testing.T) { + tests := []struct { + symbol string + want string + }{ + { + symbol: "pkg.functionName", + want: "pkg.functionName", + }, + { + symbol: "github.com/some/long/package/path/pkg.(*SomeType).Method", + want: "pkg.(*SomeType).Method", + }, + { + symbol: "github.com/some/path/pkg.typeparametric[go.shape.struct { example.com/blah/otherpkg.x int }]", + want: "pkg.typeparametric[go.shape.struct { example.com/blah/otherpkg.x int }]", + }, + } + for _, tt := range tests { + t.Run(tt.symbol, func(t *testing.T) { + loc := proc.Location{Fn: &proc.Function{Name: tt.symbol}} + if got := fnName(&loc); got != tt.want { + t.Errorf("fnName() = %v, want %v", got, tt.want) + } + }) + } +} + func TestSelectedThreadsRequest(t *testing.T) { runTest(t, "goroutinestackprog", func(client *daptest.Client, fixture protest.Fixture) { runDebugSessionWithBPs(t, client, "launch", @@ -5547,7 +5612,7 @@ func TestLaunchTestRequest(t *testing.T) { testFile, []int{14}, []onBreakpoint{{ execute: func() { - checkStop(t, client, -1, "github.com/go-delve/delve/_fixtures/buildtest.TestCurrentDirectory", 14) + checkStop(t, client, -1, "buildtest.TestCurrentDirectory", 14) client.VariablesRequest(1001) // Locals locals := client.ExpectVariablesResponse(t) checkChildren(t, locals, "Locals", 1)