diff --git a/Documentation/cli/expr.md b/Documentation/cli/expr.md index db18a676..8233d756 100644 --- a/Documentation/cli/expr.md +++ b/Documentation/cli/expr.md @@ -81,3 +81,12 @@ To use a field of a struct contained inside an interface variable use a type ass (dlv) p iface1.(*main.astruct).B 2 ``` + +# Specifying package paths + +Packages with the same name can be disambiguated by using the full package path. For example, if the application imports two packages, `some/package` and `some/other/package`, both defining a variable `A`, the two variables can be accessed using this syntax: + +``` +(dlv) p "some/package".A +(dlv) p "some/other/package".A +``` diff --git a/_fixtures/pkgrenames.go b/_fixtures/pkgrenames.go index 2ee420fd..d315e6b7 100644 --- a/_fixtures/pkgrenames.go +++ b/_fixtures/pkgrenames.go @@ -51,5 +51,5 @@ func main() { m := t.Method(0) fmt.Println(m.Type.In(0)) fmt.Println(m.Type.String()) - fmt.Println(badexpr, req, amap, amap2, dir0someType, dir1someType, amap3, anarray, achan, aslice, afunc, astruct, astruct2, iface2iface, iface3, pkg.SomeVar) + fmt.Println(badexpr, req, amap, amap2, dir0someType, dir1someType, amap3, anarray, achan, aslice, afunc, astruct, astruct2, iface2iface, iface3, pkg.SomeVar, pkg.A, dir1pkg.A) } diff --git a/_fixtures/vendor/dir0/pkg/main.go b/_fixtures/vendor/dir0/pkg/main.go index bb0d895b..c3435b26 100644 --- a/_fixtures/vendor/dir0/pkg/main.go +++ b/_fixtures/vendor/dir0/pkg/main.go @@ -1,5 +1,7 @@ package pkg +var A = 0 + type SomeType struct { X float64 } diff --git a/_fixtures/vendor/dir1/pkg/main.go b/_fixtures/vendor/dir1/pkg/main.go index 99ad1435..9201e224 100644 --- a/_fixtures/vendor/dir1/pkg/main.go +++ b/_fixtures/vendor/dir1/pkg/main.go @@ -1,5 +1,7 @@ package pkg +var A = 1 + type SomeType struct { X int Y int diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 0417c29a..ec1cb320 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -11,6 +11,7 @@ import ( "go/printer" "go/token" "reflect" + "strconv" "github.com/derekparker/delve/pkg/dwarf/godwarf" "github.com/derekparker/delve/pkg/dwarf/reader" @@ -187,6 +188,15 @@ func (scope *EvalScope) evalAST(t ast.Expr) (*Variable, error) { return v, nil } } + // try to accept "package/path".varname syntax for package variables + if maybePkg, ok := node.X.(*ast.BasicLit); ok && maybePkg.Kind == token.STRING { + pkgpath, err := strconv.Unquote(maybePkg.Value) + if err == nil { + if v, err := scope.findGlobal(pkgpath + "." + node.Sel.Name); err == nil { + return v, nil + } + } + } // if it's not a package variable then it must be a struct member access return scope.evalStructSelector(node) diff --git a/service/test/variables_test.go b/service/test/variables_test.go index bf52f9f8..5533a14b 100644 --- a/service/test/variables_test.go +++ b/service/test/variables_test.go @@ -920,6 +920,9 @@ func TestPackageRenames(t *testing.T) { {"astruct", true, `interface {}(*struct { A github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType; B github.com/derekparker/delve/_fixtures/vendor/dir0/pkg.SomeType }) *{A: github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType {X: 1, Y: 2}, B: github.com/derekparker/delve/_fixtures/vendor/dir0/pkg.SomeType {X: 3}}`, "", "interface {}", nil}, {"astruct2", true, `interface {}(*struct { github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType; X int }) *{SomeType: github.com/derekparker/delve/_fixtures/vendor/dir1/pkg.SomeType {X: 1, Y: 2}, X: 10}`, "", "interface {}", nil}, {"iface2iface", true, `interface {}(*interface { AMethod(int) int; AnotherMethod(int) int }) **github.com/derekparker/delve/_fixtures/vendor/dir0/pkg.SomeType {X: 4}`, "", "interface {}", nil}, + + {`"dir0/pkg".A`, false, "0", "", "int", nil}, + {`"dir1/pkg".A`, false, "1", "", "int", nil}, } ver, _ := goversion.Parse(runtime.Version())