mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-04 06:32:16 +08:00 
			
		
		
		
	service/dap: move build error to output event (#2482)
This commit is contained in:
		@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-delve/delve/pkg/config"
 | 
						"github.com/go-delve/delve/pkg/config"
 | 
				
			||||||
@ -60,7 +61,7 @@ func GoBuild(debugname string, pkgs []string, buildflags string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GoBuildCombinedOutput builds non-test files in 'pkgs' with the specified 'buildflags'
 | 
					// GoBuildCombinedOutput builds non-test files in 'pkgs' with the specified 'buildflags'
 | 
				
			||||||
// and writes the output at 'debugname'.
 | 
					// and writes the output at 'debugname'.
 | 
				
			||||||
func GoBuildCombinedOutput(debugname string, pkgs []string, buildflags string) ([]byte, error) {
 | 
					func GoBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
 | 
				
			||||||
	args := goBuildArgs(debugname, pkgs, buildflags, false)
 | 
						args := goBuildArgs(debugname, pkgs, buildflags, false)
 | 
				
			||||||
	return gocommandCombinedOutput("build", args...)
 | 
						return gocommandCombinedOutput("build", args...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -74,7 +75,7 @@ func GoTestBuild(debugname string, pkgs []string, buildflags string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GoTestBuildCombinedOutput builds test files 'pkgs' with the specified 'buildflags'
 | 
					// GoTestBuildCombinedOutput builds test files 'pkgs' with the specified 'buildflags'
 | 
				
			||||||
// and writes the output at 'debugname'.
 | 
					// and writes the output at 'debugname'.
 | 
				
			||||||
func GoTestBuildCombinedOutput(debugname string, pkgs []string, buildflags string) ([]byte, error) {
 | 
					func GoTestBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
 | 
				
			||||||
	args := goBuildArgs(debugname, pkgs, buildflags, true)
 | 
						args := goBuildArgs(debugname, pkgs, buildflags, true)
 | 
				
			||||||
	return gocommandCombinedOutput("test", args...)
 | 
						return gocommandCombinedOutput("test", args...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -93,19 +94,21 @@ func goBuildArgs(debugname string, pkgs []string, buildflags string, isTest bool
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func gocommandRun(command string, args ...string) error {
 | 
					func gocommandRun(command string, args ...string) error {
 | 
				
			||||||
	goBuild := gocommandExecCmd(command, args...)
 | 
						_, goBuild := gocommandExecCmd(command, args...)
 | 
				
			||||||
	goBuild.Stderr = os.Stdout
 | 
						goBuild.Stderr = os.Stdout
 | 
				
			||||||
	goBuild.Stdout = os.Stderr
 | 
						goBuild.Stdout = os.Stderr
 | 
				
			||||||
	return goBuild.Run()
 | 
						return goBuild.Run()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func gocommandCombinedOutput(command string, args ...string) ([]byte, error) {
 | 
					func gocommandCombinedOutput(command string, args ...string) (string, []byte, error) {
 | 
				
			||||||
	return gocommandExecCmd(command, args...).CombinedOutput()
 | 
						buildCmd, goBuild := gocommandExecCmd(command, args...)
 | 
				
			||||||
 | 
						out, err := goBuild.CombinedOutput()
 | 
				
			||||||
 | 
						return buildCmd, out, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func gocommandExecCmd(command string, args ...string) *exec.Cmd {
 | 
					func gocommandExecCmd(command string, args ...string) (string, *exec.Cmd) {
 | 
				
			||||||
	allargs := []string{command}
 | 
						allargs := []string{command}
 | 
				
			||||||
	allargs = append(allargs, args...)
 | 
						allargs = append(allargs, args...)
 | 
				
			||||||
	goBuild := exec.Command("go", allargs...)
 | 
						goBuild := exec.Command("go", allargs...)
 | 
				
			||||||
	return goBuild
 | 
						return strings.Join(append([]string{"go"}, allargs...), " "), goBuild
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -723,17 +723,24 @@ func (s *Server) onLaunchRequest(request *dap.LaunchRequest) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		s.log.Debugf("building binary at %s", debugbinary)
 | 
							s.log.Debugf("building binary at %s", debugbinary)
 | 
				
			||||||
 | 
							var cmd string
 | 
				
			||||||
		var out []byte
 | 
							var out []byte
 | 
				
			||||||
		switch mode {
 | 
							switch mode {
 | 
				
			||||||
		case "debug":
 | 
							case "debug":
 | 
				
			||||||
			out, err = gobuild.GoBuildCombinedOutput(debugbinary, []string{program}, buildFlags)
 | 
								cmd, out, err = gobuild.GoBuildCombinedOutput(debugbinary, []string{program}, buildFlags)
 | 
				
			||||||
		case "test":
 | 
							case "test":
 | 
				
			||||||
			out, err = gobuild.GoTestBuildCombinedOutput(debugbinary, []string{program}, buildFlags)
 | 
								cmd, out, err = gobuild.GoTestBuildCombinedOutput(debugbinary, []string{program}, buildFlags)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								s.send(&dap.OutputEvent{
 | 
				
			||||||
 | 
									Event: *newEvent("output"),
 | 
				
			||||||
 | 
									Body: dap.OutputEventBody{
 | 
				
			||||||
 | 
										Output:   fmt.Sprintf("Build Error: %s\n%s (%s)\n", cmd, strings.TrimSpace(string(out)), err.Error()),
 | 
				
			||||||
 | 
										Category: "stderr",
 | 
				
			||||||
 | 
									}})
 | 
				
			||||||
			s.sendErrorResponse(request.Request,
 | 
								s.sendErrorResponse(request.Request,
 | 
				
			||||||
				FailedToLaunch, "Failed to launch",
 | 
									FailedToLaunch, "Failed to launch",
 | 
				
			||||||
				fmt.Sprintf("Build error: %s (%s)", strings.TrimSpace(string(out)), err.Error()))
 | 
									"Build error: Check the debug console for details.")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		program = debugbinary
 | 
							program = debugbinary
 | 
				
			||||||
 | 
				
			|||||||
@ -3144,14 +3144,6 @@ func TestBadLaunchRequests(t *testing.T) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		expectFailedToLaunchWithMessageRegex := func(response *dap.ErrorResponse, errmsg string) {
 | 
					 | 
				
			||||||
			t.Helper()
 | 
					 | 
				
			||||||
			expectFailedToLaunch(response)
 | 
					 | 
				
			||||||
			if matched, _ := regexp.MatchString(errmsg, response.Body.Error.Format); !matched {
 | 
					 | 
				
			||||||
				t.Errorf("\ngot  %q\nwant %q", response.Body.Error.Format, errmsg)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Test for the DAP-specific detailed error message.
 | 
							// Test for the DAP-specific detailed error message.
 | 
				
			||||||
		client.LaunchRequest("exec", "", stopOnEntry)
 | 
							client.LaunchRequest("exec", "", stopOnEntry)
 | 
				
			||||||
		expectFailedToLaunchWithMessage(client.ExpectInvisibleErrorResponse(t),
 | 
							expectFailedToLaunchWithMessage(client.ExpectInvisibleErrorResponse(t),
 | 
				
			||||||
@ -3233,18 +3225,34 @@ func TestBadLaunchRequests(t *testing.T) {
 | 
				
			|||||||
		expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t)) // No such file or directory
 | 
							expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t)) // No such file or directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		client.LaunchRequest("debug", fixture.Path+"_does_not_exist", stopOnEntry)
 | 
							client.LaunchRequest("debug", fixture.Path+"_does_not_exist", stopOnEntry)
 | 
				
			||||||
 | 
							oe := client.ExpectOutputEvent(t)
 | 
				
			||||||
 | 
							if !strings.HasPrefix(oe.Body.Output, "Build Error: ") || oe.Body.Category != "stderr" {
 | 
				
			||||||
 | 
								t.Errorf("got %#v, want Category=\"stderr\" Output=\"Build Error: ...\"", oe)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t))
 | 
							expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		client.LaunchRequest("" /*debug by default*/, fixture.Path+"_does_not_exist", stopOnEntry)
 | 
							client.LaunchRequest("" /*debug by default*/, fixture.Path+"_does_not_exist", stopOnEntry)
 | 
				
			||||||
 | 
							oe = client.ExpectOutputEvent(t)
 | 
				
			||||||
 | 
							if !strings.HasPrefix(oe.Body.Output, "Build Error: ") || oe.Body.Category != "stderr" {
 | 
				
			||||||
 | 
								t.Errorf("got %#v, want Category=\"stderr\" Output=\"Build Error: ...\"", oe)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t))
 | 
							expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		client.LaunchRequest("exec", fixture.Source, stopOnEntry)
 | 
							client.LaunchRequest("exec", fixture.Source, stopOnEntry)
 | 
				
			||||||
		expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t)) // Not an executable
 | 
							expectFailedToLaunch(client.ExpectInvisibleErrorResponse(t)) // Not an executable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "buildFlags": "-bad -flags"})
 | 
							client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "buildFlags": "-bad -flags"})
 | 
				
			||||||
		expectFailedToLaunchWithMessageRegex(client.ExpectInvisibleErrorResponse(t), `Failed to launch: Build error: .*flag provided but not defined.*`)
 | 
							oe = client.ExpectOutputEvent(t)
 | 
				
			||||||
 | 
							if !strings.HasPrefix(oe.Body.Output, "Build Error: ") || oe.Body.Category != "stderr" {
 | 
				
			||||||
 | 
								t.Errorf("got %#v, want Category=\"stderr\" Output=\"Build Error: ...\"", oe)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							expectFailedToLaunchWithMessage(client.ExpectInvisibleErrorResponse(t), "Failed to launch: Build error: Check the debug console for details.")
 | 
				
			||||||
		client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "noDebug": true, "buildFlags": "-bad -flags"})
 | 
							client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "noDebug": true, "buildFlags": "-bad -flags"})
 | 
				
			||||||
		expectFailedToLaunchWithMessageRegex(client.ExpectInvisibleErrorResponse(t), `Failed to launch: Build error: .*flag provided but not defined.*`)
 | 
							oe = client.ExpectOutputEvent(t)
 | 
				
			||||||
 | 
							if !strings.HasPrefix(oe.Body.Output, "Build Error: ") || oe.Body.Category != "stderr" {
 | 
				
			||||||
 | 
								t.Errorf("got %#v, want Category=\"stderr\" Output=\"Build Error: ...\"", oe)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							expectFailedToLaunchWithMessage(client.ExpectInvisibleErrorResponse(t), "Failed to launch: Build error: Check the debug console for details.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Bad "wd".
 | 
							// Bad "wd".
 | 
				
			||||||
		client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "noDebug": false, "cwd": "dir/invalid"})
 | 
							client.LaunchRequestWithArgs(map[string]interface{}{"mode": "debug", "program": fixture.Source, "noDebug": false, "cwd": "dir/invalid"})
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user