*: run go1.19 'go fmt' on everything and fix problems (#3031)

Go 1.19 also formats doc comments according to the new godoc syntax.
Some of our comments, especially unexported symbols did not conform to
the godoc syntax and therefore are mangled by 'go fmt'.

This PR runs 'go fmt' from go1.19 on everything and manually fixes the
problems.

See also:
	https://github.com/golang/proposal/blob/master/design/51082-godocfmt.md
This commit is contained in:
Alessandro Arzilli 2022-06-17 19:08:11 +02:00 committed by GitHub
parent 2827145f1e
commit c412dcdc4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 242 additions and 256 deletions

@ -1,3 +1,4 @@
//go:build ignore
// +build ignore // +build ignore
package main package main

@ -1,3 +1,4 @@
//go:build ignore
// +build ignore // +build ignore
package main package main

@ -12,7 +12,7 @@ import (
// SplitQuotedFields is like strings.Fields but ignores spaces inside areas surrounded // SplitQuotedFields is like strings.Fields but ignores spaces inside areas surrounded
// by the specified quote character. // by the specified quote character.
// To specify a single quote use backslash to escape it: '\'' // To specify a single quote use backslash to escape it: \'
func SplitQuotedFields(in string, quote rune) []string { func SplitQuotedFields(in string, quote rune) []string {
type stateEnum int type stateEnum int
const ( const (

@ -193,7 +193,9 @@ func max(a, b uint64) uint64 {
} }
// fuseRanges fuses rngs2 into rngs1, it's the equivalent of // fuseRanges fuses rngs2 into rngs1, it's the equivalent of
// normalizeRanges(append(rngs1, rngs2)) //
// normalizeRanges(append(rngs1, rngs2))
//
// but more efficient. // but more efficient.
func fuseRanges(rngs1, rngs2 [][2]uint64) [][2]uint64 { func fuseRanges(rngs1, rngs2 [][2]uint64) [][2]uint64 {
if rangesContains(rngs1, rngs2) { if rangesContains(rngs1, rngs2) {

@ -535,7 +535,7 @@ func (t *UnsupportedType) stringIntl(recCheck) string {
func (t *UnsupportedType) String() string { return t.stringIntl(nil) } func (t *UnsupportedType) String() string { return t.stringIntl(nil) }
// ReadType reads the type at off in the DWARF ``info'' section. // ReadType reads the type at off in the DWARF “info” section.
func ReadType(d *dwarf.Data, index int, off dwarf.Offset, typeCache map[dwarf.Offset]Type) (Type, error) { func ReadType(d *dwarf.Data, index int, off dwarf.Offset, typeCache map[dwarf.Offset]Type) (Type, error) {
typ, err := readType(d, "info", d.Reader(), off, typeCache, nil) typ, err := readType(d, "info", d.Reader(), off, typeCache, nil)
if typ != nil { if typ != nil {

@ -3,13 +3,14 @@
// //
// Location spec examples: // Location spec examples:
// //
// locStr ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address> // locStr ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
// * <filename> can be the full path of a file or just a suffix //
// * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name> // * <filename> can be the full path of a file or just a suffix
// <function> must be unambiguous // * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name>
// * /<regex>/ will return a location for each function matched by regex // <function> must be unambiguous
// * +<offset> returns a location for the line that is <offset> lines after the current line // * /<regex>/ will return a location for each function matched by regex
// * -<offset> returns a location for the line that is <offset> lines before the current line // * +<offset> returns a location for the line that is <offset> lines after the current line
// * <line> returns a location for a line in the current file // * -<offset> returns a location for the line that is <offset> lines before the current line
// * *<address> returns the location corresponding to the specified address // * <line> returns a location for a line in the current file
// * *<address> returns the location corresponding to the specified address
package locspec package locspec

@ -1337,7 +1337,7 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
return nil return nil
} }
// _STT_FUNC is a code object, see /usr/include/elf.h for a full definition. // _STT_FUNC is a code object, see /usr/include/elf.h for a full definition.
const _STT_FUNC = 2 const _STT_FUNC = 2
func (bi *BinaryInfo) loadSymbolName(image *Image, file *elf.File, wg *sync.WaitGroup) { func (bi *BinaryInfo) loadSymbolName(image *Image, file *elf.File, wg *sync.WaitGroup) {
@ -1633,13 +1633,15 @@ func (bi *BinaryInfo) parseDebugFrameMacho(image *Image, exe *macho.File, debugI
bi.parseDebugFrameGeneral(image, debugFrameBytes, "__debug_frame", debugFrameErr, ehFrameBytes, ehFrameAddr, "__eh_frame", frame.DwarfEndian(debugInfoBytes)) bi.parseDebugFrameGeneral(image, debugFrameBytes, "__debug_frame", debugFrameErr, ehFrameBytes, ehFrameAddr, "__eh_frame", frame.DwarfEndian(debugInfoBytes))
} }
// macOSDebugFrameBugWorkaround applies a workaround for: // macOSDebugFrameBugWorkaround applies a workaround for [golang/go#25841]
// https://github.com/golang/go/issues/25841 //
// It finds the Go function with the lowest entry point and the first // It finds the Go function with the lowest entry point and the first
// debug_frame FDE, calculates the difference between the start of the // debug_frame FDE, calculates the difference between the start of the
// function and the start of the FDE and sums it to all debug_frame FDEs. // function and the start of the FDE and sums it to all debug_frame FDEs.
// A number of additional checks are performed to make sure we don't ruin // A number of additional checks are performed to make sure we don't ruin
// executables unaffected by this bug. // executables unaffected by this bug.
//
// [golang/go#25841]: https://github.com/golang/go/issues/25841
func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() { func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() {
//TODO: log extensively because of bugs in the field //TODO: log extensively because of bugs in the field
if bi.GOOS != "darwin" || bi.Arch.Name != "arm64" { if bi.GOOS != "darwin" || bi.Arch.Name != "arm64" {
@ -1967,9 +1969,9 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugInfoBytes, debugLineB
// LookupGenericFunc returns a map that allows searching for instantiations of generic function by specificying a function name without type parameters. // LookupGenericFunc returns a map that allows searching for instantiations of generic function by specificying a function name without type parameters.
// For example the key "pkg.(*Receiver).Amethod" will find all instantiations of Amethod: // For example the key "pkg.(*Receiver).Amethod" will find all instantiations of Amethod:
// - pkg.(*Receiver[.shape.int]).Amethod" // - pkg.(*Receiver[.shape.int]).Amethod
// - pkg.(*Receiver[.shape.*uint8]).Amethod" // - pkg.(*Receiver[.shape.*uint8]).Amethod
// - etc. // - etc.
func (bi *BinaryInfo) LookupGenericFunc() map[string][]*Function { func (bi *BinaryInfo) LookupGenericFunc() map[string][]*Function {
if bi.lookupGenericFunc == nil { if bi.lookupGenericFunc == nil {
bi.lookupGenericFunc = make(map[string][]*Function) bi.lookupGenericFunc = make(map[string][]*Function)

@ -21,10 +21,12 @@ var ErrNoThreads = errors.New("no threads found in core file")
// 0x0000000000400000 0x000000000044f000 0x0000000000000000 // 0x0000000000400000 0x000000000044f000 0x0000000000000000
// but then it's partially overwritten with an RW mapping whose data is stored // but then it's partially overwritten with an RW mapping whose data is stored
// in the core file: // in the core file:
// Type Offset VirtAddr PhysAddr //
// FileSiz MemSiz Flags Align // Type Offset VirtAddr PhysAddr
// LOAD 0x0000000000004000 0x000000000049a000 0x0000000000000000 // FileSiz MemSiz Flags Align
// 0x0000000000002000 0x0000000000002000 RW 1000 // LOAD 0x0000000000004000 0x000000000049a000 0x0000000000000000
// 0x0000000000002000 0x0000000000002000 RW 1000
//
// This can be represented in a SplicedMemory by adding the original region, // This can be represented in a SplicedMemory by adding the original region,
// then putting the RW mapping on top of it. // then putting the RW mapping on top of it.
type splicedMemory struct { type splicedMemory struct {

@ -2,8 +2,8 @@
// the process we are debugging. // the process we are debugging.
// //
// proc implements all core functionality including: // proc implements all core functionality including:
// * creating / attaching to a process
// * process manipulation (step, next, continue, halt)
// * methods to explore the memory of the process
// //
// - creating / attaching to a process
// - process manipulation (step, next, continue, halt)
// - methods to explore the memory of the process
package proc package proc

@ -338,17 +338,17 @@ func afterLastArgAddr(vars []*Variable) uint64 {
} }
// setValue writes the value of srcv to dstv. // setValue writes the value of srcv to dstv.
// * If srcv is a numerical literal constant and srcv is of a compatible type // - If srcv is a numerical literal constant and srcv is of a compatible type
// the necessary type conversion is performed. // the necessary type conversion is performed.
// * If srcv is nil and dstv is of a nil'able type then dstv is nilled. // - If srcv is nil and dstv is of a nil'able type then dstv is nilled.
// * If srcv is the empty string and dstv is a string then dstv is set to the // - If srcv is the empty string and dstv is a string then dstv is set to the
// empty string. // empty string.
// * If dstv is an "interface {}" and srcv is either an interface (possibly // - If dstv is an "interface {}" and srcv is either an interface (possibly
// non-empty) or a pointer shaped type (map, channel, pointer or struct // non-empty) or a pointer shaped type (map, channel, pointer or struct
// containing a single pointer field) the type conversion to "interface {}" // containing a single pointer field) the type conversion to "interface {}"
// is performed. // is performed.
// * If srcv and dstv have the same type and are both addressable then the // - If srcv and dstv have the same type and are both addressable then the
// contents of srcv are copied byte-by-byte into dstv // contents of srcv are copied byte-by-byte into dstv
func (scope *EvalScope) setValue(dstv, srcv *Variable, srcExpr string) error { func (scope *EvalScope) setValue(dstv, srcv *Variable, srcExpr string) error {
srcv.loadValue(loadSingleValue) srcv.loadValue(loadSingleValue)

@ -2,7 +2,6 @@ package gdbserial
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -12,8 +11,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
"unicode"
"github.com/go-delve/delve/pkg/config"
"github.com/go-delve/delve/pkg/proc" "github.com/go-delve/delve/pkg/proc"
) )
@ -248,7 +247,7 @@ func (err *ErrMalformedRRGdbCommand) Error() string {
func rrParseGdbCommand(line string) rrInit { func rrParseGdbCommand(line string) rrInit {
port := "" port := ""
fields := splitQuotedFields(line) fields := config.SplitQuotedFields(line, '\'')
for i := 0; i < len(fields); i++ { for i := 0; i < len(fields); i++ {
switch fields[i] { switch fields[i] {
case "-ex": case "-ex":
@ -279,63 +278,6 @@ func rrParseGdbCommand(line string) rrInit {
return rrInit{port: port, exe: exe} return rrInit{port: port, exe: exe}
} }
// Like strings.Fields but ignores spaces inside areas surrounded
// by single quotes.
// To specify a single quote use backslash to escape it: '\''
func splitQuotedFields(in string) []string {
type stateEnum int
const (
inSpace stateEnum = iota
inField
inQuote
inQuoteEscaped
)
state := inSpace
r := []string{}
var buf bytes.Buffer
for _, ch := range in {
switch state {
case inSpace:
if ch == '\'' {
state = inQuote
} else if !unicode.IsSpace(ch) {
buf.WriteRune(ch)
state = inField
}
case inField:
if ch == '\'' {
state = inQuote
} else if unicode.IsSpace(ch) {
r = append(r, buf.String())
buf.Reset()
} else {
buf.WriteRune(ch)
}
case inQuote:
if ch == '\'' {
state = inField
} else if ch == '\\' {
state = inQuoteEscaped
} else {
buf.WriteRune(ch)
}
case inQuoteEscaped:
buf.WriteRune(ch)
state = inQuote
}
}
if buf.Len() != 0 {
r = append(r, buf.String())
}
return r
}
// RecordAndReplay acts like calling Record and then Replay. // RecordAndReplay acts like calling Record and then Replay.
func RecordAndReplay(cmd []string, wd string, quiet bool, debugInfoDirs []string, redirects [3]string) (*proc.Target, string, error) { func RecordAndReplay(cmd []string, wd string, quiet bool, debugInfoDirs []string, redirects [3]string) (*proc.Target, string, error) {
tracedir, err := Record(cmd, wd, quiet, redirects) tracedir, err := Record(cmd, wd, quiet, redirects)

@ -47,12 +47,13 @@ func ptraceGetRegset(tid int) (regset amd64util.AMD64Xstate, err error) {
// ptraceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread. // ptraceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread.
// See http://man7.org/linux/man-pages/man2/ptrace.2.html for detail about PTRACE_GET_THREAD_AREA. // See http://man7.org/linux/man-pages/man2/ptrace.2.html for detail about PTRACE_GET_THREAD_AREA.
// struct user_desc at https://golang.org/src/runtime/sys_linux_386.s // struct user_desc at https://golang.org/src/runtime/sys_linux_386.s
// type UserDesc struct { //
// EntryNumber uint32 // type UserDesc struct {
// BaseAddr uint32 // EntryNumber uint32
// Limit uint32 // BaseAddr uint32
// Flag uint32 // Limit uint32
// } // Flag uint32
// }
func ptraceGetTls(gs int32, tid int) (uint32, error) { func ptraceGetTls(gs int32, tid int) (uint32, error) {
ud := [4]uint32{} ud := [4]uint32{}

@ -65,9 +65,10 @@ func (wpstate *watchpointState) set(idx uint8, addr, ctrl uint64) {
// The format of this register set is described by user_hwdebug_state in // The format of this register set is described by user_hwdebug_state in
// arch/arm64/include/uapi/asm/ptrace.h. // arch/arm64/include/uapi/asm/ptrace.h.
// It consists of one 64bit word containing: // It consists of one 64bit word containing:
// * 1byte number of watchpoints // - 1byte number of watchpoints
// * 1byte debug architecture version (the 4 least significant bits of ID_AA64DFR0_EL1) // - 1byte debug architecture version (the 4 least significant bits of ID_AA64DFR0_EL1)
// * 6bytes padding // - 6bytes padding
//
// Followed by 2 64bit words for each watchpoint, up to a maximum of 16 // Followed by 2 64bit words for each watchpoint, up to a maximum of 16
// watchpoints. The first word contains the address at which the watchpoint // watchpoints. The first word contains the address at which the watchpoint
// is set (DBGWVRn_EL1), the second word is the control register for the // is set (DBGWVRn_EL1), the second word is the control register for the

@ -42,26 +42,26 @@ func TestScopeWithEscapedVariable(t *testing.T) {
} }
// TestScope will: // TestScope will:
// - run _fixtures/scopetest.go // - run _fixtures/scopetest.go
// - set a breakpoint on all lines containing a comment // - set a breakpoint on all lines containing a comment
// - continue until the program ends // - continue until the program ends
// - every time a breakpoint is hit it will check that // - every time a breakpoint is hit it will check that
// scope.FunctionArguments+scope.LocalVariables and scope.EvalExpression // scope.FunctionArguments+scope.LocalVariables and scope.EvalExpression
// return what the corresponding comment describes they should return and // return what the corresponding comment describes they should return and
// removes the breakpoint. // removes the breakpoint.
// //
// Each comment is a comma separated list of variable declarations, with // Each comment is a comma separated list of variable declarations, with
// each variable declaration having the following format: // each variable declaration having the following format:
// //
// name type = initialvalue // name type = initialvalue
// //
// the = and the initial value are optional and can only be specified if the // the = and the initial value are optional and can only be specified if the
// type is an integer type, float32, float64 or bool. // type is an integer type, float32, float64 or bool.
// //
// If multiple variables with the same name are specified: // If multiple variables with the same name are specified:
// 1. LocalVariables+FunctionArguments should return them in the same order and // 1. LocalVariables+FunctionArguments should return them in the same order and
// every variable except the last one should be marked as shadowed // every variable except the last one should be marked as shadowed
// 2. EvalExpression should return the last one. // 2. EvalExpression should return the last one.
func TestScope(t *testing.T) { func TestScope(t *testing.T) {
if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) { if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}) {
return return

@ -221,9 +221,9 @@ func conditionErrors(threads []Thread) error {
} }
// pick a new dbp.currentThread, with the following priority: // pick a new dbp.currentThread, with the following priority:
// - a thread with an active stepping breakpoint // - a thread with an active stepping breakpoint
// - a thread with an active breakpoint, prioritizing trapthread // - a thread with an active breakpoint, prioritizing trapthread
// - trapthread // - trapthread
func pickCurrentThread(dbp *Target, trapthread Thread, threads []Thread) error { func pickCurrentThread(dbp *Target, trapthread Thread, threads []Thread) error {
for _, th := range threads { for _, th := range threads {
if bp := th.Breakpoint(); bp.Active && bp.Stepping { if bp := th.Breakpoint(); bp.Active && bp.Stepping {
@ -445,14 +445,14 @@ func (dbp *Target) StepInstruction() (err error) {
// once the CALL is reached. // once the CALL is reached.
// //
// Regardless of stepInto the following breakpoints will be set: // Regardless of stepInto the following breakpoints will be set:
// - a breakpoint on the first deferred function with NextDeferBreakpoint // - a breakpoint on the first deferred function with NextDeferBreakpoint
// kind, the list of all the addresses to deferreturn calls in this function // kind, the list of all the addresses to deferreturn calls in this function
// and condition checking that we remain on the same goroutine // and condition checking that we remain on the same goroutine
// - a breakpoint on each line of the function, with a condition checking // - a breakpoint on each line of the function, with a condition checking
// that we stay on the same stack frame and goroutine. // that we stay on the same stack frame and goroutine.
// - a breakpoint on the return address of the function, with a condition // - a breakpoint on the return address of the function, with a condition
// checking that we move to the previous stack frame and stay on the same // checking that we move to the previous stack frame and stay on the same
// goroutine. // goroutine.
// //
// The breakpoint on the return address is *not* set if the current frame is // The breakpoint on the return address is *not* set if the current frame is
// an inlined call. For inlined calls topframe.Current.Fn is the function // an inlined call. For inlined calls topframe.Current.Fn is the function
@ -957,12 +957,13 @@ func findCallInstrForRet(p Process, mem MemoryReadWriter, ret uint64, fn *Functi
} }
// stepOutReverse sets a breakpoint on the CALL instruction that created the current frame, this is either: // stepOutReverse sets a breakpoint on the CALL instruction that created the current frame, this is either:
// - the CALL instruction immediately preceding the return address of the // - the CALL instruction immediately preceding the return address of the
// current frame // current frame
// - the return address of the current frame if the current frame was // - the return address of the current frame if the current frame was
// created by a runtime.deferreturn run // created by a runtime.deferreturn run
// - the return address of the runtime.gopanic frame if the current frame // - the return address of the runtime.gopanic frame if the current frame
// was created by a panic // was created by a panic
//
// This function is used to implement reversed StepOut // This function is used to implement reversed StepOut
func stepOutReverse(p *Target, topframe, retframe Stackframe, sameGCond ast.Expr) error { func stepOutReverse(p *Target, topframe, retframe Stackframe, sameGCond ast.Expr) error {
curthread := p.CurrentThread() curthread := p.CurrentThread()

@ -263,20 +263,20 @@ func AllowRecording(t testing.TB) {
// MustHaveRecordingAllowed skips this test if recording is not allowed // MustHaveRecordingAllowed skips this test if recording is not allowed
// //
// Not all the tests can be run with a recording: // Not all the tests can be run with a recording:
// - some fixtures never terminate independently (loopprog, // - some fixtures never terminate independently (loopprog,
// testnextnethttp) and can not be recorded // testnextnethttp) and can not be recorded
// - some tests assume they can interact with the target process (for // - some tests assume they can interact with the target process (for
// example TestIssue419, or anything changing the value of a variable), // example TestIssue419, or anything changing the value of a variable),
// which we can't do on with a recording // which we can't do on with a recording
// - some tests assume that the Pid returned by the process is valid, but // - some tests assume that the Pid returned by the process is valid, but
// it won't be at replay time // it won't be at replay time
// - some tests will start the fixture but not never execute a single // - some tests will start the fixture but not never execute a single
// instruction, for some reason rr doesn't like this and will print an // instruction, for some reason rr doesn't like this and will print an
// error if it happens // error if it happens
// - many tests will assume that we can return from a runtime.Breakpoint, // - many tests will assume that we can return from a runtime.Breakpoint,
// with a recording this is not possible because when the fixture ran it // with a recording this is not possible because when the fixture ran it
// wasn't attached to a debugger and in those circumstances a // wasn't attached to a debugger and in those circumstances a
// runtime.Breakpoint leads directly to a crash // runtime.Breakpoint leads directly to a crash
// //
// Some of the tests using runtime.Breakpoint (anything involving variable // Some of the tests using runtime.Breakpoint (anything involving variable
// evaluation and TestWorkDir) have been adapted to work with a recording. // evaluation and TestWorkDir) have been adapted to work with a recording.

@ -112,13 +112,13 @@ func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off d
// runtimeTypeToDIE returns the DIE corresponding to the runtime._type. // runtimeTypeToDIE returns the DIE corresponding to the runtime._type.
// This is done in three different ways depending on the version of go. // This is done in three different ways depending on the version of go.
// * Before go1.7 the type name is retrieved directly from the runtime._type // - Before go1.7 the type name is retrieved directly from the runtime._type
// and looked up in debug_info // and looked up in debug_info
// * After go1.7 the runtime._type struct is read recursively to reconstruct // - After go1.7 the runtime._type struct is read recursively to reconstruct
// the name of the type, and then the type's name is used to look up // the name of the type, and then the type's name is used to look up
// debug_info // debug_info
// * After go1.11 the runtimeTypeToDIE map is used to look up the address of // - After go1.11 the runtimeTypeToDIE map is used to look up the address of
// the type and map it drectly to a DIE. // the type and map it drectly to a DIE.
func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) { func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) {
bi := _type.bi bi := _type.bi

@ -1705,10 +1705,11 @@ func (s *Session) onThreadsRequest(request *dap.ThreadsRequest) {
// onAttachRequest handles 'attach' request. // onAttachRequest handles 'attach' request.
// This is a mandatory request to support. // This is a mandatory request to support.
// Attach debug sessions support the following modes: // Attach debug sessions support the following modes:
// -- [DEFAULT] "local" -- attaches debugger to a local running process //
// Required args: processID // - [DEFAULT] "local" -- attaches debugger to a local running process.
// -- "remote" - attaches client to a debugger already attached to a process // Required args: processID
// Required args: none (host/port are used externally to connect) // - "remote" -- attaches client to a debugger already attached to a process.
// Required args: none (host/port are used externally to connect)
func (s *Session) onAttachRequest(request *dap.AttachRequest) { func (s *Session) onAttachRequest(request *dap.AttachRequest) {
var args AttachConfig = defaultAttachConfig // narrow copy for initializing non-zero default values var args AttachConfig = defaultAttachConfig // narrow copy for initializing non-zero default values
if err := unmarshalLaunchAttachArgs(request.Arguments, &args); err != nil { if err := unmarshalLaunchAttachArgs(request.Arguments, &args); err != nil {
@ -2591,12 +2592,15 @@ func (s *Session) convertVariableWithOpts(v *proc.Variable, qualifiedNameOrExpr
// onEvaluateRequest handles 'evalute' requests. // onEvaluateRequest handles 'evalute' requests.
// This is a mandatory request to support. // This is a mandatory request to support.
// Support the following expressions: // Support the following expressions:
// -- {expression} - evaluates the expression and returns the result as a variable //
// -- call {function} - injects a function call and returns the result as a variable // - {expression} - evaluates the expression and returns the result as a variable
// -- config {expression} - updates configuration parameters // - call {function} - injects a function call and returns the result as a variable
// - config {expression} - updates configuration parameters
//
// TODO(polina): users have complained about having to click to expand multi-level // TODO(polina): users have complained about having to click to expand multi-level
// variables, so consider also adding the following: // variables, so consider also adding the following:
// -- print {expression} - return the result as a string like from dlv cli //
// - print {expression} - return the result as a string like from dlv cli
func (s *Session) onEvaluateRequest(request *dap.EvaluateRequest) { func (s *Session) onEvaluateRequest(request *dap.EvaluateRequest) {
showErrorToUser := request.Arguments.Context != "watch" && request.Arguments.Context != "repl" && request.Arguments.Context != "hover" showErrorToUser := request.Arguments.Context != "watch" && request.Arguments.Context != "repl" && request.Arguments.Context != "hover"
if s.debugger == nil { if s.debugger == nil {
@ -3301,7 +3305,8 @@ func (s *Session) getExprString(expr string, goroutineID, frame int) (string, er
} }
// sendErrorResponseWithOpts offers configuration options. // sendErrorResponseWithOpts offers configuration options.
// showUser - if true, the error will be shown to the user (e.g. via a visible pop-up) //
// showUser - if true, the error will be shown to the user (e.g. via a visible pop-up)
func (s *Session) sendErrorResponseWithOpts(request dap.Request, id int, summary, details string, showUser bool) { func (s *Session) sendErrorResponseWithOpts(request dap.Request, id int, summary, details string, showUser bool) {
er := &dap.ErrorResponse{} er := &dap.ErrorResponse{}
er.Type = "response" er.Type = "response"
@ -3706,7 +3711,8 @@ type logMessage struct {
} }
// parseLogPoint parses a log message according to the DAP spec: // parseLogPoint parses a log message according to the DAP spec:
// "Expressions within {} are interpolated." //
// "Expressions within {} are interpolated."
func parseLogPoint(msg string) (bool, *logMessage, error) { func parseLogPoint(msg string) (bool, *logMessage, error) {
// Note: All braces *must* come in pairs, even those within an // Note: All braces *must* come in pairs, even those within an
// expression to be interpolated. // expression to be interpolated.

@ -321,37 +321,39 @@ func TestForceStopWhileStopping(t *testing.T) {
// TestLaunchStopOnEntry emulates the message exchange that can be observed with // TestLaunchStopOnEntry emulates the message exchange that can be observed with
// VS Code for the most basic launch debug session with "stopOnEntry" enabled: // VS Code for the most basic launch debug session with "stopOnEntry" enabled:
// - User selects "Start Debugging": 1 >> initialize //
// : 1 << initialize // User selects "Start Debugging": 1 >> initialize
// : 2 >> launch // : 1 << initialize
// : << initialized event // : 2 >> launch
// : 2 << launch // : << initialized event
// : 3 >> setBreakpoints (empty) // : 2 << launch
// : 3 << setBreakpoints // : 3 >> setBreakpoints (empty)
// : 4 >> setExceptionBreakpoints (empty) // : 3 << setBreakpoints
// : 4 << setExceptionBreakpoints // : 4 >> setExceptionBreakpoints (empty)
// : 5 >> configurationDone // : 4 << setExceptionBreakpoints
// - Program stops upon launching : << stopped event // : 5 >> configurationDone
// : 5 << configurationDone // Program stops upon launching : << stopped event
// : 6 >> threads // : 5 << configurationDone
// : 6 << threads (Dummy) // : 6 >> threads
// : 7 >> threads // : 6 << threads (Dummy)
// : 7 << threads (Dummy) // : 7 >> threads
// : 8 >> stackTrace // : 7 << threads (Dummy)
// : 8 << error (Unable to produce stack trace) // : 8 >> stackTrace
// : 9 >> stackTrace // : 8 << error (Unable to produce stack trace)
// : 9 << error (Unable to produce stack trace) // : 9 >> stackTrace
// - User evaluates bad expression : 10 >> evaluate // : 9 << error (Unable to produce stack trace)
// : 10 << error (unable to find function context) // User evaluates bad expression : 10 >> evaluate
// - User evaluates good expression: 11 >> evaluate // : 10 << error (unable to find function context)
// : 11 << evaluate // User evaluates good expression: 11 >> evaluate
// - User selects "Continue" : 12 >> continue // : 11 << evaluate
// : 12 << continue // User selects "Continue" : 12 >> continue
// - Program runs to completion : << terminated event // : 12 << continue
// : 13 >> disconnect // Program runs to completion : << terminated event
// : << output event (Process exited) // : 13 >> disconnect
// : << output event (Detaching) // : << output event (Process exited)
// : 13 << disconnect // : << output event (Detaching)
// : 13 << disconnect
//
// This test exhaustively tests Seq and RequestSeq on all messages from the // This test exhaustively tests Seq and RequestSeq on all messages from the
// server. Other tests do not necessarily need to repeat all these checks. // server. Other tests do not necessarily need to repeat all these checks.
func TestLaunchStopOnEntry(t *testing.T) { func TestLaunchStopOnEntry(t *testing.T) {
@ -801,11 +803,12 @@ func TestPreSetBreakpoint(t *testing.T) {
} }
// checkStackFramesExact is a helper for verifying the values within StackTraceResponse. // checkStackFramesExact is a helper for verifying the values within StackTraceResponse.
// wantStartName - name of the first returned frame (ignored if "") //
// wantStartLine - file line of the first returned frame (ignored if <0). // wantStartName - name of the first returned frame (ignored if "")
// wantStartID - id of the first frame returned (ignored if wantFrames is 0). // wantStartLine - file line of the first returned frame (ignored if <0).
// wantFrames - number of frames returned (length of StackTraceResponse.Body.StackFrames array). // wantStartID - id of the first frame returned (ignored if wantFrames is 0).
// wantTotalFrames - total number of stack frames available (StackTraceResponse.Body.TotalFrames). // wantFrames - number of frames returned (length of StackTraceResponse.Body.StackFrames array).
// wantTotalFrames - total number of stack frames available (StackTraceResponse.Body.TotalFrames).
func checkStackFramesExact(t *testing.T, got *dap.StackTraceResponse, func checkStackFramesExact(t *testing.T, got *dap.StackTraceResponse,
wantStartName string, wantStartLine, wantStartID, wantFrames, wantTotalFrames int) { wantStartName string, wantStartLine, wantStartID, wantFrames, wantTotalFrames int) {
t.Helper() t.Helper()
@ -956,9 +959,10 @@ func checkStackFramesNamed(testName string, t *testing.T, got *dap.StackTraceRes
} }
// checkScope is a helper for verifying the values within a ScopesResponse. // checkScope is a helper for verifying the values within a ScopesResponse.
// i - index of the scope within ScopesRespose.Body.Scopes array //
// name - name of the scope // i - index of the scope within ScopesRespose.Body.Scopes array
// varRef - reference to retrieve variables of this scope. If varRef is negative, the reference is not checked. // name - name of the scope
// varRef - reference to retrieve variables of this scope. If varRef is negative, the reference is not checked.
func checkScope(t *testing.T, got *dap.ScopesResponse, i int, name string, varRef int) { func checkScope(t *testing.T, got *dap.ScopesResponse, i int, name string, varRef int) {
t.Helper() t.Helper()
if len(got.Body.Scopes) <= i { if len(got.Body.Scopes) <= i {
@ -971,8 +975,9 @@ func checkScope(t *testing.T, got *dap.ScopesResponse, i int, name string, varRe
} }
// checkChildren is a helper for verifying the number of variables within a VariablesResponse. // checkChildren is a helper for verifying the number of variables within a VariablesResponse.
// parentName - pseudoname of the enclosing variable or scope (used for error message only) //
// numChildren - number of variables/fields/elements of this variable // parentName - pseudoname of the enclosing variable or scope (used for error message only)
// numChildren - number of variables/fields/elements of this variable
func checkChildren(t *testing.T, got *dap.VariablesResponse, parentName string, numChildren int) { func checkChildren(t *testing.T, got *dap.VariablesResponse, parentName string, numChildren int) {
t.Helper() t.Helper()
if got.Body.Variables == nil { if got.Body.Variables == nil {
@ -984,13 +989,14 @@ func checkChildren(t *testing.T, got *dap.VariablesResponse, parentName string,
} }
// checkVar is a helper for verifying the values within a VariablesResponse. // checkVar is a helper for verifying the values within a VariablesResponse.
// i - index of the variable within VariablesRespose.Body.Variables array (-1 will search all vars for a match) //
// name - name of the variable // i - index of the variable within VariablesRespose.Body.Variables array (-1 will search all vars for a match)
// evalName - fully qualified variable name or alternative expression to load this variable // name - name of the variable
// value - the value of the variable // evalName - fully qualified variable name or alternative expression to load this variable
// useExactMatch - true if name, evalName and value are to be compared to exactly, false if to be used as regex // value - the value of the variable
// hasRef - true if the variable should have children and therefore a non-0 variable reference // useExactMatch - true if name, evalName and value are to be compared to exactly, false if to be used as regex
// ref - reference to retrieve children of this variable (0 if none) // hasRef - true if the variable should have children and therefore a non-0 variable reference
// ref - reference to retrieve children of this variable (0 if none)
func checkVar(t *testing.T, got *dap.VariablesResponse, i int, name, evalName, value, typ string, useExactMatch, hasRef bool, indexed, named int) (ref int) { func checkVar(t *testing.T, got *dap.VariablesResponse, i int, name, evalName, value, typ string, useExactMatch, hasRef bool, indexed, named int) (ref int) {
t.Helper() t.Helper()
if len(got.Body.Variables) <= i { if len(got.Body.Variables) <= i {
@ -3756,9 +3762,10 @@ func TestWorkingDir(t *testing.T) {
} }
// checkEval is a helper for verifying the values within an EvaluateResponse. // checkEval is a helper for verifying the values within an EvaluateResponse.
// value - the value of the evaluated expression //
// hasRef - true if the evaluated expression should have children and therefore a non-0 variable reference // value - the value of the evaluated expression
// ref - reference to retrieve children of this evaluated expression (0 if none) // hasRef - true if the evaluated expression should have children and therefore a non-0 variable reference
// ref - reference to retrieve children of this evaluated expression (0 if none)
func checkEval(t *testing.T, got *dap.EvaluateResponse, value string, hasRef bool) (ref int) { func checkEval(t *testing.T, got *dap.EvaluateResponse, value string, hasRef bool) (ref int) {
t.Helper() t.Helper()
if got.Body.Result != value || (got.Body.VariablesReference > 0) != hasRef { if got.Body.Result != value || (got.Body.VariablesReference > 0) != hasRef {
@ -3768,9 +3775,10 @@ func checkEval(t *testing.T, got *dap.EvaluateResponse, value string, hasRef boo
} }
// checkEvalIndexed is a helper for verifying the values within an EvaluateResponse. // checkEvalIndexed is a helper for verifying the values within an EvaluateResponse.
// value - the value of the evaluated expression //
// hasRef - true if the evaluated expression should have children and therefore a non-0 variable reference // value - the value of the evaluated expression
// ref - reference to retrieve children of this evaluated expression (0 if none) // hasRef - true if the evaluated expression should have children and therefore a non-0 variable reference
// ref - reference to retrieve children of this evaluated expression (0 if none)
func checkEvalIndexed(t *testing.T, got *dap.EvaluateResponse, value string, hasRef bool, indexed, named int) (ref int) { func checkEvalIndexed(t *testing.T, got *dap.EvaluateResponse, value string, hasRef bool, indexed, named int) (ref int) {
t.Helper() t.Helper()
if got.Body.Result != value || (got.Body.VariablesReference > 0) != hasRef || got.Body.IndexedVariables != indexed || got.Body.NamedVariables != named { if got.Body.Result != value || (got.Body.VariablesReference > 0) != hasRef || got.Body.IndexedVariables != indexed || got.Body.NamedVariables != named {
@ -5089,14 +5097,15 @@ type onBreakpoint struct {
// runDebugSessionWithBPs is a helper for executing the common init and shutdown // runDebugSessionWithBPs is a helper for executing the common init and shutdown
// sequences for a program that does not stop on entry // sequences for a program that does not stop on entry
// while specifying breakpoints and unique launch/attach criteria via parameters. // while specifying breakpoints and unique launch/attach criteria via parameters.
// cmd - "launch" or "attach" //
// cmdRequest - a function that sends a launch or attach request, // cmd - "launch" or "attach"
// so the test author has full control of its arguments. // cmdRequest - a function that sends a launch or attach request,
// Note that he rest of the test sequence assumes that // so the test author has full control of its arguments.
// stopOnEntry is false. // Note that he rest of the test sequence assumes that
// source - source file path, needed to set breakpoints, "" if none to be set. // stopOnEntry is false.
// breakpoints - list of lines, where breakpoints are to be set // source - source file path, needed to set breakpoints, "" if none to be set.
// onBPs - list of test sequences to execute at each of the set breakpoints. // breakpoints - list of lines, where breakpoints are to be set
// onBPs - list of test sequences to execute at each of the set breakpoints.
func runDebugSessionWithBPs(t *testing.T, client *daptest.Client, cmd string, cmdRequest func(), source string, breakpoints []int, onBPs []onBreakpoint) { func runDebugSessionWithBPs(t *testing.T, client *daptest.Client, cmd string, cmdRequest func(), source string, breakpoints []int, onBPs []onBreakpoint) {
client.InitializeRequest() client.InitializeRequest()
client.ExpectInitializeResponseAndCapabilities(t) client.ExpectInitializeResponseAndCapabilities(t)

@ -7,22 +7,32 @@ import (
) )
// Launch debug sessions support the following modes: // Launch debug sessions support the following modes:
// -- [DEFAULT] "debug" - builds and launches debugger for specified program (similar to 'dlv debug') //
// Required args: program // -- [DEFAULT] "debug" - builds and launches debugger for specified program (similar to 'dlv debug')
// Optional args with default: output, cwd, noDebug //
// Optional args: buildFlags, args // Required args: program
// -- "test" - builds and launches debugger for specified test (similar to 'dlv test') // Optional args with default: output, cwd, noDebug
// same args as above // Optional args: buildFlags, args
// -- "exec" - launches debugger for precompiled binary (similar to 'dlv exec') //
// Required args: program // -- "test" - builds and launches debugger for specified test (similar to 'dlv test')
// Optional args with default: cwd, noDebug //
// Optional args: args // same args as above
// -- "replay" - replays a trace generated by mozilla rr. Mozilla rr must be installed. //
// Required args: traceDirPath // -- "exec" - launches debugger for precompiled binary (similar to 'dlv exec')
// Optional args: args //
// -- "core" - examines a core dump (only supports linux and windows core dumps). // Required args: program
// Required args: program, coreFilePath // Optional args with default: cwd, noDebug
// Optional args: args // Optional args: args
//
// -- "replay" - replays a trace generated by mozilla rr. Mozilla rr must be installed.
//
// Required args: traceDirPath
// Optional args: args
//
// -- "core" - examines a core dump (only supports linux and windows core dumps).
//
// Required args: program, coreFilePath
// Optional args: args
// //
// TODO(hyangah): change this to 'validateLaunchMode' that checks // TODO(hyangah): change this to 'validateLaunchMode' that checks
// all the required/optional fields mentioned above. // all the required/optional fields mentioned above.

@ -632,15 +632,21 @@ type ListGoroutinesOut struct {
// If arg.Filters are specified the list of returned goroutines is filtered // If arg.Filters are specified the list of returned goroutines is filtered
// applying the specified filters. // applying the specified filters.
// For example: // For example:
// ListGoroutinesFilter{ Kind: ListGoroutinesFilterUserLoc, Negated: false, Arg: "afile.go" } //
// ListGoroutinesFilter{ Kind: ListGoroutinesFilterUserLoc, Negated: false, Arg: "afile.go" }
//
// will only return goroutines whose UserLoc contains "afile.go" as a substring. // will only return goroutines whose UserLoc contains "afile.go" as a substring.
// More specifically a goroutine matches a location filter if the specified // More specifically a goroutine matches a location filter if the specified
// location, formatted like this: // location, formatted like this:
// filename:lineno in function //
// filename:lineno in function
//
// contains Arg[0] as a substring. // contains Arg[0] as a substring.
// //
// Filters can also be applied to goroutine labels: // Filters can also be applied to goroutine labels:
// ListGoroutineFilter{ Kind: ListGoroutinesFilterLabel, Negated: false, Arg: "key=value" } //
// ListGoroutineFilter{ Kind: ListGoroutinesFilterLabel, Negated: false, Arg: "key=value" }
//
// this filter will only return goroutines that have a key=value label. // this filter will only return goroutines that have a key=value label.
// //
// If arg.GroupBy is not GoroutineFieldNone then the goroutines will // If arg.GroupBy is not GoroutineFieldNone then the goroutines will
@ -700,15 +706,15 @@ type FindLocationOut struct {
// FindLocation returns concrete location information described by a location expression. // FindLocation returns concrete location information described by a location expression.
// //
// loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address> // loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
// * <filename> can be the full path of a file or just a suffix // * <filename> can be the full path of a file or just a suffix
// * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name> // * <function> ::= <package>.<receiver type>.<name> | <package>.(*<receiver type>).<name> | <receiver type>.<name> | <package>.<name> | (*<receiver type>).<name> | <name>
// * <function> must be unambiguous // <function> must be unambiguous
// * /<regex>/ will return a location for each function matched by regex // * /<regex>/ will return a location for each function matched by regex
// * +<offset> returns a location for the line that is <offset> lines after the current line // * +<offset> returns a location for the line that is <offset> lines after the current line
// * -<offset> returns a location for the line that is <offset> lines before the current line // * -<offset> returns a location for the line that is <offset> lines before the current line
// * <line> returns a location for a line in the current file // * <line> returns a location for a line in the current file
// * *<address> returns the location corresponding to the specified address // * *<address> returns the location corresponding to the specified address
// //
// NOTE: this function does not actually set breakpoints. // NOTE: this function does not actually set breakpoints.
func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error { func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error {

@ -213,8 +213,9 @@ func isExportedOrBuiltinType(t reflect.Type) bool {
// available through the RPC interface. // available through the RPC interface.
// These are all the public methods of rcvr that have one of those // These are all the public methods of rcvr that have one of those
// two signatures: // two signatures:
// func (rcvr ReceiverType) Method(in InputType, out *ReplyType) error //
// func (rcvr ReceiverType) Method(in InputType, cb service.RPCCallback) // func (rcvr ReceiverType) Method(in InputType, out *ReplyType) error
// func (rcvr ReceiverType) Method(in InputType, cb service.RPCCallback)
func suitableMethods(rcvr interface{}, methods map[string]*methodType, log *logrus.Entry) { func suitableMethods(rcvr interface{}, methods map[string]*methodType, log *logrus.Entry) {
typ := reflect.TypeOf(rcvr) typ := reflect.TypeOf(rcvr)
rcvrv := reflect.ValueOf(rcvr) rcvrv := reflect.ValueOf(rcvr)