Skip to content

Commit

Permalink
allow printing of unexported fields and methods
Browse files Browse the repository at this point in the history
Also guard against panics in the eval library.
  • Loading branch information
jeremyschlatter committed Jul 20, 2015
1 parent ce7ad0e commit e57fb7e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 20 deletions.
16 changes: 15 additions & 1 deletion lib/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"sync/atomic"
"unicode"
"unsafe"

"github.com/mailgun/godebug/Godeps/_workspace/src/github.com/0xfaded/eval"
)
Expand Down Expand Up @@ -334,6 +335,13 @@ func waitForInput(scope *Scope, line int) {
default:
s := make([]string, len(results))
for i, r := range results {
if !r.CanInterface() {
if r.CanAddr() {
r = reflect.NewAt(r.Type(), unsafe.Pointer(r.UnsafeAddr())).Elem()
} else {
s[i] = fmt.Sprintf("godebug cannot access this field or method. Sorry! Let us know about it at github.com/mailgun/godebug/issues/new and we'll fix it")
}
}
ifc := r.Interface()
if _, ok := ifc.(*eval.ConstNumber); ok {
s[i] = fmt.Sprintf("%v", ifc)
Expand All @@ -357,10 +365,16 @@ func waitForInput(scope *Scope, line int) {

// goEval runs eval.EvalEnv in a new goroutine. This is a quick hack to
// keep the debugger from pausing while running eval.EvalEnv.
// It is also used to recover from panics in the eval library.
func goEval(expr string, env eval.Env) (result []reflect.Value, panik error, compileErrors []error) {
c := make(chan struct{})
go func() {
defer close(c)
defer func() {
if r := recover(); r != nil {
panik = fmt.Errorf("%v", r)
}
close(c)
}()
result, panik, compileErrors = eval.EvalEnv(expr, env)
}()
<-c
Expand Down
15 changes: 11 additions & 4 deletions testdata/single-file-tests/regression-in.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ func a() int {
return 0
}

func init() {
switchInit()
}

// Don't repeat switch initialization, use correct scope inside switch.
func switchInit() {
_ = "breakpoint"
Expand All @@ -141,3 +137,14 @@ func constants() {
const tooSmallForInt32 = (-1 << 31) - 1
const tooBigForInt64 = 1 << 63
}

func unexportedField() {
var f struct{ bar int }
f.bar = 5
_ = "breakpoint"
}

func init() {
switchInit()
unexportedField()
}
56 changes: 41 additions & 15 deletions testdata/single-file-tests/regression-out.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,31 +283,27 @@ func a() int {
return 0
}

func init() {
switchInit()
}

func switchInit() {
ctx, _ok := godebug.EnterFunc(switchInit)
if !_ok {
return
}
defer godebug.ExitFunc(ctx)
godebug.SetTraceGen(ctx)
godebug.Line(ctx, regression_in_go_scope, 132)
godebug.Line(ctx, regression_in_go_scope, 128)
{
godebug.Line(ctx, regression_in_go_scope, 133)
godebug.Line(ctx, regression_in_go_scope, 129)
a := a()
scope := regression_in_go_scope.EnteringNewChildScope()
scope.Declare("a", &a)
switch {
default:
godebug.Line(ctx, scope, 134)
godebug.Line(ctx, scope, 135)
godebug.Line(ctx, scope, 130)
godebug.Line(ctx, scope, 131)
_ = a
}
}
godebug.Line(ctx, regression_in_go_scope, 137)
godebug.Line(ctx, regression_in_go_scope, 133)
_ = "the variable a should be out of scope"
}

Expand All @@ -317,15 +313,37 @@ func constants() {
return
}
defer godebug.ExitFunc(ctx)
godebug.Line(ctx, regression_in_go_scope, 141)
godebug.Line(ctx, regression_in_go_scope, 137)
const tooSmallForInt32 = (-1 << 31) - 1
scope := regression_in_go_scope.EnteringNewChildScope()
scope.Constant("tooSmallForInt32", int64(tooSmallForInt32))
godebug.Line(ctx, scope, 142)
godebug.Line(ctx, scope, 138)
const tooBigForInt64 = 1 << 63
scope.Constant("tooBigForInt64", uint64(tooBigForInt64))
}

func unexportedField() {
ctx, _ok := godebug.EnterFunc(unexportedField)
if !_ok {
return
}
defer godebug.ExitFunc(ctx)
godebug.Line(ctx, regression_in_go_scope, 142)
var f struct{ bar int }
scope := regression_in_go_scope.EnteringNewChildScope()
scope.Declare("f", &f)
godebug.Line(ctx, scope, 143)
f.bar = 5
godebug.SetTraceGen(ctx)
godebug.Line(ctx, scope, 144)

}

func init() {
switchInit()
unexportedField()
}

var regression_in_go_contents = `package main
func main() {
Expand Down Expand Up @@ -451,10 +469,6 @@ func a() int {
return 0
}
func init() {
switchInit()
}
// Don't repeat switch initialization, use correct scope inside switch.
func switchInit() {
_ = "breakpoint"
Expand All @@ -469,6 +483,17 @@ func constants() {
const tooSmallForInt32 = (-1 << 31) - 1
const tooBigForInt64 = 1 << 63
}
func unexportedField() {
var f struct{ bar int }
f.bar = 5
_ = "breakpoint"
}
func init() {
switchInit()
unexportedField()
}
`


Expand All @@ -492,6 +517,7 @@ func init() {
"a": a,
"switchInit": switchInit,
"constants": constants,
"unexportedField": unexportedField,

}
}
4 changes: 4 additions & 0 deletions testdata/single-file-tests/regression-session.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
(godebug) p a
undefined: a
(godebug) continue
-> _ = "breakpoint"
(godebug) p f.bar
5
(godebug) continue
hello
test
-> _ = "breakpoint"
Expand Down

0 comments on commit e57fb7e

Please sign in to comment.