From a51109ef13d63b4514e0537bbe449d46920a1247 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Sat, 22 Jun 2024 17:44:39 +0200 Subject: [PATCH 01/10] Adding DAP implementation for debugging OPA Signed-off-by: Johan Fylling --- cmd/debugger.go | 408 +++++++++++++++++++++++++++++++++++++ go.mod | 9 +- go.sum | 36 ++-- internal/dap/dap.go | 453 +++++++++++++++++++++++++++++++++++++++++ internal/dap/logger.go | 129 ++++++++++++ 5 files changed, 1016 insertions(+), 19 deletions(-) create mode 100644 cmd/debugger.go create mode 100644 internal/dap/dap.go create mode 100644 internal/dap/logger.go diff --git a/cmd/debugger.go b/cmd/debugger.go new file mode 100644 index 00000000..7a27e416 --- /dev/null +++ b/cmd/debugger.go @@ -0,0 +1,408 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "io" + "os" + "strings" + + godap "github.com/google/go-dap" + "github.com/open-policy-agent/opa/ast/location" + "github.com/open-policy-agent/opa/debug" + "github.com/open-policy-agent/opa/logging" + "github.com/spf13/cobra" + "github.com/styrainc/regal/internal/dap" +) + +func init() { + verboseLogging := false + + debuggerCommand := &cobra.Command{ + Use: "debug", + Short: "Run the Regal OPA Debugger", + Long: `Start the Regal OPA debugger and listen on stdin/stdout for client editor messages.`, + + RunE: wrapProfiling(func([]string) error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := dap.NewDebugLogger(logging.New(), logging.Debug) + if verboseLogging { + logger.Local.SetLevel(logging.Debug) + } + + protoManager := dap.NewProtocolManager(logger.Local) + logger.ProtocolManager = protoManager + + debugParams := []debug.DebuggerOption{ + debug.SetEventHandler(newEventHandler(protoManager)), + debug.SetLogger(logger), + } + + debugger := debug.NewDebugger(debugParams...) + + conn := newCmdConn(os.Stdin, os.Stdout) + s := newState(ctx, protoManager, debugger, logger) + return protoManager.Start(ctx, conn, s.messageHandler) + }), + } + + debuggerCommand.Flags().BoolVarP(&verboseLogging, "verbose", "v", verboseLogging, "Enable verbose logging") + + RootCommand.AddCommand(debuggerCommand) +} + +type state struct { + ctx context.Context + protocolManager *dap.ProtocolManager + debugger debug.Debugger + session debug.Session + logger *dap.DebugLogger + serverCapabilities *godap.Capabilities + clientCapabilities *godap.InitializeRequestArguments +} + +func newState(ctx context.Context, protocolManager *dap.ProtocolManager, debugger debug.Debugger, logger *dap.DebugLogger) *state { + return &state{ + ctx: ctx, + protocolManager: protocolManager, + debugger: debugger, + logger: logger, + serverCapabilities: &godap.Capabilities{ + SupportsBreakpointLocationsRequest: true, + SupportsCancelRequest: true, + SupportsConfigurationDoneRequest: true, + SupportsSingleThreadExecutionRequests: true, + SupportSuspendDebuggee: true, + SupportTerminateDebuggee: true, + SupportsTerminateRequest: true, + }, + } +} + +func newEventHandler(pm *dap.ProtocolManager) debug.EventHandler { + return func(e debug.DebugEvent) { + switch e.Type { + case debug.ExceptionEventType: + pm.SendEvent(dap.NewStoppedExceptionEvent(e.Thread, e.Message)) + case debug.StdoutEventType: + pm.SendEvent(dap.NewOutputEvent("stdout", e.Message)) + case debug.StoppedEventType: + pm.SendEvent(dap.NewStoppedEvent(e.Message, e.Thread, nil, "", "")) + case debug.TerminatedEventType: + pm.SendEvent(dap.NewTerminatedEvent()) + case debug.ThreadEventType: + pm.SendEvent(dap.NewThreadEvent(e.Thread, e.Message)) + } + } +} + +func (s *state) messageHandler(message godap.Message) (bool, godap.ResponseMessage, error) { + var resp godap.ResponseMessage + var err error + switch request := message.(type) { + case *godap.AttachRequest: + resp = dap.NewAttachResponse() + err = fmt.Errorf("attach not supported") + case *godap.BreakpointLocationsRequest: + resp, err = s.breakpointLocations(request) + case *godap.ConfigurationDoneRequest: + // FIXME: Is this when we should start eval? + resp = dap.NewConfigurationDoneResponse() + case *godap.ContinueRequest: + resp, err = s.resume(request) + case *godap.DisconnectRequest: + return true, dap.NewDisconnectResponse(), nil + case *godap.EvaluateRequest: + resp, err = s.evaluate(request) + case *godap.InitializeRequest: + resp, err = s.initialize(request) + case *godap.LaunchRequest: + resp, err = s.launch(request) + case *godap.NextRequest: + resp, err = s.next(request) + case *godap.ScopesRequest: + resp, err = s.scopes(request) + case *godap.SetBreakpointsRequest: + resp, err = s.setBreakpoints(request) + case *godap.StackTraceRequest: + resp, err = s.stackTrace(request) + case *godap.StepInRequest: + resp, err = s.stepIn(request) + case *godap.StepOutRequest: + resp, err = s.stepOut(request) + case *godap.TerminateRequest: + resp, err = s.terminate(request) + case *godap.ThreadsRequest: + resp, err = s.threads(request) + case *godap.VariablesRequest: + resp, err = s.variables(request) + default: + s.logger.Warn("Handler not found for request: %T", message) + err = fmt.Errorf("handler not found for request: %T", message) + } + return false, resp, err +} + +func (s *state) initialize(r *godap.InitializeRequest) (*godap.InitializeResponse, error) { + if args, err := json.Marshal(r.Arguments); err == nil { + s.logger.Info("Initializing: %s", args) + } else { + s.logger.Info("Initializing") + } + + s.clientCapabilities = &r.Arguments + + return dap.NewInitializeResponse(*s.serverCapabilities), nil +} + +type launchProperties struct { + Command string `json:"command"` + LogLevel string `json:"log_level"` +} + +func (s *state) launch(r *godap.LaunchRequest) (*godap.LaunchResponse, error) { + var props launchProperties + if err := json.Unmarshal(r.Arguments, &props); err != nil { + return dap.NewLaunchResponse(), fmt.Errorf("invalid launch properties: %v", err) + } + + if props.LogLevel != "" { + s.logger.SetLevelFromString(props.LogLevel) + } else { + s.logger.SetRemoteEnabled(false) + } + + s.logger.Info("Launching: %s", props) + + var err error + switch props.Command { + case "eval": + var evalProps debug.LaunchEvalProperties + if err := json.Unmarshal(r.Arguments, &evalProps); err != nil { + return dap.NewLaunchResponse(), fmt.Errorf("invalid launch eval properties: %v", err) + } + // FIXME: Should we protect this with a mutex? + s.session, err = s.debugger.LaunchEval(s.ctx, evalProps) + case "test": + err = fmt.Errorf("test not supported") + case "": + err = fmt.Errorf("missing launch command") + default: + err = fmt.Errorf("unsupported launch command: '%s'", props.Command) + } + + if err == nil { + s.protocolManager.SendEvent(dap.NewInitializedEvent()) + } + + err = s.session.ResumeAll() + + return dap.NewLaunchResponse(), err +} + +func (s *state) evaluate(_ *godap.EvaluateRequest) (*godap.EvaluateResponse, error) { + return dap.NewEvaluateResponse(""), fmt.Errorf("evaluate not supported") +} + +func (s *state) resume(r *godap.ContinueRequest) (*godap.ContinueResponse, error) { + return dap.NewContinueResponse(), s.session.Resume(debug.ThreadID(r.Arguments.ThreadId)) +} + +func (s *state) next(r *godap.NextRequest) (*godap.NextResponse, error) { + return dap.NewNextResponse(), s.session.StepOver(debug.ThreadID(r.Arguments.ThreadId)) +} + +func (s *state) stepIn(r *godap.StepInRequest) (*godap.StepInResponse, error) { + return dap.NewStepInResponse(), s.session.StepIn(debug.ThreadID(r.Arguments.ThreadId)) +} + +func (s *state) stepOut(r *godap.StepOutRequest) (*godap.StepOutResponse, error) { + return dap.NewStepOutResponse(), s.session.StepOut(debug.ThreadID(r.Arguments.ThreadId)) +} + +func (s *state) threads(_ *godap.ThreadsRequest) (*godap.ThreadsResponse, error) { + var threads []godap.Thread + ts, err := s.session.Threads() + if err == nil { + for _, t := range ts { + threads = append(threads, godap.Thread{Id: int(t.Id()), Name: t.Name()}) + } + } + return dap.NewThreadsResponse(threads), err +} + +func (s *state) stackTrace(r *godap.StackTraceRequest) (*godap.StackTraceResponse, error) { + var stackFrames []godap.StackFrame + fs, err := s.session.StackTrace(debug.ThreadID(r.Arguments.ThreadId)) + if err == nil { + for _, f := range fs { + var source *godap.Source + source, line, col, endLine, endCol := pos(f.Location()) + stackFrames = append(stackFrames, godap.StackFrame{ + Id: int(f.ID()), + Name: f.Name(), + Source: source, + Line: line, + Column: col, + EndLine: endLine, + EndColumn: endCol, + PresentationHint: "normal", + }) + } + } + return dap.NewStackTraceResponse(stackFrames), err +} + +func pos(loc *location.Location) (source *godap.Source, line, col, endLine, endCol int) { + if loc == nil { + return nil, 1, 0, 1, 0 + } + + if loc.File != "" { + source = &godap.Source{ + Path: loc.File, + } + } + + lines := strings.Split(string(loc.Text), "\n") + line = loc.Row + col = loc.Col + + // vs-code will select text if multiple lines are present; avoid this + //endLine = loc.Row + len(lines) - 1 + //endCol = col + len(lines[len(lines)-1]) + endLine = line + endCol = col + len(lines[0]) + return +} + +func (s *state) scopes(r *godap.ScopesRequest) (*godap.ScopesResponse, error) { + var scopes []godap.Scope + ss, err := s.session.Scopes(debug.FrameID(r.Arguments.FrameId)) + if err == nil { + for _, s := range ss { + var source *godap.Source + line := 1 + if loc := s.Location(); loc != nil { + line = loc.Row + if loc.File != "" { + source = &godap.Source{ + Path: loc.File, + } + } + } + scopes = append(scopes, godap.Scope{ + Name: s.Name(), + NamedVariables: s.NamedVariables(), + VariablesReference: int(s.VariablesReference()), + Source: source, + Line: line, + }) + } + } + return dap.NewScopesResponse(scopes), err +} + +func (s *state) variables(r *godap.VariablesRequest) (*godap.VariablesResponse, error) { + var variables []godap.Variable + vs, err := s.session.Variables(debug.VarRef(r.Arguments.VariablesReference)) + if err == nil { + for _, v := range vs { + variables = append(variables, godap.Variable{ + Name: v.Name(), + Value: v.Value(), + Type: v.Type(), + VariablesReference: int(v.VariablesReference()), + }) + } + } + return dap.NewVariablesResponse(variables), err +} + +func (s *state) breakpointLocations(request *godap.BreakpointLocationsRequest) (*godap.BreakpointLocationsResponse, error) { + line := request.Arguments.Line + s.logger.Debug("Breakpoint locations requested for: %s:%d", request.Arguments.Source.Name, line) + + // TODO: Actually assert where breakpoints can be placed. + return dap.NewBreakpointLocationsResponse([]godap.BreakpointLocation{ + { + Line: line, + Column: 1, + }, + }), nil +} + +func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.SetBreakpointsResponse, error) { + locations := make([]location.Location, len(request.Arguments.Breakpoints)) + for i, bp := range request.Arguments.Breakpoints { + locations[i] = location.Location{ + File: request.Arguments.Source.Path, + Row: bp.Line, + } + } + + var breakpoints []godap.Breakpoint + bps, err := s.session.SetBreakpoints(locations) + if err == nil { + for _, bp := range bps { + var source *godap.Source + line := 1 + l := bp.Location() + line = bp.Location().Row + if bp.Location().File != "" { + source = &godap.Source{ + Path: l.File, + } + } + breakpoints = append(breakpoints, godap.Breakpoint{ + Id: bp.Id(), + Source: source, + Line: line, + Verified: true, + }) + } + } + + return dap.NewSetBreakpointsResponse(breakpoints), err +} + +func (s *state) terminate(_ *godap.TerminateRequest) (*godap.TerminateResponse, error) { + return dap.NewTerminateResponse(), s.session.Terminate() +} + +type cmdConn struct { + in io.ReadCloser + out io.WriteCloser +} + +func newCmdConn(in io.ReadCloser, out io.WriteCloser) *cmdConn { + return &cmdConn{ + in: in, + out: out, + } +} + +func (c *cmdConn) Read(p []byte) (n int, err error) { + return c.in.Read(p) +} + +func (c *cmdConn) Write(p []byte) (n int, err error) { + return c.out.Write(p) +} + +func (c *cmdConn) Close() error { + var errs []error + if err := c.in.Close(); err != nil { + errs = append(errs, err) + } + if err := c.out.Close(); err != nil { + errs = append(errs, err) + } + if len(errs) > 0 { + return fmt.Errorf("errors: %v", errs) + } + return nil +} diff --git a/go.mod b/go.mod index 55f7edba..8fb6f420 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/gobwas/glob v0.2.3 github.com/google/go-cmp v0.6.0 + github.com/google/go-dap v0.12.0 github.com/mitchellh/mapstructure v1.5.0 github.com/olekukonko/tablewriter v0.0.5 github.com/open-policy-agent/opa v0.66.0 @@ -26,7 +27,7 @@ require ( github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/tcell v1.1.4 // indirect @@ -58,9 +59,11 @@ require ( go.opentelemetry.io/otel/metric v1.21.0 // indirect go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497 diff --git a/go.sum b/go.sum index 301c1f18..161ef914 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqy github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -61,8 +61,8 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -77,6 +77,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-dap v0.12.0 h1:rVcjv3SyMIrpaOoTAdFDyHs99CwVOItIJGKLQFQhNeM= +github.com/google/go-dap v0.12.0/go.mod h1:tNjCASCm5cqePi/RVXXWEVqtnNLV1KTWtYOqu6rZNzc= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -90,6 +92,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9K github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497 h1:XRzOpVyRSH8C8YNXQlokJQL4wp3vNKci3llwR/Qss7Q= +github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497/go.mod h1:0KAybKnTTNQdZaofj4RPUJh24N8wCcYZHbnzU2icTU4= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -195,8 +199,8 @@ golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -206,8 +210,8 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -217,14 +221,14 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/dap/dap.go b/internal/dap/dap.go new file mode 100644 index 00000000..50ebf91d --- /dev/null +++ b/internal/dap/dap.go @@ -0,0 +1,453 @@ +// Copyright 2024 The OPA Authors. All rights reserved. +// Use of this source code is governed by an Apache2 +// license that can be found in the LICENSE file. + +package dap + +import ( + "bufio" + "context" + "encoding/json" + "io" + "sync" + + "github.com/google/go-dap" + godap "github.com/google/go-dap" + "github.com/open-policy-agent/opa/debug" + "github.com/open-policy-agent/opa/logging" +) + +type MessageHandler func(request godap.Message) (bool, godap.ResponseMessage, error) + +type ProtocolManager struct { + //handle messageHandler + inChan chan godap.Message + outChan chan godap.Message + logger logging.Logger + seq int + seqLock sync.Mutex +} + +func NewProtocolManager(logger logging.Logger) *ProtocolManager { + return &ProtocolManager{ + //handle: handler, + inChan: make(chan godap.Message), + outChan: make(chan godap.Message), + logger: logger, + } +} + +func (pm *ProtocolManager) Start(ctx context.Context, conn io.ReadWriteCloser, handle MessageHandler) error { + reader := bufio.NewReader(conn) + done := make(chan error) + + go func() { + for resp := range pm.outChan { + if pm.logger.GetLevel() == logging.Debug { + if respData, _ := json.Marshal(resp); respData != nil { + pm.logger.Debug("Sending %T\n%s", resp, respData) + } else { + pm.logger.Debug("Sending %T", resp) + } + } + if err := godap.WriteProtocolMessage(conn, resp); err != nil { + done <- err + return + } + } + }() + + go func() { + for { + pm.logger.Debug("Waiting for message...") + req, err := godap.ReadProtocolMessage(reader) + if err != nil { + done <- err + return + } + + if pm.logger.GetLevel() == logging.Debug { + if reqData, _ := json.Marshal(req); reqData != nil { + pm.logger.Debug("Received %T\n%s", req, reqData) + } else { + pm.logger.Debug("Received %T", req) + } + } + + stop, resp, err := handle(req) + if err != nil { + pm.logger.Warn("Error handling request: %v", err) + } + pm.SendResponse(resp, req, err) + if stop { + done <- err + return + } + } + }() + + for { + select { + case err := <-done: + return err + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (pm *ProtocolManager) SendEvent(e godap.EventMessage) { + e.GetEvent().Seq = pm.nextSeq() + pm.outChan <- e +} + +func (pm *ProtocolManager) SendResponse(resp godap.ResponseMessage, req godap.Message, err error) { + if resp == nil { + return + } + + if r := resp.GetResponse(); r != nil { + r.Success = err == nil + if err != nil { + r.Message = err.Error() + } + r.Seq = pm.nextSeq() + if req != nil { + r.RequestSeq = req.GetSeq() + } + } + pm.outChan <- resp +} + +func (pm *ProtocolManager) Close() { + close(pm.outChan) + close(pm.inChan) +} + +func (pm *ProtocolManager) nextSeq() int { + if pm == nil { + return 0 + } + pm.seqLock.Lock() + defer pm.seqLock.Unlock() + pm.seq++ + return pm.seq +} + +func NewContinueResponse() *godap.ContinueResponse { + return &godap.ContinueResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "continue", + Success: true, + }, + } +} + +func NewNextResponse() *godap.NextResponse { + return &godap.NextResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "next", + Success: true, + }, + } +} + +func NewStepInResponse() *godap.StepInResponse { + return &godap.StepInResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "stepIn", + Success: true, + }, + } +} + +func NewStepOutResponse() *godap.StepOutResponse { + return &godap.StepOutResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "stepOut", + Success: true, + }, + } +} + +func NewInitializeResponse(capabilities godap.Capabilities) *godap.InitializeResponse { + return &godap.InitializeResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + //Seq: pm.nextSeq(), + Type: "response", + }, + Command: "initialize", + //RequestSeq: r.GetSeq(), + Success: true, + }, + Body: capabilities, + } +} + +func NewAttachResponse() *godap.AttachResponse { + return &godap.AttachResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "attach", + Success: true, + }, + } +} + +func NewBreakpointLocationsResponse(breakpoints []godap.BreakpointLocation) *godap.BreakpointLocationsResponse { + return &godap.BreakpointLocationsResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "breakpointLocations", + Success: true, + }, + Body: godap.BreakpointLocationsResponseBody{ + Breakpoints: breakpoints, + }, + } +} + +func NewSetBreakpointsResponse(breakpoints []godap.Breakpoint) *godap.SetBreakpointsResponse { + return &godap.SetBreakpointsResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "setBreakpoints", + Success: true, + }, + Body: godap.SetBreakpointsResponseBody{ + Breakpoints: breakpoints, + }, + } +} + +func NewConfigurationDoneResponse() *godap.ConfigurationDoneResponse { + return &godap.ConfigurationDoneResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "configurationDone", + Success: true, + }, + } +} + +func NewDisconnectResponse() *godap.DisconnectResponse { + return &godap.DisconnectResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "disconnect", + Success: true, + }, + } +} + +func NewEvaluateResponse(value string) *godap.EvaluateResponse { + return &godap.EvaluateResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "evaluate", + Success: true, + }, + Body: godap.EvaluateResponseBody{ + Result: value, + }, + } +} + +func NewLaunchResponse() *godap.LaunchResponse { + return &godap.LaunchResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "launch", + Success: true, + }, + } +} + +func NewScopesResponse(scopes []godap.Scope) *godap.ScopesResponse { + return &godap.ScopesResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "scopes", + Success: true, + }, + Body: dap.ScopesResponseBody{ + Scopes: scopes, + }, + } +} + +func NewStackTraceResponse(stack []godap.StackFrame) *godap.StackTraceResponse { + return &godap.StackTraceResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "stackTrace", + Success: true, + }, + Body: godap.StackTraceResponseBody{ + StackFrames: stack, + TotalFrames: len(stack), + }, + } +} + +func NewTerminateResponse() *godap.TerminateResponse { + return &godap.TerminateResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "terminate", + Success: true, + }, + } +} + +func NewThreadsResponse(threads []godap.Thread) *godap.ThreadsResponse { + return &godap.ThreadsResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "threads", + Success: true, + }, + Body: godap.ThreadsResponseBody{ + Threads: threads, + }, + } +} + +func NewVariablesResponse(variables []godap.Variable) *godap.VariablesResponse { + return &godap.VariablesResponse{ + Response: godap.Response{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "response", + }, + Command: "variables", + Success: true, + }, + Body: godap.VariablesResponseBody{ + Variables: variables, + }, + } +} + +// Events + +func NewInitializedEvent() *godap.InitializedEvent { + return &godap.InitializedEvent{ + Event: godap.Event{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "event", + }, + Event: "initialized", + }, + } +} + +func NewOutputEvent(category string, output string) *godap.OutputEvent { + return &godap.OutputEvent{ + Event: godap.Event{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "event", + }, + Event: "output", + }, + Body: godap.OutputEventBody{ + Output: output, + Category: category, + }, + } +} + +func NewThreadEvent(threadId debug.ThreadID, reason string) *godap.ThreadEvent { + return &godap.ThreadEvent{ + Event: godap.Event{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "event", + }, + Event: "thread", + }, + Body: godap.ThreadEventBody{ + Reason: reason, + ThreadId: int(threadId), + }, + } +} + +func NewTerminatedEvent() *godap.TerminatedEvent { + return &godap.TerminatedEvent{ + Event: godap.Event{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "event", + }, + Event: "terminated", + }, + } +} + +func NewStoppedEntryEvent(threadId debug.ThreadID) *godap.StoppedEvent { + return NewStoppedEvent("entry", threadId, nil, "", "") +} + +func NewStoppedExceptionEvent(threadId debug.ThreadID, text string) *godap.StoppedEvent { + return NewStoppedEvent("exception", threadId, nil, "", text) +} + +func NewStoppedResultEvent(threadId debug.ThreadID) *godap.StoppedEvent { + return NewStoppedEvent("result", threadId, nil, "", "") +} + +func NewStoppedBreakpointEvent(threadId debug.ThreadID, bp *godap.Breakpoint) *godap.StoppedEvent { + return NewStoppedEvent("breakpoint", threadId, []int{bp.Id}, "", "") +} + +func NewStoppedEvent(reason string, threadId debug.ThreadID, bps []int, description string, text string) *godap.StoppedEvent { + return &godap.StoppedEvent{ + Event: godap.Event{ + ProtocolMessage: godap.ProtocolMessage{ + Type: "event", + }, + Event: "stopped", + }, + Body: godap.StoppedEventBody{ + Reason: reason, + ThreadId: int(threadId), + Text: text, + AllThreadsStopped: true, + HitBreakpointIds: bps, + PreserveFocusHint: false, + }, + } +} diff --git a/internal/dap/logger.go b/internal/dap/logger.go new file mode 100644 index 00000000..49e63a92 --- /dev/null +++ b/internal/dap/logger.go @@ -0,0 +1,129 @@ +package dap + +import ( + strFmt "fmt" + + "github.com/open-policy-agent/opa/logging" +) + +type DebugLogger struct { + Local logging.Logger + ProtocolManager *ProtocolManager + + level logging.Level + remoteEnabled bool +} + +func NewDebugLogger(localLogger logging.Logger, level logging.Level) *DebugLogger { + return &DebugLogger{ + Local: localLogger, + level: level, + } +} + +func (l *DebugLogger) Debug(fmt string, a ...interface{}) { + if l == nil { + return + } + l.Local.Debug(fmt, a...) + l.send(logging.Debug, fmt, a...) +} + +func (l *DebugLogger) Info(fmt string, a ...interface{}) { + if l == nil { + return + } + l.Local.Info(fmt, a...) + l.send(logging.Info, fmt, a...) +} + +func (l *DebugLogger) Error(fmt string, a ...interface{}) { + if l == nil { + return + } + l.Local.Error(fmt, a...) + l.send(logging.Error, fmt, a...) +} + +func (l *DebugLogger) Warn(fmt string, a ...interface{}) { + if l == nil { + return + } + l.Local.Warn(fmt, a...) + l.send(logging.Warn, fmt, a...) +} + +func (l *DebugLogger) WithFields(map[string]interface{}) logging.Logger { + if l == nil { + return nil + } + return l +} + +func (l *DebugLogger) GetLevel() logging.Level { + if l == nil { + return 0 + } + if l.Local.GetLevel() > l.level { + return l.level + } + return l.level +} + +func (l *DebugLogger) SetRemoteEnabled(enabled bool) { + if l == nil { + return + } + l.remoteEnabled = enabled +} + +func (l *DebugLogger) SetLevel(level logging.Level) { + if l == nil { + return + } + l.level = level +} + +func (l *DebugLogger) SetLevelFromString(level string) { + if l == nil { + return + } + + l.remoteEnabled = true + + switch level { + case "error": + l.level = logging.Error + case "warn": + l.level = logging.Warn + case "info": + l.level = logging.Info + case "debug": + l.level = logging.Debug + } +} + +func (l *DebugLogger) send(level logging.Level, fmt string, a ...interface{}) { + if l == nil || l.ProtocolManager == nil || !l.remoteEnabled || level > l.level { + return + } + + var levelStr string + switch level { + + case logging.Error: + levelStr = "ERROR" + case logging.Warn: + levelStr = "WARN" + case logging.Info: + levelStr = "INFO" + case logging.Debug: + levelStr = "DEBUG" + default: + levelStr = "UNKNOWN" + } + + message := strFmt.Sprintf(fmt, a...) + output := strFmt.Sprintf("%s: %s\n", levelStr, message) + l.ProtocolManager.SendEvent(NewOutputEvent("console", output)) +} From 07c726f873dfc825752c2b96811610a619c6559e Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Fri, 19 Jul 2024 14:43:21 +0200 Subject: [PATCH 02/10] Adding `--server` flag to `debug` command to more easily debug the debugger --- cmd/debugger.go | 78 ++++++++++++++++++++++++++++++++++++++++++------- go.mod | 2 +- go.sum | 6 ++-- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index 7a27e416..32f3f56e 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "net" "os" "strings" @@ -18,6 +19,8 @@ import ( func init() { verboseLogging := false + serverMode := false + address := "localhost:4712" debuggerCommand := &cobra.Command{ Use: "debug", @@ -33,6 +36,62 @@ func init() { logger.Local.SetLevel(logging.Debug) } + if serverMode { + return startServer(ctx, address, logger) + } + + return startCmd(ctx, logger) + }), + } + + debuggerCommand.Flags().BoolVarP(&verboseLogging, "verbose", "v", verboseLogging, "Enable verbose logging") + debuggerCommand.Flags().BoolVarP(&serverMode, "server", "s", serverMode, "Start the debugger in server mode") + debuggerCommand.Flags().StringVarP(&address, "address", "a", address, "Address to listen on. For use with --server flag.") + + RootCommand.AddCommand(debuggerCommand) +} + +func startCmd(ctx context.Context, logger *dap.DebugLogger) error { + protoManager := dap.NewProtocolManager(logger.Local) + logger.ProtocolManager = protoManager + + debugParams := []debug.DebuggerOption{ + debug.SetEventHandler(newEventHandler(protoManager)), + debug.SetLogger(logger), + } + + debugger := debug.NewDebugger(debugParams...) + + conn := newCmdConn(os.Stdin, os.Stdout) + s := newState(ctx, protoManager, debugger, logger) + return protoManager.Start(ctx, conn, s.messageHandler) +} + +func startServer(ctx context.Context, address string, logger *dap.DebugLogger) error { + + l, err := net.Listen("tcp", address) + if err != nil { + return err + } + + logger.Local.Info("Listening on %s", address) + + for { + conn, err := l.Accept() + if err != nil { + return err + } + + logger.Local.Info("New connection from %s", conn.RemoteAddr()) + + go func() { + defer func() { + if err := conn.Close(); err != nil { + logger.Local.Error("Error closing connection: %v", err) + } + logger.Local.Info("Connection closed") + }() + protoManager := dap.NewProtocolManager(logger.Local) logger.ProtocolManager = protoManager @@ -43,15 +102,14 @@ func init() { debugger := debug.NewDebugger(debugParams...) - conn := newCmdConn(os.Stdin, os.Stdout) s := newState(ctx, protoManager, debugger, logger) - return protoManager.Start(ctx, conn, s.messageHandler) - }), - } - - debuggerCommand.Flags().BoolVarP(&verboseLogging, "verbose", "v", verboseLogging, "Enable verbose logging") + if err := protoManager.Start(ctx, conn, s.messageHandler); err != nil { + logger.Local.Error("Error handling connection: %v", err) + } - RootCommand.AddCommand(debuggerCommand) + logger.Local.Info("Closing connection...") + }() + } } type state struct { @@ -83,7 +141,7 @@ func newState(ctx context.Context, protocolManager *dap.ProtocolManager, debugge } func newEventHandler(pm *dap.ProtocolManager) debug.EventHandler { - return func(e debug.DebugEvent) { + return func(e debug.Event) { switch e.Type { case debug.ExceptionEventType: pm.SendEvent(dap.NewStoppedExceptionEvent(e.Thread, e.Message)) @@ -228,7 +286,7 @@ func (s *state) threads(_ *godap.ThreadsRequest) (*godap.ThreadsResponse, error) ts, err := s.session.Threads() if err == nil { for _, t := range ts { - threads = append(threads, godap.Thread{Id: int(t.Id()), Name: t.Name()}) + threads = append(threads, godap.Thread{Id: int(t.ID()), Name: t.Name()}) } } return dap.NewThreadsResponse(threads), err @@ -358,7 +416,7 @@ func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.Set } } breakpoints = append(breakpoints, godap.Breakpoint{ - Id: bp.Id(), + Id: int(bp.ID()), Source: source, Line: line, Verified: true, diff --git a/go.mod b/go.mod index 8fb6f420..fcf479ae 100644 --- a/go.mod +++ b/go.mod @@ -66,4 +66,4 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497 +replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863 diff --git a/go.sum b/go.sum index 161ef914..3fc6dc3f 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9K github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497 h1:XRzOpVyRSH8C8YNXQlokJQL4wp3vNKci3llwR/Qss7Q= -github.com/johanfylling/opa v0.35.1-0.20240718112810-6c1f9914b497/go.mod h1:0KAybKnTTNQdZaofj4RPUJh24N8wCcYZHbnzU2icTU4= +github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863 h1:x1RZHeYlFRsksSlov+P4QHtnMJtkbuEdy5TIATqYqXs= +github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863/go.mod h1:0KAybKnTTNQdZaofj4RPUJh24N8wCcYZHbnzU2icTU4= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -121,8 +121,6 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/open-policy-agent/opa v0.66.0 h1:DbrvfJQja0FBRcPOB3Z/BOckocN+M4ApNWyNhSRJt0w= -github.com/open-policy-agent/opa v0.66.0/go.mod h1:EIgNnJcol7AvQR/IcWLwL13k64gHVbNAVG46b2G+/EY= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= github.com/owenrumney/go-sarif/v2 v2.3.3 h1:ubWDJcF5i3L/EIOER+ZyQ03IfplbSU1BLOE26uKQIIU= github.com/owenrumney/go-sarif/v2 v2.3.3/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w= From fd219a55559c11c112482e3e3ec2bc656303517d Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Fri, 19 Jul 2024 18:15:48 +0200 Subject: [PATCH 03/10] Shadowing `abs` instead of `contains` built-in func since `contains` is also a keyword --- e2e/testdata/violations/most_violations.rego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/testdata/violations/most_violations.rego b/e2e/testdata/violations/most_violations.rego index 46e483b4..aa9cdc24 100644 --- a/e2e/testdata/violations/most_violations.rego +++ b/e2e/testdata/violations/most_violations.rego @@ -60,7 +60,7 @@ not_equals_in_loop if { } # rule-shadows-builtin -contains := true +abs := true top_level_iteration := input[_] From cc911d58b59a5494ecc464aafe35d3245df12245 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Fri, 19 Jul 2024 18:22:19 +0200 Subject: [PATCH 04/10] Making linter happy Signed-off-by: Johan Fylling --- cmd/debugger.go | 129 +++++++++++++++++++++++++++-------------- internal/dap/dap.go | 62 +++++++++++--------- internal/dap/logger.go | 16 ++++- 3 files changed, 137 insertions(+), 70 deletions(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index 32f3f56e..bf72f473 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -3,6 +3,7 @@ package cmd import ( "context" "encoding/json" + "errors" "fmt" "io" "net" @@ -10,10 +11,12 @@ import ( "strings" godap "github.com/google/go-dap" + "github.com/spf13/cobra" + "github.com/open-policy-agent/opa/ast/location" "github.com/open-policy-agent/opa/debug" "github.com/open-policy-agent/opa/logging" - "github.com/spf13/cobra" + "github.com/styrainc/regal/internal/dap" ) @@ -44,9 +47,12 @@ func init() { }), } - debuggerCommand.Flags().BoolVarP(&verboseLogging, "verbose", "v", verboseLogging, "Enable verbose logging") - debuggerCommand.Flags().BoolVarP(&serverMode, "server", "s", serverMode, "Start the debugger in server mode") - debuggerCommand.Flags().StringVarP(&address, "address", "a", address, "Address to listen on. For use with --server flag.") + debuggerCommand.Flags().BoolVarP( + &verboseLogging, "verbose", "v", verboseLogging, "Enable verbose logging") + debuggerCommand.Flags().BoolVarP( + &serverMode, "server", "s", serverMode, "Start the debugger in server mode") + debuggerCommand.Flags().StringVarP( + &address, "address", "a", address, "Address to listen on. For use with --server flag.") RootCommand.AddCommand(debuggerCommand) } @@ -63,15 +69,19 @@ func startCmd(ctx context.Context, logger *dap.DebugLogger) error { debugger := debug.NewDebugger(debugParams...) conn := newCmdConn(os.Stdin, os.Stdout) - s := newState(ctx, protoManager, debugger, logger) - return protoManager.Start(ctx, conn, s.messageHandler) + s := newState(protoManager, debugger, logger) + + if err := protoManager.Start(ctx, conn, s.messageHandler); err != nil { + return fmt.Errorf("failed to handle connection: %w", err) + } + + return nil } func startServer(ctx context.Context, address string, logger *dap.DebugLogger) error { - l, err := net.Listen("tcp", address) if err != nil { - return err + return fmt.Errorf("could not listen: %w", err) } logger.Local.Info("Listening on %s", address) @@ -79,7 +89,7 @@ func startServer(ctx context.Context, address string, logger *dap.DebugLogger) e for { conn, err := l.Accept() if err != nil { - return err + return fmt.Errorf("could not accept: %w", err) } logger.Local.Info("New connection from %s", conn.RemoteAddr()) @@ -89,6 +99,7 @@ func startServer(ctx context.Context, address string, logger *dap.DebugLogger) e if err := conn.Close(); err != nil { logger.Local.Error("Error closing connection: %v", err) } + logger.Local.Info("Connection closed") }() @@ -102,9 +113,9 @@ func startServer(ctx context.Context, address string, logger *dap.DebugLogger) e debugger := debug.NewDebugger(debugParams...) - s := newState(ctx, protoManager, debugger, logger) + s := newState(protoManager, debugger, logger) if err := protoManager.Start(ctx, conn, s.messageHandler); err != nil { - logger.Local.Error("Error handling connection: %v", err) + logger.Local.Error("Failed to handle connection: %v", err) } logger.Local.Info("Closing connection...") @@ -113,7 +124,6 @@ func startServer(ctx context.Context, address string, logger *dap.DebugLogger) e } type state struct { - ctx context.Context protocolManager *dap.ProtocolManager debugger debug.Debugger session debug.Session @@ -122,9 +132,8 @@ type state struct { clientCapabilities *godap.InitializeRequestArguments } -func newState(ctx context.Context, protocolManager *dap.ProtocolManager, debugger debug.Debugger, logger *dap.DebugLogger) *state { +func newState(protocolManager *dap.ProtocolManager, debugger debug.Debugger, logger *dap.DebugLogger) *state { return &state{ - ctx: ctx, protocolManager: protocolManager, debugger: debugger, logger: logger, @@ -157,15 +166,17 @@ func newEventHandler(pm *dap.ProtocolManager) debug.EventHandler { } } -func (s *state) messageHandler(message godap.Message) (bool, godap.ResponseMessage, error) { +func (s *state) messageHandler(ctx context.Context, message godap.Message) (bool, godap.ResponseMessage, error) { var resp godap.ResponseMessage + var err error + switch request := message.(type) { case *godap.AttachRequest: resp = dap.NewAttachResponse() - err = fmt.Errorf("attach not supported") + err = errors.New("attach not supported") case *godap.BreakpointLocationsRequest: - resp, err = s.breakpointLocations(request) + resp = s.breakpointLocations(request) case *godap.ConfigurationDoneRequest: // FIXME: Is this when we should start eval? resp = dap.NewConfigurationDoneResponse() @@ -176,9 +187,9 @@ func (s *state) messageHandler(message godap.Message) (bool, godap.ResponseMessa case *godap.EvaluateRequest: resp, err = s.evaluate(request) case *godap.InitializeRequest: - resp, err = s.initialize(request) + resp = s.initialize(request) case *godap.LaunchRequest: - resp, err = s.launch(request) + resp, err = s.launch(ctx, request) case *godap.NextRequest: resp, err = s.next(request) case *godap.ScopesRequest: @@ -201,10 +212,11 @@ func (s *state) messageHandler(message godap.Message) (bool, godap.ResponseMessa s.logger.Warn("Handler not found for request: %T", message) err = fmt.Errorf("handler not found for request: %T", message) } + return false, resp, err } -func (s *state) initialize(r *godap.InitializeRequest) (*godap.InitializeResponse, error) { +func (s *state) initialize(r *godap.InitializeRequest) *godap.InitializeResponse { if args, err := json.Marshal(r.Arguments); err == nil { s.logger.Info("Initializing: %s", args) } else { @@ -213,7 +225,7 @@ func (s *state) initialize(r *godap.InitializeRequest) (*godap.InitializeRespons s.clientCapabilities = &r.Arguments - return dap.NewInitializeResponse(*s.serverCapabilities), nil + return dap.NewInitializeResponse(*s.serverCapabilities) } type launchProperties struct { @@ -221,10 +233,10 @@ type launchProperties struct { LogLevel string `json:"log_level"` } -func (s *state) launch(r *godap.LaunchRequest) (*godap.LaunchResponse, error) { +func (s *state) launch(ctx context.Context, r *godap.LaunchRequest) (*godap.LaunchResponse, error) { var props launchProperties if err := json.Unmarshal(r.Arguments, &props); err != nil { - return dap.NewLaunchResponse(), fmt.Errorf("invalid launch properties: %v", err) + return dap.NewLaunchResponse(), fmt.Errorf("invalid launch properties: %w", err) } if props.LogLevel != "" { @@ -236,18 +248,20 @@ func (s *state) launch(r *godap.LaunchRequest) (*godap.LaunchResponse, error) { s.logger.Info("Launching: %s", props) var err error + switch props.Command { case "eval": var evalProps debug.LaunchEvalProperties if err := json.Unmarshal(r.Arguments, &evalProps); err != nil { - return dap.NewLaunchResponse(), fmt.Errorf("invalid launch eval properties: %v", err) + return dap.NewLaunchResponse(), fmt.Errorf("invalid launch eval properties: %w", err) } + // FIXME: Should we protect this with a mutex? - s.session, err = s.debugger.LaunchEval(s.ctx, evalProps) + s.session, err = s.debugger.LaunchEval(ctx, evalProps) case "test": - err = fmt.Errorf("test not supported") + err = errors.New("test not supported") case "": - err = fmt.Errorf("missing launch command") + err = errors.New("missing launch command") default: err = fmt.Errorf("unsupported launch command: '%s'", props.Command) } @@ -261,8 +275,8 @@ func (s *state) launch(r *godap.LaunchRequest) (*godap.LaunchResponse, error) { return dap.NewLaunchResponse(), err } -func (s *state) evaluate(_ *godap.EvaluateRequest) (*godap.EvaluateResponse, error) { - return dap.NewEvaluateResponse(""), fmt.Errorf("evaluate not supported") +func (*state) evaluate(_ *godap.EvaluateRequest) (*godap.EvaluateResponse, error) { + return dap.NewEvaluateResponse(""), errors.New("evaluate not supported") } func (s *state) resume(r *godap.ContinueRequest) (*godap.ContinueResponse, error) { @@ -283,17 +297,20 @@ func (s *state) stepOut(r *godap.StepOutRequest) (*godap.StepOutResponse, error) func (s *state) threads(_ *godap.ThreadsRequest) (*godap.ThreadsResponse, error) { var threads []godap.Thread + ts, err := s.session.Threads() if err == nil { for _, t := range ts { threads = append(threads, godap.Thread{Id: int(t.ID()), Name: t.Name()}) } } + return dap.NewThreadsResponse(threads), err } func (s *state) stackTrace(r *godap.StackTraceRequest) (*godap.StackTraceResponse, error) { var stackFrames []godap.StackFrame + fs, err := s.session.StackTrace(debug.ThreadID(r.Arguments.ThreadId)) if err == nil { for _, f := range fs { @@ -311,6 +328,7 @@ func (s *state) stackTrace(r *godap.StackTraceRequest) (*godap.StackTraceRespons }) } } + return dap.NewStackTraceResponse(stackFrames), err } @@ -330,28 +348,34 @@ func pos(loc *location.Location) (source *godap.Source, line, col, endLine, endC col = loc.Col // vs-code will select text if multiple lines are present; avoid this - //endLine = loc.Row + len(lines) - 1 - //endCol = col + len(lines[len(lines)-1]) + // endLine = loc.Row + len(lines) - 1 + // endCol = col + len(lines[len(lines)-1]) endLine = line endCol = col + len(lines[0]) + return } func (s *state) scopes(r *godap.ScopesRequest) (*godap.ScopesResponse, error) { var scopes []godap.Scope + ss, err := s.session.Scopes(debug.FrameID(r.Arguments.FrameId)) if err == nil { for _, s := range ss { var source *godap.Source + line := 1 + if loc := s.Location(); loc != nil { line = loc.Row + if loc.File != "" { source = &godap.Source{ Path: loc.File, } } } + scopes = append(scopes, godap.Scope{ Name: s.Name(), NamedVariables: s.NamedVariables(), @@ -361,11 +385,13 @@ func (s *state) scopes(r *godap.ScopesRequest) (*godap.ScopesResponse, error) { }) } } + return dap.NewScopesResponse(scopes), err } func (s *state) variables(r *godap.VariablesRequest) (*godap.VariablesResponse, error) { var variables []godap.Variable + vs, err := s.session.Variables(debug.VarRef(r.Arguments.VariablesReference)) if err == nil { for _, v := range vs { @@ -377,10 +403,11 @@ func (s *state) variables(r *godap.VariablesRequest) (*godap.VariablesResponse, }) } } + return dap.NewVariablesResponse(variables), err } -func (s *state) breakpointLocations(request *godap.BreakpointLocationsRequest) (*godap.BreakpointLocationsResponse, error) { +func (s *state) breakpointLocations(request *godap.BreakpointLocationsRequest) *godap.BreakpointLocationsResponse { line := request.Arguments.Line s.logger.Debug("Breakpoint locations requested for: %s:%d", request.Arguments.Source.Name, line) @@ -390,11 +417,12 @@ func (s *state) breakpointLocations(request *godap.BreakpointLocationsRequest) ( Line: line, Column: 1, }, - }), nil + }) } func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.SetBreakpointsResponse, error) { locations := make([]location.Location, len(request.Arguments.Breakpoints)) + for i, bp := range request.Arguments.Breakpoints { locations[i] = location.Location{ File: request.Arguments.Source.Path, @@ -403,18 +431,21 @@ func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.Set } var breakpoints []godap.Breakpoint + bps, err := s.session.SetBreakpoints(locations) if err == nil { for _, bp := range bps { var source *godap.Source - line := 1 - l := bp.Location() - line = bp.Location().Row - if bp.Location().File != "" { + + loc := bp.Location() + line := loc.Row + + if loc.File != "" { source = &godap.Source{ - Path: l.File, + Path: loc.File, } } + breakpoints = append(breakpoints, godap.Breakpoint{ Id: int(bp.ID()), Source: source, @@ -443,24 +474,38 @@ func newCmdConn(in io.ReadCloser, out io.WriteCloser) *cmdConn { } } -func (c *cmdConn) Read(p []byte) (n int, err error) { - return c.in.Read(p) +func (c *cmdConn) Read(p []byte) (int, error) { + n, err := c.in.Read(p) + if err != nil { + return n, fmt.Errorf("failed to read: %w", err) + } + + return n, nil } -func (c *cmdConn) Write(p []byte) (n int, err error) { - return c.out.Write(p) +func (c *cmdConn) Write(p []byte) (int, error) { + n, err := c.out.Write(p) + if err != nil { + return n, fmt.Errorf("failed to write: %w", err) + } + + return n, nil } func (c *cmdConn) Close() error { var errs []error + if err := c.in.Close(); err != nil { errs = append(errs, err) } + if err := c.out.Close(); err != nil { errs = append(errs, err) } + if len(errs) > 0 { return fmt.Errorf("errors: %v", errs) } + return nil } diff --git a/internal/dap/dap.go b/internal/dap/dap.go index 50ebf91d..aca2de97 100644 --- a/internal/dap/dap.go +++ b/internal/dap/dap.go @@ -1,26 +1,22 @@ -// Copyright 2024 The OPA Authors. All rights reserved. -// Use of this source code is governed by an Apache2 -// license that can be found in the LICENSE file. - package dap import ( "bufio" "context" "encoding/json" + "fmt" "io" "sync" - "github.com/google/go-dap" godap "github.com/google/go-dap" + "github.com/open-policy-agent/opa/debug" "github.com/open-policy-agent/opa/logging" ) -type MessageHandler func(request godap.Message) (bool, godap.ResponseMessage, error) +type MessageHandler func(ctx context.Context, request godap.Message) (bool, godap.ResponseMessage, error) type ProtocolManager struct { - //handle messageHandler inChan chan godap.Message outChan chan godap.Message logger logging.Logger @@ -30,7 +26,6 @@ type ProtocolManager struct { func NewProtocolManager(logger logging.Logger) *ProtocolManager { return &ProtocolManager{ - //handle: handler, inChan: make(chan godap.Message), outChan: make(chan godap.Message), logger: logger, @@ -44,14 +39,16 @@ func (pm *ProtocolManager) Start(ctx context.Context, conn io.ReadWriteCloser, h go func() { for resp := range pm.outChan { if pm.logger.GetLevel() == logging.Debug { - if respData, _ := json.Marshal(resp); respData != nil { + if respData, err := json.Marshal(resp); respData != nil && err == nil { pm.logger.Debug("Sending %T\n%s", resp, respData) } else { pm.logger.Debug("Sending %T", resp) } } + if err := godap.WriteProtocolMessage(conn, resp); err != nil { done <- err + return } } @@ -60,27 +57,32 @@ func (pm *ProtocolManager) Start(ctx context.Context, conn io.ReadWriteCloser, h go func() { for { pm.logger.Debug("Waiting for message...") + req, err := godap.ReadProtocolMessage(reader) if err != nil { done <- err + return } if pm.logger.GetLevel() == logging.Debug { - if reqData, _ := json.Marshal(req); reqData != nil { + if reqData, err := json.Marshal(req); reqData != nil && err == nil { pm.logger.Debug("Received %T\n%s", req, reqData) } else { pm.logger.Debug("Received %T", req) } } - stop, resp, err := handle(req) + stop, resp, err := handle(ctx, req) if err != nil { pm.logger.Warn("Error handling request: %v", err) } + pm.SendResponse(resp, req, err) + if stop { done <- err + return } } @@ -91,7 +93,7 @@ func (pm *ProtocolManager) Start(ctx context.Context, conn io.ReadWriteCloser, h case err := <-done: return err case <-ctx.Done(): - return ctx.Err() + return fmt.Errorf("context closed: %w", ctx.Err()) } } } @@ -108,9 +110,11 @@ func (pm *ProtocolManager) SendResponse(resp godap.ResponseMessage, req godap.Me if r := resp.GetResponse(); r != nil { r.Success = err == nil + if err != nil { r.Message = err.Error() } + r.Seq = pm.nextSeq() if req != nil { r.RequestSeq = req.GetSeq() @@ -128,9 +132,12 @@ func (pm *ProtocolManager) nextSeq() int { if pm == nil { return 0 } + pm.seqLock.Lock() defer pm.seqLock.Unlock() + pm.seq++ + return pm.seq } @@ -186,11 +193,9 @@ func NewInitializeResponse(capabilities godap.Capabilities) *godap.InitializeRes return &godap.InitializeResponse{ Response: godap.Response{ ProtocolMessage: godap.ProtocolMessage{ - //Seq: pm.nextSeq(), Type: "response", }, Command: "initialize", - //RequestSeq: r.GetSeq(), Success: true, }, Body: capabilities, @@ -299,7 +304,7 @@ func NewScopesResponse(scopes []godap.Scope) *godap.ScopesResponse { Command: "scopes", Success: true, }, - Body: dap.ScopesResponseBody{ + Body: godap.ScopesResponseBody{ Scopes: scopes, }, } @@ -391,7 +396,7 @@ func NewOutputEvent(category string, output string) *godap.OutputEvent { } } -func NewThreadEvent(threadId debug.ThreadID, reason string) *godap.ThreadEvent { +func NewThreadEvent(threadID debug.ThreadID, reason string) *godap.ThreadEvent { return &godap.ThreadEvent{ Event: godap.Event{ ProtocolMessage: godap.ProtocolMessage{ @@ -401,7 +406,7 @@ func NewThreadEvent(threadId debug.ThreadID, reason string) *godap.ThreadEvent { }, Body: godap.ThreadEventBody{ Reason: reason, - ThreadId: int(threadId), + ThreadId: int(threadID), }, } } @@ -417,23 +422,25 @@ func NewTerminatedEvent() *godap.TerminatedEvent { } } -func NewStoppedEntryEvent(threadId debug.ThreadID) *godap.StoppedEvent { - return NewStoppedEvent("entry", threadId, nil, "", "") +func NewStoppedEntryEvent(threadID debug.ThreadID) *godap.StoppedEvent { + return NewStoppedEvent("entry", threadID, nil, "", "") } -func NewStoppedExceptionEvent(threadId debug.ThreadID, text string) *godap.StoppedEvent { - return NewStoppedEvent("exception", threadId, nil, "", text) +func NewStoppedExceptionEvent(threadID debug.ThreadID, text string) *godap.StoppedEvent { + return NewStoppedEvent("exception", threadID, nil, "", text) } -func NewStoppedResultEvent(threadId debug.ThreadID) *godap.StoppedEvent { - return NewStoppedEvent("result", threadId, nil, "", "") +func NewStoppedResultEvent(threadID debug.ThreadID) *godap.StoppedEvent { + return NewStoppedEvent("result", threadID, nil, "", "") } -func NewStoppedBreakpointEvent(threadId debug.ThreadID, bp *godap.Breakpoint) *godap.StoppedEvent { - return NewStoppedEvent("breakpoint", threadId, []int{bp.Id}, "", "") +func NewStoppedBreakpointEvent(threadID debug.ThreadID, bp *godap.Breakpoint) *godap.StoppedEvent { + return NewStoppedEvent("breakpoint", threadID, []int{bp.Id}, "", "") } -func NewStoppedEvent(reason string, threadId debug.ThreadID, bps []int, description string, text string) *godap.StoppedEvent { +func NewStoppedEvent(reason string, threadID debug.ThreadID, bps []int, description string, + text string, +) *godap.StoppedEvent { return &godap.StoppedEvent{ Event: godap.Event{ ProtocolMessage: godap.ProtocolMessage{ @@ -443,8 +450,9 @@ func NewStoppedEvent(reason string, threadId debug.ThreadID, bps []int, descript }, Body: godap.StoppedEventBody{ Reason: reason, - ThreadId: int(threadId), + ThreadId: int(threadID), Text: text, + Description: description, AllThreadsStopped: true, HitBreakpointIds: bps, PreserveFocusHint: false, diff --git a/internal/dap/logger.go b/internal/dap/logger.go index 49e63a92..533732b7 100644 --- a/internal/dap/logger.go +++ b/internal/dap/logger.go @@ -25,7 +25,9 @@ func (l *DebugLogger) Debug(fmt string, a ...interface{}) { if l == nil { return } + l.Local.Debug(fmt, a...) + l.send(logging.Debug, fmt, a...) } @@ -33,7 +35,9 @@ func (l *DebugLogger) Info(fmt string, a ...interface{}) { if l == nil { return } + l.Local.Info(fmt, a...) + l.send(logging.Info, fmt, a...) } @@ -41,7 +45,9 @@ func (l *DebugLogger) Error(fmt string, a ...interface{}) { if l == nil { return } + l.Local.Error(fmt, a...) + l.send(logging.Error, fmt, a...) } @@ -49,7 +55,9 @@ func (l *DebugLogger) Warn(fmt string, a ...interface{}) { if l == nil { return } + l.Local.Warn(fmt, a...) + l.send(logging.Warn, fmt, a...) } @@ -57,6 +65,7 @@ func (l *DebugLogger) WithFields(map[string]interface{}) logging.Logger { if l == nil { return nil } + return l } @@ -64,9 +73,11 @@ func (l *DebugLogger) GetLevel() logging.Level { if l == nil { return 0 } + if l.Local.GetLevel() > l.level { return l.level } + return l.level } @@ -74,6 +85,7 @@ func (l *DebugLogger) SetRemoteEnabled(enabled bool) { if l == nil { return } + l.remoteEnabled = enabled } @@ -81,6 +93,7 @@ func (l *DebugLogger) SetLevel(level logging.Level) { if l == nil { return } + l.level = level } @@ -109,8 +122,8 @@ func (l *DebugLogger) send(level logging.Level, fmt string, a ...interface{}) { } var levelStr string - switch level { + switch level { case logging.Error: levelStr = "ERROR" case logging.Warn: @@ -125,5 +138,6 @@ func (l *DebugLogger) send(level logging.Level, fmt string, a ...interface{}) { message := strFmt.Sprintf(fmt, a...) output := strFmt.Sprintf("%s: %s\n", levelStr, message) + l.ProtocolManager.SendEvent(NewOutputEvent("console", output)) } From 8ce935bffd48e0fe855cc01149d6b46e2c592473 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Wed, 24 Jul 2024 11:33:48 +0200 Subject: [PATCH 05/10] Fixing NPE when `Debugger.LaunchEval()` fails Signed-off-by: Johan Fylling --- cmd/debugger.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index bf72f473..0a958f51 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -267,11 +267,10 @@ func (s *state) launch(ctx context.Context, r *godap.LaunchRequest) (*godap.Laun } if err == nil { + err = s.session.ResumeAll() s.protocolManager.SendEvent(dap.NewInitializedEvent()) } - err = s.session.ResumeAll() - return dap.NewLaunchResponse(), err } From e785a226be4d95415f2bc082ec2321c8bc08c9e7 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Tue, 20 Aug 2024 12:21:37 +0200 Subject: [PATCH 06/10] Fixing breakpoint issues * Breakpoints would sometimes not be set in time before eval starts and completes * Setting breakpoints for one source file would clear breakpoints for all files. Signed-off-by: Johan Fylling --- cmd/debugger.go | 63 +++++++++++++++++++++----------------- go.mod | 16 +++++----- go.sum | 80 ++++++++++++++++++++++++------------------------- 3 files changed, 83 insertions(+), 76 deletions(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index 0a958f51..730f213c 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -178,7 +178,7 @@ func (s *state) messageHandler(ctx context.Context, message godap.Message) (bool case *godap.BreakpointLocationsRequest: resp = s.breakpointLocations(request) case *godap.ConfigurationDoneRequest: - // FIXME: Is this when we should start eval? + err = s.start() resp = dap.NewConfigurationDoneResponse() case *godap.ContinueRequest: resp, err = s.resume(request) @@ -230,7 +230,7 @@ func (s *state) initialize(r *godap.InitializeRequest) *godap.InitializeResponse type launchProperties struct { Command string `json:"command"` - LogLevel string `json:"log_level"` + LogLevel string `json:"logLevel"` } func (s *state) launch(ctx context.Context, r *godap.LaunchRequest) (*godap.LaunchResponse, error) { @@ -267,13 +267,17 @@ func (s *state) launch(ctx context.Context, r *godap.LaunchRequest) (*godap.Laun } if err == nil { - err = s.session.ResumeAll() + // err = s.session.ResumeAll() s.protocolManager.SendEvent(dap.NewInitializedEvent()) } return dap.NewLaunchResponse(), err } +func (s *state) start() error { + return s.session.ResumeAll() +} + func (*state) evaluate(_ *godap.EvaluateRequest) (*godap.EvaluateResponse, error) { return dap.NewEvaluateResponse(""), errors.New("evaluate not supported") } @@ -420,38 +424,41 @@ func (s *state) breakpointLocations(request *godap.BreakpointLocationsRequest) * } func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.SetBreakpointsResponse, error) { - locations := make([]location.Location, len(request.Arguments.Breakpoints)) - - for i, bp := range request.Arguments.Breakpoints { - locations[i] = location.Location{ - File: request.Arguments.Source.Path, - Row: bp.Line, - } + bps, err := s.session.Breakpoints() + if err != nil { + return dap.NewSetBreakpointsResponse(nil), err } - var breakpoints []godap.Breakpoint + // Remove all breakpoints for the given source. + for _, bp := range bps { + if bp.Location().File != request.Arguments.Source.Path { + continue + } - bps, err := s.session.SetBreakpoints(locations) - if err == nil { - for _, bp := range bps { - var source *godap.Source + if _, err := s.session.RemoveBreakpoint(bp.ID()); err != nil { + return dap.NewSetBreakpointsResponse(nil), err + } + } - loc := bp.Location() - line := loc.Row + breakpoints := make([]godap.Breakpoint, len(request.Arguments.Breakpoints)) - if loc.File != "" { - source = &godap.Source{ - Path: loc.File, - } - } + for _, sbp := range request.Arguments.Breakpoints { + loc := location.Location{ + File: request.Arguments.Source.Path, + Row: sbp.Line, + } - breakpoints = append(breakpoints, godap.Breakpoint{ - Id: int(bp.ID()), - Source: source, - Line: line, - Verified: true, - }) + bp, err := s.session.AddBreakpoint(loc) + if err != nil { + return dap.NewSetBreakpointsResponse(breakpoints), err } + + breakpoints = append(breakpoints, godap.Breakpoint{ + Id: int(bp.ID()), + Source: &godap.Source{Path: loc.File}, + Line: bp.Location().Row, + Verified: true, + }) } return dap.NewSetBreakpointsResponse(breakpoints), err diff --git a/go.mod b/go.mod index fcf479ae..a276143b 100644 --- a/go.mod +++ b/go.mod @@ -55,15 +55,15 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) -replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863 +replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d diff --git a/go.sum b/go.sum index 3fc6dc3f..eba4d54d 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -87,13 +87,13 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863 h1:x1RZHeYlFRsksSlov+P4QHtnMJtkbuEdy5TIATqYqXs= -github.com/johanfylling/opa v0.35.1-0.20240719123043-aef2d042f863/go.mod h1:0KAybKnTTNQdZaofj4RPUJh24N8wCcYZHbnzU2icTU4= +github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d h1:DVbBS6E7EQK/pfCYTmqgoEI+PaQCcfls7d0+/BvWJwI= +github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d/go.mod h1:eYxmzwsuyNNZ3I55p7MBAr3v7jEj88egRwLafs95Vg8= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -145,8 +145,8 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -161,8 +161,8 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= @@ -176,31 +176,31 @@ github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Y github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -208,25 +208,25 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 67df8f0bf3036ff13a8802cc1918eef8084475a5 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Tue, 20 Aug 2024 16:36:35 +0200 Subject: [PATCH 07/10] Updating OPA dep Signed-off-by: Johan Fylling --- go.mod | 9 +++++---- go.sum | 25 +++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index a276143b..3241bac9 100644 --- a/go.mod +++ b/go.mod @@ -43,11 +43,12 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.10 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.20.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/rivo/uniseg v0.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -66,4 +67,4 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d +replace github.com/open-policy-agent/opa => github.com/johanfylling/opa v0.35.1-0.20240820142624-aee74fa7ceff diff --git a/go.sum b/go.sum index eba4d54d..4ef2e437 100644 --- a/go.sum +++ b/go.sum @@ -23,9 +23,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= @@ -92,10 +91,10 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737 github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d h1:DVbBS6E7EQK/pfCYTmqgoEI+PaQCcfls7d0+/BvWJwI= -github.com/johanfylling/opa v0.35.1-0.20240820100229-d0f6e616f34d/go.mod h1:eYxmzwsuyNNZ3I55p7MBAr3v7jEj88egRwLafs95Vg8= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/johanfylling/opa v0.35.1-0.20240820142624-aee74fa7ceff h1:KAnA7XYX23RvgXq+2pMXouW7lQbiPosbXT4TrpKn61c= +github.com/johanfylling/opa v0.35.1-0.20240820142624-aee74fa7ceff/go.mod h1:RE/FGopUrWBbUtqVKqsS349ejqtkMFNTIt8gW+wZCjc= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -119,6 +118,8 @@ github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= @@ -133,14 +134,14 @@ github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDj github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= From 513f3a363a1e15fe076c4a6360976cc27392aa59 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Wed, 21 Aug 2024 14:31:25 +0200 Subject: [PATCH 08/10] fixing breakpoints list in `SetBreakpointsResponse` Signed-off-by: Johan Fylling --- cmd/debugger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index 730f213c..92e67e40 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -440,7 +440,7 @@ func (s *state) setBreakpoints(request *godap.SetBreakpointsRequest) (*godap.Set } } - breakpoints := make([]godap.Breakpoint, len(request.Arguments.Breakpoints)) + breakpoints := make([]godap.Breakpoint, 0, len(request.Arguments.Breakpoints)) for _, sbp := range request.Arguments.Breakpoints { loc := location.Location{ From a579bc9e6ae810673de594e5211cce7460505028 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Fri, 30 Aug 2024 09:57:18 +0200 Subject: [PATCH 09/10] Adding back go-dap dependency Signed-off-by: Johan Fylling --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 7589e6cd..9fc3a982 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/gobwas/glob v0.2.3 github.com/google/go-cmp v0.6.0 + github.com/google/go-dap v0.12.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/mitchellh/mapstructure v1.5.0 github.com/olekukonko/tablewriter v0.0.5 diff --git a/go.sum b/go.sum index 9ae2d522..ff3ab6dc 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-dap v0.12.0 h1:rVcjv3SyMIrpaOoTAdFDyHs99CwVOItIJGKLQFQhNeM= +github.com/google/go-dap v0.12.0/go.mod h1:tNjCASCm5cqePi/RVXXWEVqtnNLV1KTWtYOqu6rZNzc= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= From 8604c12091855e46fdb39f0f6826dcca7c810be4 Mon Sep 17 00:00:00 2001 From: Johan Fylling Date: Fri, 30 Aug 2024 10:05:27 +0200 Subject: [PATCH 10/10] Fixing linter issue Signed-off-by: Johan Fylling --- cmd/debugger.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/debugger.go b/cmd/debugger.go index 92e67e40..67119255 100644 --- a/cmd/debugger.go +++ b/cmd/debugger.go @@ -275,7 +275,11 @@ func (s *state) launch(ctx context.Context, r *godap.LaunchRequest) (*godap.Laun } func (s *state) start() error { - return s.session.ResumeAll() + if err := s.session.ResumeAll(); err != nil { + return fmt.Errorf("failed to start debug session: %w", err) + } + + return nil } func (*state) evaluate(_ *godap.EvaluateRequest) (*godap.EvaluateResponse, error) {