### InitializeRequest and InitializeResponse Example Source: https://context7.com/google/go-dap/llms.txt Demonstrates the DAP handshake process, where a client sends an InitializeRequest with its capabilities and an adapter responds with its supported features. This is the first message pair in a DAP session. ```go package main import ( "bufio" "bytes" "fmt" "github.com/google/go-dap" ) func main() { // Client sends initialize req := &dap.InitializeRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "request"}, Command: "initialize", }, Arguments: dap.InitializeRequestArguments{ ClientID: "vscode", ClientName: "Visual Studio Code", AdapterID: "go", LinesStartAt1: true, ColumnsStartAt1: true, SupportsVariableType: true, SupportsVariablePaging: true, SupportsRunInTerminalRequest: true, SupportsProgressReporting: true, Locale: "en-us", }, } var buf bytes.Buffer dap.WriteProtocolMessage(&buf, req) // Adapter reads and responds msg, _ := dap.ReadProtocolMessage(bufio.NewReader(&buf)) initReq := msg.(*dap.InitializeRequest) fmt.Printf("Adapter ID: %s, client: %s\n", initReq.Arguments.AdapterID, initReq.Arguments.ClientName) // Adapter builds response with its capabilities resp := &dap.InitializeResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "response"}, RequestSeq: initReq.Seq, Success: true, Command: "initialize", }, Body: dap.Capabilities{ SupportsConfigurationDoneRequest: true, SupportsFunctionBreakpoints: true, SupportsConditionalBreakpoints: true, SupportsProgressReporting: true, SupportsCancelRequest: true, }, } fmt.Printf("Supports function breakpoints: %v\n", resp.Body.SupportsFunctionBreakpoints) // Adapter ID: go, client: Visual Studio Code // Supports function breakpoints: true } ``` -------------------------------- ### Stack Trace Request and Response in Go Source: https://context7.com/google/go-dap/llms.txt Request the call stack frames for a given thread and receive them with source file information. Supports specifying the starting frame and the number of levels to retrieve. ```go package main import ( "fmt" "github.com/google/go-dap" ) func main() { req := &dap.StackTraceRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 8, Type: "request"}, Command: "stackTrace", }, Arguments: dap.StackTraceArguments{ ThreadId: 1, StartFrame: 0, Levels: 20, }, } resp := &dap.StackTraceResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 8, Type: "response"}, RequestSeq: req.Seq, Success: true, Command: "stackTrace", }, Body: dap.StackTraceResponseBody{ StackFrames: []dap.StackFrame{ { Id: 1000, Name: "main.processRequest", Source: &dap.Source{Name: "server.go", Path: "/project/server.go"}, Line: 84, Column: 0, }, { Id: 1001, Name: "main.main", Source: &dap.Source{Name: "main.go", Path: "/project/main.go"}, Line: 12, Column: 0, }, }, TotalFrames: 2, }, } for i, frame := range resp.Body.StackFrames { fmt.Printf("#%d %s %s:%d\n", i, frame.Name, frame.Source.Name, frame.Line) } // #0 main.processRequest server.go:84 // #1 main.main main.go:12 _ = req } ``` -------------------------------- ### Marshal and Write Typed DAP Message Source: https://context7.com/google/go-dap/llms.txt Accepts any dap.Message, JSON-marshals it, and writes it as a base-protocol frame. Includes an example of reading the message back and type-asserting it. ```go package main import ( "bufio" "bytes" "fmt" "github.com/google/go-dap" ) func main() { req := &dap.CancelRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 25, Type: "request"}, Command: "cancel", }, Arguments: &dap.CancelArguments{RequestId: 24}, } var buf bytes.Buffer if err := dap.WriteProtocolMessage(&buf, req); err != nil { panic(err) } // Content-Length: 75\r\n\r\n{"seq":25,"type":"request","command":"cancel","arguments":{"requestId":24}} fmt.Println(buf.String()) // Round-trip: read back msg, err := dap.ReadProtocolMessage(bufio.NewReader(&buf)) if err != nil { panic(err) } cancel := msg.(*dap.CancelRequest) fmt.Printf("Seq=%d CancelledReqId=%d\n", cancel.Seq, cancel.Arguments.RequestId) // Seq=25 CancelledReqId=24 } ``` -------------------------------- ### InitializeRequest and InitializeResponse Source: https://context7.com/google/go-dap/llms.txt Details the first message pair in a DAP session: InitializeRequest sent by the client with its capabilities, and InitializeResponse sent by the adapter declaring supported optional protocol features. ```APIDOC ## InitializeRequest / InitializeResponse The first message pair in every DAP session. The client sends its capabilities; the adapter responds with a `Capabilities` struct declaring what optional protocol features it supports. ### Example Usage This Go code snippet demonstrates the client sending an `InitializeRequest` and the adapter responding with an `InitializeResponse` containing its capabilities. ```go package main import ( "bufio" "bytes" "fmt" "github.com/google/go-dap" ) func main() { // Client sends initialize req := &dap.InitializeRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "request"}, Command: "initialize", }, Arguments: dap.InitializeRequestArguments{ ClientID: "vscode", ClientName: "Visual Studio Code", AdapterID: "go", LinesStartAt1: true, ColumnsStartAt1: true, SupportsVariableType: true, SupportsVariablePaging: true, SupportsRunInTerminalRequest: true, SupportsProgressReporting: true, Locale: "en-us", }, } var buf bytes.Buffer dap.WriteProtocolMessage(&buf, req) // Adapter reads and responds msg, _ := dap.ReadProtocolMessage(bufio.NewReader(&buf)) initReq := msg.(*dap.InitializeRequest) fmt.Printf("Adapter ID: %s, client: %s\n", initReq.Arguments.AdapterID, initReq.Arguments.ClientName) // Adapter builds response with its capabilities resp := &dap.InitializeResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "response"}, RequestSeq: initReq.Seq, Success: true, Command: "initialize", }, Body: dap.Capabilities{ SupportsConfigurationDoneRequest: true, SupportsFunctionBreakpoints: true, SupportsConditionalBreakpoints: true, SupportsProgressReporting: true, SupportsCancelRequest: true, }, } fmt.Printf("Supports function breakpoints: %v\n", resp.Body.SupportsFunctionBreakpoints) // Adapter ID: go, client: Visual Studio Code // Supports function breakpoints: true } ``` ``` -------------------------------- ### Generate Go Types from DAP Schema Source: https://github.com/google/go-dap/blob/main/cmd/gentypes/README.md Run this command to generate Go types from the debugProtocol.json schema. The output is redirected to schematypes.go. ```bash $ go run cmd/gentypes/gentypes.go cmd/gentypes/debugProtocol.json > schematypes.go ``` -------------------------------- ### Set Breakpoints Request and Response in Go Source: https://context7.com/google/go-dap/llms.txt Register breakpoints in a source file and receive verification from the adapter. Supports line numbers, conditions, hit counts, and log messages. ```go package main import ( "fmt" "github.com/google/go-dap" ) func main() { req := &dap.SetBreakpointsRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 3, Type: "request"}, Command: "setBreakpoints", }, Arguments: dap.SetBreakpointsArguments{ Source: dap.Source{ Name: "main.go", Path: "/home/user/project/main.go", }, Breakpoints: []dap.SourceBreakpoint{ {Line: 42}, {Line: 87, Condition: "x > 10"}, {Line: 120, HitCondition: "5", LogMessage: "hit line 120"}, }, }, } // Adapter processes and responds resp := &dap.SetBreakpointsResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 3, Type: "response"}, RequestSeq: req.Seq, Success: true, Command: "setBreakpoints", }, Body: dap.SetBreakpointsResponseBody{ Breakpoints: []dap.Breakpoint{ {Id: 1, Verified: true, Line: 42}, {Id: 2, Verified: true, Line: 87, Message: "condition applied"}, {Id: 3, Verified: false, Message: "line not reachable"}, }, }, } for _, bp := range resp.Body.Breakpoints { fmt.Printf("bp id=%d line=%d verified=%v msg=%q\n", bp.Id, bp.Line, bp.Verified, bp.Message) } // bp id=1 line=42 verified=true msg="" // bp id=2 line=87 verified=true msg="condition applied" // bp id=3 line=0 verified=false msg="line not reachable" _ = req } ``` -------------------------------- ### Extend DAP Protocol with Custom Messages Source: https://context7.com/google/go-dap/llms.txt Use `dap.NewCodec`, `Codec.RegisterRequest`, and `Codec.RegisterEvent` to add custom commands/events. This allows proprietary extensions while leveraging standard decoding. ```go package main import ( "bufio" "bytes" "encoding/json" "fmt" "github.com/google/go-dap" ) // Custom request/response types for a hypothetical "profiling" command type StartProfilingRequest struct { dap.Request Arguments StartProfilingArguments `json:"arguments"` } type StartProfilingArguments struct { OutputFile string `json:"outputFile"` Duration int `json:"duration"` // seconds } type StartProfilingResponse struct { dap.Response Body StartProfilingResponseBody `json:"body"` } type StartProfilingResponseBody struct { ProfileId string `json:"profileId"` } func (r *StartProfilingRequest) GetSeq() int { return r.Seq } func (r *StartProfilingResponse) GetSeq() int { return r.Seq } func main() { codec := dap.NewCodec() // Register custom "startProfiling" command err := codec.RegisterRequest( "startProfiling", func() dap.Message { return &StartProfilingRequest{} }, func() dap.Message { return &StartProfilingResponse{} }, ) if err != nil { panic(err) // already registered } // Build and encode a custom request req := &StartProfilingRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "request"}, Command: "startProfiling", }, Arguments: StartProfilingArguments{OutputFile: "/tmp/profile.out", Duration: 30}, } data, _ := json.Marshal(req) // Decode using the extended codec var buf bytes.Buffer dap.WriteBaseMessage(&buf, data) rawMsg, _ := dap.ReadBaseMessage(bufio.NewReader(&buf)) msg, err := codec.DecodeMessage(rawMsg) if err != nil { panic(err) } custom := msg.(*StartProfilingRequest) fmt.Printf("profiling to %s for %ds\n", custom.Arguments.OutputFile, custom.Arguments.Duration) // profiling to /tmp/profile.out for 30s } ``` -------------------------------- ### Scopes and Variables Inspection Source: https://context7.com/google/go-dap/llms.txt Demonstrates how to retrieve variable scopes for a given stack frame using `ScopesRequest` and then fetch the actual variables within a specific scope using `VariablesRequest`. ```APIDOC ## ScopesRequest / ScopesResponse ### Description Retrieves the variable scopes (local, global, etc.) for a stack frame. Each scope carries a `VariablesReference` handle used in `VariablesRequest` to retrieve the actual variables within that scope. ### Method Not applicable (Go SDK usage) ### Endpoint Not applicable (Go SDK usage) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `ScopesRequest` requires `FrameId` in its `Arguments`. ### Request Example ```go scopesReq := &dap.ScopesRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 9, Type: "request"}, Command: "scopes", }, Arguments: dap.ScopesArguments{FrameId: 1000}, } ``` ### Response #### Success Response `ScopesResponse` contains a slice of `dap.Scope` objects, each with `Name`, `VariablesReference`, and `Expensive` fields. #### Response Example ```go scopesResp := &dap.ScopesResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 9, Type: "response"}, RequestSeq: scopesReq.Seq, Success: true, Command: "scopes", }, Body: dap.ScopesResponseBody{ Scopes: []dap.Scope{ {Name: "Local", VariablesReference: 1000, Expensive: false}, {Name: "Global", VariablesReference: 1001, Expensive: true}, }, }, } ``` ## VariablesRequest / VariablesResponse ### Description Retrieves the actual variables within a given scope using a `VariablesReference` obtained from `ScopesResponse`. ### Method Not applicable (Go SDK usage) ### Endpoint Not applicable (Go SDK usage) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `VariablesRequest` requires `VariablesReference` in its `Arguments`. Optional arguments include `Filter`, `Start`, and `Count`. ### Request Example ```go varsReq := &dap.VariablesRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "request"}, Command: "variables", }, Arguments: dap.VariablesArguments{ VariablesReference: 1000, // local scope Filter: "named", Start: 0, Count: 100, }, } ``` ### Response #### Success Response `VariablesResponse` contains a slice of `dap.Variable` objects, each with `Name`, `Value`, `Type`, `EvaluateName`, and `VariablesReference` fields. #### Response Example ```go varsResp := &dap.VariablesResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "response"}, RequestSeq: varsReq.Seq, Success: true, Command: "variables", }, Body: dap.VariablesResponseBody{ Variables: []dap.Variable{ {Name: "i", Value: "42", Type: "int", EvaluateName: "i", VariablesReference: 0}, {Name: "msg", Value: "\"hello\"", Type: "string", EvaluateName: "msg", VariablesReference: 0}, }, }, } ``` ``` -------------------------------- ### Apache 2.0 Source Code Header Source: https://github.com/google/go-dap/blob/main/docs/contributing.md All source files must include this header, which contains copyright and license information. Ensure compliance with Apache License, Version 2.0. ```text Copyright 2020 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` -------------------------------- ### Base Message Structs and Interfaces Source: https://context7.com/google/go-dap/llms.txt Demonstrates the usage of base message structs like ProtocolMessage, Request, Response, and Event, along with their corresponding interfaces (Message, RequestMessage, ResponseMessage, EventMessage) for handling different types of DAP messages. ```APIDOC ## Base Message Structs and Interfaces All DAP messages embed `ProtocolMessage`, which carries `Seq` (sequence number) and `Type` (`"request"`, `"response"`, or `"event"`). The `Message` interface provides `GetSeq()`. `RequestMessage`, `ResponseMessage`, and `EventMessage` interfaces give typed access to the embedded base. ### Example Usage This Go code snippet shows how to create, populate, and process different types of DAP messages (Request, Response, Event) using the `go-dap` library. ```go package main import ( "fmt" "github.com/google/go-dap" ) func printMessageInfo(m dap.Message) { fmt.Printf("seq=%d ", m.GetSeq()) switch v := m.(type) { case dap.RequestMessage: fmt.Printf("type=request command=%s\n", v.GetRequest().Command) case dap.ResponseMessage: r := v.GetResponse() fmt.Printf("type=response command=%s success=%v\n", r.Command, r.Success) case dap.EventMessage: fmt.Printf("type=event event=%s\n", v.GetEvent().Event) } } func main() { // Request req := &dap.ThreadsRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 5, Type: "request"}, Command: "threads", }, } printMessageInfo(req) // seq=5 type=request command=threads // Response resp := &dap.ThreadsResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 6, Type: "response"}, RequestSeq: 5, Success: true, Command: "threads", }, Body: dap.ThreadsResponseBody{ Threads: []dap.Thread{{Id: 1, Name: "main"}, {Id: 2, Name: "worker"}}, }, } printMessageInfo(resp) // seq=6 type=response command=threads success=true // Event stopped := &dap.StoppedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 7, Type: "event"}, Event: "stopped", }, Body: dap.StoppedEventBody{ Reason: "breakpoint", ThreadId: 1, AllThreadsStopped: true, HitBreakpointIds: []int{42}, }, } printMessageInfo(stopped) // seq=7 type=event event=stopped } ``` ``` -------------------------------- ### Handle Protocol Errors and Wire Format Issues in Go Source: https://context7.com/google/go-dap/llms.txt This snippet demonstrates creating a protocol-level `ErrorResponse` and then processing various malformed inputs to trigger `BaseProtocolError` sentinel errors like `ErrHeaderDelimiterNotCrLfCrLf`, `ErrHeaderNotContentLength`, and `ErrHeaderContentTooLong`. ```go package main import ( "bufio" "errors" "fmt" "strings" "github.com/google/go-dap" ) func main() { // --- Protocol-level error response --- er := &dap.ErrorResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 5, Type: "response"}, RequestSeq: 4, Success: false, Command: "evaluate", Message: "notStopped", }, Body: dap.ErrorResponseBody{ Error: &dap.ErrorMessage{ Id: 1001, Format: "Cannot evaluate '{expr}' while the program is running", Variables: map[string]string{"expr": "someVar"}, ShowUser: true, }, }, } fmt.Printf("error id=%d format=%q\n", er.Body.Error.Id, er.Body.Error.Format) // --- Base protocol wire errors --- badInputs := []string{ "garbage\r\nabc", // bad delimiter "Cache-Control: no-cache\r\n\r\n", // wrong header "Content-Length: 5000000\r\n\r\n", // content too long } for _, input := range badInputs { _, err := dap.ReadBaseMessage(bufio.NewReader(strings.NewReader(input))) switch { case errors.Is(err, dap.ErrHeaderDelimiterNotCrLfCrLf): fmt.Println("bad delimiter") case errors.Is(err, dap.ErrHeaderNotContentLength): fmt.Println("bad header format") case errors.Is(err, dap.ErrHeaderContentTooLong): fmt.Println("content too long") default: fmt.Printf("other error: %v\n", err) } } // error id=1001 format="Cannot evaluate '{expr}' while the program is running" // bad delimiter // bad header format // content too long } ``` -------------------------------- ### Inspect Variables using Scopes and Variables Requests in Go Source: https://context7.com/google/go-dap/llms.txt Retrieve variable scopes for a given frame and then fetch the actual variables within a specific scope. Ensure the correct frame ID and variable reference are used. ```go package main import ( "fmt" "github.com/google/go-dap" ) func main() { // Step 1: get scopes for frame 1000 scopesReq := &dap.ScopesRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 9, Type: "request"}, Command: "scopes", }, Arguments: dap.ScopesArguments{FrameId: 1000}, } scopesResp := &dap.ScopesResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 9, Type: "response"}, RequestSeq: scopesReq.Seq, Success: true, Command: "scopes", }, Body: dap.ScopesResponseBody{ Scopes: []dap.Scope{ {Name: "Local", VariablesReference: 1000, Expensive: false}, {Name: "Global", VariablesReference: 1001, Expensive: true}, }, }, } // Step 2: get variables for the local scope for _, scope := range scopesResp.Body.Scopes { fmt.Printf("scope %q ref=%d expensive=%v\n", scope.Name, scope.VariablesReference, scope.Expensive) } varsReq := &dap.VariablesRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "request"}, Command: "variables", }, Arguments: dap.VariablesArguments{ VariablesReference: 1000, // local scope Filter: "named", Start: 0, Count: 100, }, } varsResp := &dap.VariablesResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "response"}, RequestSeq: varsReq.Seq, Success: true, Command: "variables", }, Body: dap.VariablesResponseBody{ Variables: []dap.Variable{ {Name: "i", Value: "42", Type: "int", EvaluateName: "i", VariablesReference: 0}, {Name: "msg", Value: `"hello"`, Type: "string", EvaluateName: "msg", VariablesReference: 0}, }, }, } for _, v := range varsResp.Body.Variables { fmt.Printf(" %s %s = %s\n", v.Type, v.Name, v.Value) } // scope "Local" ref=1000 expensive=false // scope "Global" ref=1001 expensive=true // int i = 42 // string msg = "hello" } ``` -------------------------------- ### ReadProtocolMessage Source: https://context7.com/google/go-dap/llms.txt Reads one base-protocol frame and immediately decodes it into the correct concrete Go type using DecodeProtocolMessage. ```APIDOC ## ReadProtocolMessage ### Description Reads one base-protocol frame and immediately decodes it into the correct concrete Go type using `DecodeProtocolMessage`. The returned value is a `dap.Message` interface and must be type-asserted to the specific message type. ### Method `dap.ReadProtocolMessage(r *bufio.Reader) (dap.Message, error)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go package main import ( "bufio" "fmt" "strings" "github.com/google/go-dap" ) func main() { wire := `Content-Length: 75` + "\r\n\r\n" + `{"seq":25,"type":"request","command":"cancel","arguments":{"requestId":24}}` msg, err := dap.ReadProtocolMessage(bufio.NewReader(strings.NewReader(wire))) if err != nil { panic(err) } switch m := msg.(type) { case *dap.CancelRequest: fmt.Printf("cancel request seq=%d, cancels seq=%d\n", m.Seq, m.Arguments.RequestId) case *dap.InitializeRequest: fmt.Printf("initialize from client %s\n", m.Arguments.ClientName) default: fmt.Printf("unhandled: %T\n", m) } // cancel request seq=25, cancels seq=24 } ``` ### Response #### Success Response (200) - **msg** (dap.Message) - The decoded DAP message. Must be type-asserted to the specific message type (e.g., `*dap.CancelRequest`). #### Response Example None ``` -------------------------------- ### StackTraceRequest / StackTraceResponse Source: https://context7.com/google/go-dap/llms.txt Requests the call stack frames for a given thread. Each StackFrame includes source file information, line/column position, and a frame name. ```APIDOC ## StackTraceRequest / StackTraceResponse ### Description Requests the call stack frames for a given thread. Each `StackFrame` includes source file information, line/column position, and a frame name. ### Method Not specified (typically part of a request-response cycle in DAP) ### Endpoint Not applicable (DAP is a protocol, not HTTP) ### Parameters #### Request Body (StackTraceRequest) - **ThreadId** (int) - Required - The ID of the thread for which to retrieve the stack trace. - **StartFrame** (int) - Optional - The starting frame index. Defaults to 0. - **Levels** (int) - Optional - The maximum number of frames to return. Defaults to a reasonable value. #### Response Body (StackTraceResponse) - **StackFrames** ([]dap.StackFrame) - Required - An array of stack frames. - **Id** (int) - Required - An identifier for the stack frame. - **Name** (string) - Required - The name of the function or scope this frame represents. - **Source** (dap.Source) - Optional - Source information for the frame. - **Name** (string) - Optional - The name of the source file. - **Path** (string) - Optional - The path to the source file. - **Line** (int) - Required - The line number in the source file. - **Column** (int) - Required - The column number in the source file. - **TotalFrames** (int) - Optional - The total number of frames available on the stack. ### Request Example ```go { "seq": 8, "type": "request", "command": "stackTrace", "arguments": { "threadId": 1, "startFrame": 0, "levels": 20 } } ``` ### Response Example ```go { "seq": 8, "type": "response", "requestSeq": 8, "success": true, "command": "stackTrace", "body": { "stackFrames": [ { "id": 1000, "name": "main.processRequest", "source": {"name": "server.go", "path": "/project/server.go"}, "line": 84, "column": 0 }, { "id": 1001, "name": "main.main", "source": {"name": "main.go", "path": "/project/main.go"}, "line": 12, "column": 0 } ], "totalFrames": 2 } } ``` ``` -------------------------------- ### Handle Execution State Events in Go DAP Source: https://context7.com/google/go-dap/llms.txt Process key events emitted by a debug adapter to notify the client about execution state changes. This includes handling stopped, continued, and terminated events. ```go package main import ( "bufio" "bytes" "fmt" "github.com/google/go-dap" ) func sendEvent(w *bytes.Buffer, msg dap.Message) { dap.WriteProtocolMessage(w, msg) } func main() { var buf bytes.Buffer // Adapter sends: stopped at breakpoint sendEvent(&buf, &dap.StoppedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "event"}, Event: "stopped", }, Body: dap.StoppedEventBody{ Reason: "breakpoint", ThreadId: 1, AllThreadsStopped: true, HitBreakpointIds: []int{42}, Description: "Paused on breakpoint", }, }) // Adapter sends: continued sendEvent(&buf, &dap.ContinuedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 2, Type: "event"}, Event: "continued", }, Body: dap.ContinuedEventBody{ThreadId: 1, AllThreadsContinued: true}, }) // Adapter sends: terminated sendEvent(&buf, &dap.TerminatedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 3, Type: "event"}, Event: "terminated", }, }) // Client reads all events reader := bufio.NewReader(&buf) for i := 0; i < 3; i++ { msg, err := dap.ReadProtocolMessage(reader) if err != nil { break } switch e := msg.(type) { case *dap.StoppedEvent: fmt.Printf("STOPPED reason=%s thread=%d bps=%v\n", e.Body.Reason, e.Body.ThreadId, e.Body.HitBreakpointIds) case *dap.ContinuedEvent: fmt.Printf("CONTINUED thread=%d all=%v\n", e.Body.ThreadId, e.Body.AllThreadsContinued) case *dap.TerminatedEvent: fmt.Println("TERMINATED") } } // STOPPED reason=breakpoint thread=1 bps=[42] // CONTINUED thread=1 all=true // TERMINATED } ``` -------------------------------- ### NewCodec, Codec.RegisterRequest, Codec.RegisterEvent Source: https://context7.com/google/go-dap/llms.txt Extends the codec with custom messages. `NewCodec` creates a codec with standard DAP messages. `RegisterRequest` and `RegisterEvent` allow adding custom command/event types for proprietary extensions. ```APIDOC ## NewCodec / Codec.RegisterRequest / Codec.RegisterEvent ### Description `NewCodec` creates a codec pre-populated with all standard DAP messages. `RegisterRequest` and `RegisterEvent` add custom command/event types beyond the specification, enabling proprietary adapter extensions while reusing all standard decoding infrastructure. ### Usage Example ```go package main import ( "bufio" "bytes" "encoding/json" "fmt" "github.com/google/go-dap" ) // Custom request/response types for a hypothetical "profiling" command type StartProfilingRequest struct { dap.Request Arguments StartProfilingArguments `json:"arguments"` } type StartProfilingArguments struct { OutputFile string `json:"outputFile"` Duration int `json:"duration"` // seconds } type StartProfilingResponse struct { dap.Response Body StartProfilingResponseBody `json:"body"` } type StartProfilingResponseBody struct { ProfileId string `json:"profileId"` } func (r *StartProfilingRequest) GetSeq() int { return r.Seq } func (r *StartProfilingResponse) GetSeq() int { return r.Seq } func main() { codec := dap.NewCodec() // Register custom "startProfiling" command err := codec.RegisterRequest( "startProfiling", func() dap.Message { return &StartProfilingRequest{} }, func() dap.Message { return &StartProfilingResponse{} }, ) if err != nil { panic(err) // already registered } // Build and encode a custom request req := &StartProfilingRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 10, Type: "request"}, Command: "startProfiling", }, Arguments: StartProfilingArguments{OutputFile: "/tmp/profile.out", Duration: 30}, } data, _ := json.Marshal(req) // Decode using the extended codec var buf bytes.Buffer dap.WriteBaseMessage(&buf, data) rawMsg, _ := dap.ReadBaseMessage(bufio.NewReader(&buf)) msg, err := codec.DecodeMessage(rawMsg) if err != nil { panic(err) } custom := msg.(*StartProfilingRequest) fmt.Printf("profiling to %s for %ds\n", custom.Arguments.OutputFile, custom.Arguments.Duration) // profiling to /tmp/profile.out for 30s } ``` ``` -------------------------------- ### SetBreakpointsRequest / SetBreakpointsResponse Source: https://context7.com/google/go-dap/llms.txt Sent by the client to register breakpoints in a source file. The adapter responds with a Breakpoint entry for each requested location indicating whether it was verified. ```APIDOC ## SetBreakpointsRequest / SetBreakpointsResponse ### Description Sent by the client to register breakpoints in a source file. The adapter responds with a `Breakpoint` entry for each requested location indicating whether it was verified. ### Method Not specified (typically part of a request-response cycle in DAP) ### Endpoint Not applicable (DAP is a protocol, not HTTP) ### Parameters #### Request Body (SetBreakpointsRequest) - **Source** (dap.Source) - Required - Information about the source file. - **Name** (string) - Optional - The name of the source file. - **Path** (string) - Optional - The path to the source file. - **Breakpoints** ([]dap.SourceBreakpoint) - Required - An array of breakpoints to set. - **Line** (int) - Required - The line number for the breakpoint. - **Column** (int) - Optional - The column number for the breakpoint. - **Condition** (string) - Optional - An expression that must be true for the breakpoint to be hit. - **HitCondition** (string) - Optional - A condition that must be met for the breakpoint to be hit (e.g., a hit count). - **LogMessage** (string) - Optional - A message to log when the breakpoint is hit. #### Response Body (SetBreakpointsResponse) - **Breakpoints** ([]dap.Breakpoint) - Required - An array of breakpoints set by the adapter. - **Id** (int) - Required - The unique identifier for the breakpoint. - **Verified** (bool) - Required - Indicates whether the breakpoint was successfully verified. - **Line** (int) - Optional - The verified line number of the breakpoint. - **Column** (int) - Optional - The verified column number of the breakpoint. - **Message** (string) - Optional - An informational message about the breakpoint. ### Request Example ```go { "seq": 3, "type": "request", "command": "setBreakpoints", "arguments": { "source": { "name": "main.go", "path": "/home/user/project/main.go" }, "breakpoints": [ {"line": 42}, {"line": 87, "condition": "x > 10"}, {"line": 120, "hitCondition": "5", "logMessage": "hit line 120"} ] } } ``` ### Response Example ```go { "seq": 3, "type": "response", "requestSeq": 3, "success": true, "command": "setBreakpoints", "body": { "breakpoints": [ {"id": 1, "verified": true, "line": 42}, {"id": 2, "verified": true, "line": 87, "message": "condition applied"}, {"id": 3, "verified": false, "message": "line not reachable"} ] } } ``` ``` -------------------------------- ### WriteProtocolMessage Source: https://context7.com/google/go-dap/llms.txt Accepts any dap.Message (request, response, or event struct), JSON-marshals it, and writes it as a base-protocol frame in one call. ```APIDOC ## WriteProtocolMessage ### Description Accepts any `dap.Message` (request, response, or event struct), JSON-marshals it, and writes it as a base-protocol frame in one call. ### Method `dap.WriteProtocolMessage(w io.Writer, msg dap.Message) error` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go package main import ( "bufio" "bytes" "fmt" "github.com/google/go-dap" ) func main() { req := &dap.CancelRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 25, Type: "request"}, Command: "cancel", }, Arguments: &dap.CancelArguments{RequestId: 24}, } var buf bytes.Buffer if err := dap.WriteProtocolMessage(&buf, req); err != nil { panic(err) } // Content-Length: 75\r\n\r\n{"seq":25,"type":"request","command":"cancel","arguments":{"requestId":24}} fmt.Println(buf.String()) // Round-trip: read back msg, err := dap.ReadProtocolMessage(bufio.NewReader(&buf)) if err != nil { panic(err) } cancel := msg.(*dap.CancelRequest) fmt.Printf("Seq=%d CancelledReqId=%d\n", cancel.Seq, cancel.Arguments.RequestId) // Seq=25 CancelledReqId=24 } ``` ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Write DAP Base Protocol Message Source: https://context7.com/google/go-dap/llms.txt Formats raw bytes with the Content-Length header and writes the framed message to an io.Writer. ```go package main import ( "bytes" "fmt" "github.com/google/go-dap" ) func main() { content := []byte(`{"seq":1,"type":"request","command":"initialize"}`) var buf bytes.Buffer if err := dap.WriteBaseMessage(&buf, content); err != nil { panic(err) } // Output: "Content-Length: 48\r\n\r\n{\"seq\":1,\"type\":\"request\",\"command\":\"initialize\"}" fmt.Printf("%q\n", buf.String()) } ``` -------------------------------- ### Execution State Events Source: https://context7.com/google/go-dap/llms.txt Details the key events emitted by the debug adapter to notify the client of execution state changes, including stopped, continued, and terminated events. ```APIDOC ## StoppedEvent ### Description Fires when the debuggee halts due to a breakpoint, step, or exception. ### Event Type `stopped` ### Event Body Fields - **Reason** (string) - The cause of the stop (e.g., "breakpoint", "step", "exception"). - **ThreadId** (int) - The ID of the thread that stopped. - **AllThreadsStopped** (bool) - Indicates if all threads have stopped. - **HitBreakpointIds** ([]int) - An optional list of breakpoint IDs that were hit. - **Description** (string) - A human-readable description of the stop reason. ### Example ```go &dap.StoppedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 1, Type: "event"}, Event: "stopped", }, Body: dap.StoppedEventBody{ Reason: "breakpoint", ThreadId: 1, AllThreadsStopped: true, HitBreakpointIds: []int{42}, Description: "Paused on breakpoint", }, } ``` ## ContinuedEvent ### Description Fires when execution resumes in the debuggee. ### Event Type `continued` ### Event Body Fields - **ThreadId** (int) - The ID of the thread that continued. - **AllThreadsContinued** (bool) - Indicates if all threads have continued. ### Example ```go &dap.ContinuedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 2, Type: "event"}, Event: "continued", }, Body: dap.ContinuedEventBody{ThreadId: 1, AllThreadsContinued: true}, } ``` ## TerminatedEvent ### Description Fires when the debugging session ends. ### Event Type `terminated` ### Example ```go &dap.TerminatedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 3, Type: "event"}, Event: "terminated", }, } ``` ``` -------------------------------- ### Print DAP Message Information Source: https://context7.com/google/go-dap/llms.txt This function inspects a DAP message and prints its sequence number, type, and relevant command or event details. It handles RequestMessage, ResponseMessage, and EventMessage types. ```go package main import ( "fmt" "github.com/google/go-dap" ) func printMessageInfo(m dap.Message) { fmt.Printf("seq=%d ", m.GetSeq()) switch v := m.(type) { case dap.RequestMessage: fmt.Printf("type=request command=%s\n", v.GetRequest().Command) case dap.ResponseMessage: r := v.GetResponse() fmt.Printf("type=response command=%s success=%v\n", r.Command, r.Success) case dap.EventMessage: fmt.Printf("type=event event=%s\n", v.GetEvent().Event) } } func main() { // Request req := &dap.ThreadsRequest{ Request: dap.Request{ ProtocolMessage: dap.ProtocolMessage{Seq: 5, Type: "request"}, Command: "threads", }, } printMessageInfo(req) // seq=5 type=request command=threads // Response resp := &dap.ThreadsResponse{ Response: dap.Response{ ProtocolMessage: dap.ProtocolMessage{Seq: 6, Type: "response"}, RequestSeq: 5, Success: true, Command: "threads", }, Body: dap.ThreadsResponseBody{ Threads: []dap.Thread{{Id: 1, Name: "main"}, {Id: 2, Name: "worker"}}, }, } printMessageInfo(resp) // seq=6 type=response command=threads success=true // Event stopped := &dap.StoppedEvent{ Event: dap.Event{ ProtocolMessage: dap.ProtocolMessage{Seq: 7, Type: "event"}, Event: "stopped", }, Body: dap.StoppedEventBody{ Reason: "breakpoint", ThreadId: 1, AllThreadsStopped: true, HitBreakpointIds: []int{42}, }, } printMessageInfo(stopped) // seq=7 type=event event=stopped } ``` -------------------------------- ### WriteBaseMessage Source: https://context7.com/google/go-dap/llms.txt Formats raw bytes with the Content-Length header required by the DAP base protocol and writes the entire framed message to any io.Writer. ```APIDOC ## WriteBaseMessage ### Description Formats raw bytes with the `Content-Length: N\r\n\r\n` header required by the DAP base protocol and writes the entire framed message to any `io.Writer`. ### Method `dap.WriteBaseMessage(w io.Writer, content []byte) error` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go package main import ( "bytes" "fmt" "github.com/google/go-dap" ) func main() { content := []byte(`{"seq":1,"type":"request","command":"initialize"}`) var buf bytes.Buffer if err := dap.WriteBaseMessage(&buf, content); err != nil { panic(err) } // Output: "Content-Length: 48\r\n\r\n{\"seq\":1,\"type\":\"request\",\"command\":\"initialize\"}" fmt.Printf("%q\n", buf.String()) } ``` ### Response #### Success Response (200) None #### Response Example None ```