Skip to content

Commit 63f52b1

Browse files
committed
service/dap: accept a string list as launch request's buildFlags
This change accepts both string type and []string. dap.BuildFlags is a union of string and []string. Fixes go-delve#2718 For golang/vscode-go#1831, golang/vscode-go#1027
1 parent f469a0a commit 63f52b1

File tree

4 files changed

+82
-10
lines changed

4 files changed

+82
-10
lines changed

pkg/gobuild/gobuild.go

+31-4
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ func GoBuild(debugname string, pkgs []string, buildflags string) error {
4141

4242
// GoBuildCombinedOutput builds non-test files in 'pkgs' with the specified 'buildflags'
4343
// and writes the output at 'debugname'.
44-
func GoBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
45-
args := goBuildArgs(debugname, pkgs, buildflags, false)
44+
func GoBuildCombinedOutput(debugname string, pkgs []string, buildflags interface{}) (string, []byte, error) {
45+
args, err := goBuildArgs2(debugname, pkgs, buildflags, false)
46+
if err != nil {
47+
return "", nil, err
48+
}
4649
return gocommandCombinedOutput("build", args...)
4750
}
4851

@@ -55,8 +58,11 @@ func GoTestBuild(debugname string, pkgs []string, buildflags string) error {
5558

5659
// GoTestBuildCombinedOutput builds test files 'pkgs' with the specified 'buildflags'
5760
// and writes the output at 'debugname'.
58-
func GoTestBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
59-
args := goBuildArgs(debugname, pkgs, buildflags, true)
61+
func GoTestBuildCombinedOutput(debugname string, pkgs []string, buildflags interface{}) (string, []byte, error) {
62+
args, err := goBuildArgs2(debugname, pkgs, buildflags, true)
63+
if err != nil {
64+
return "", nil, err
65+
}
6066
return gocommandCombinedOutput("test", args...)
6167
}
6268

@@ -84,6 +90,27 @@ func goBuildArgs(debugname string, pkgs []string, buildflags string, isTest bool
8490
return args
8591
}
8692

93+
// goBuildArgs2 is like goBuildArgs, but takes either string or []string.
94+
func goBuildArgs2(debugname string, pkgs []string, buildflags interface{}, isTest bool) ([]string, error) {
95+
var args []string
96+
switch buildflags := buildflags.(type) {
97+
case string:
98+
return goBuildArgs(debugname, pkgs, buildflags, false), nil
99+
case nil:
100+
case []string:
101+
args = append(args, buildflags...)
102+
default:
103+
return nil, fmt.Errorf("invalid buildflags type %T", buildflags)
104+
}
105+
106+
args = append(args, "-o", debugname)
107+
if isTest {
108+
args = append([]string{"-c"}, args...)
109+
}
110+
args = append(args, "-gcflags", "all=-N -l")
111+
return append(args, pkgs...), nil
112+
}
113+
87114
func gocommandRun(command string, args ...string) error {
88115
_, goBuild := gocommandExecCmd(command, args...)
89116
goBuild.Stderr = os.Stdout

service/dap/server.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -982,9 +982,9 @@ func (s *Session) onLaunchRequest(request *dap.LaunchRequest) {
982982

983983
switch args.Mode {
984984
case "debug":
985-
cmd, out, err = gobuild.GoBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags)
985+
cmd, out, err = gobuild.GoBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags.value)
986986
case "test":
987-
cmd, out, err = gobuild.GoTestBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags)
987+
cmd, out, err = gobuild.GoTestBuildCombinedOutput(args.Output, []string{args.Program}, args.BuildFlags.value)
988988
}
989989
args.DlvCwd, _ = filepath.Abs(args.DlvCwd)
990990
s.config.log.Debugf("building from %q: [%s]", args.DlvCwd, cmd)

service/dap/server_test.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -5594,6 +5594,18 @@ func TestLaunchRequestWithBuildFlags(t *testing.T) {
55945594
})
55955595
}
55965596

5597+
func TestLaunchRequestWithBuildFlags2(t *testing.T) {
5598+
runTest(t, "buildflagtest", func(client *daptest.Client, fixture protest.Fixture) {
5599+
runDebugSession(t, client, "launch", func() {
5600+
// We reuse the harness that builds, but ignore the built binary,
5601+
// only relying on the source to be built in response to LaunchRequest.
5602+
client.LaunchRequestWithArgs(map[string]interface{}{
5603+
"mode": "debug", "program": fixture.Source, "output": "__mybin",
5604+
"buildFlags": []string{"-ldflags", "-X main.Hello=World"}})
5605+
})
5606+
})
5607+
}
5608+
55975609
func TestLaunchRequestWithEnv(t *testing.T) {
55985610
// testenv fixture will lookup SOMEVAR with
55995611
// x, y := os.Lookup("SOMEVAR")
@@ -6304,7 +6316,7 @@ func TestBadLaunchRequests(t *testing.T) {
63046316
// Bad "buildFlags"
63056317
client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "buildFlags": 123})
63066318
checkFailedToLaunchWithMessage(client.ExpectVisibleErrorResponse(t),
6307-
"Failed to launch: invalid debug configuration - cannot unmarshal number into \"buildFlags\" of type string")
6319+
"Failed to launch: invalid debug configuration - cannot unmarshal number into \"buildFlags\" of type []string or string")
63086320

63096321
// Bad "backend"
63106322
client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "backend": 123})

service/dap/types.go

+36-3
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,15 @@ type LaunchConfig struct {
102102
// Relative paths used in BuildFlags will be interpreted as paths
103103
// relative to Delve's current working directory.
104104
//
105-
// It is like `dlv --build-flags`. For example,
106-
// "buildFlags": "-tags=integration -mod=vendor -cover -v"
107-
BuildFlags string `json:"buildFlags,omitempty"`
105+
// It should be a string like `dlv --build-flags`, or
106+
// an array of strings that is augmented when invoking the go build or
107+
// test command through os/exec.Command API.
108+
// For example, both forms are acceptible.
109+
// "buildFlags": "-tags=integration -ldflags='-X main.Hello=World'"
110+
// or
111+
// "buildFlags": ["-tags=integration", "-ldflags=-X main.Hello=World"]
112+
// Using other types is an error.
113+
BuildFlags BuildFlags `json:"buildFlags,omitempty"`
108114

109115
// Output path for the binary of the debuggee.
110116
// Relative path is interpreted as the path relative to
@@ -268,3 +274,30 @@ func prettyPrint(config interface{}) string {
268274
}
269275
return string(pretty)
270276
}
277+
278+
// BuildFlags is either string or []string.
279+
type BuildFlags struct{
280+
value interface{}
281+
}
282+
283+
func (s *BuildFlags) UnmarshalJSON(b []byte) error {
284+
if v := string(b); v == "" || v == "null" {
285+
s.value = nil
286+
return nil
287+
}
288+
var strs []string
289+
if err := json.Unmarshal(b, &strs); err == nil {
290+
s.value = strs
291+
return nil
292+
}
293+
var str string
294+
if err := json.Unmarshal(b, &str); err != nil {
295+
s.value = nil
296+
if uerr, ok := err.(*json.UnmarshalTypeError); ok {
297+
return fmt.Errorf(`cannot unmarshal %v into "buildFlags" of type []string or string`, uerr.Value)
298+
}
299+
return err
300+
}
301+
s.value = str
302+
return nil
303+
}

0 commit comments

Comments
 (0)