Skip to content

Commit

Permalink
go/pointer: support reflect.Value in AddExtendedQuery
Browse files Browse the repository at this point in the history
We were calling types.Type.Underlying() too early, which caused CanPoint
to see an ordinary struct, not reflect.Value.

Change-Id: I23ba3b9451bc1abc1ad8a45c790d2e22c1481f26
Reviewed-on: https://go-review.googlesource.com/129196
Run-TryBot: Dominik Honnef <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Alan Donovan <[email protected]>
  • Loading branch information
dominikh committed Aug 13, 2018
1 parent 87c7dcb commit a434f64
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 12 deletions.
2 changes: 1 addition & 1 deletion go/pointer/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (c *Config) AddIndirectQuery(v ssa.Value) {
// // 'type T struct { F *int }', the following query will access the field F.
// c.AddExtendedQuery(v, "x[1][0].F")
func (c *Config) AddExtendedQuery(v ssa.Value, query string) (*Pointer, error) {
ops, _, err := parseExtendedQuery(v.Type().Underlying(), query)
ops, _, err := parseExtendedQuery(v.Type(), query)
if err != nil {
return nil, fmt.Errorf("invalid query %q: %s", query, err)
}
Expand Down
4 changes: 2 additions & 2 deletions go/pointer/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func destructuringOps(typ types.Type, expr ast.Expr) ([]interface{}, types.Type,
}

var structT *types.Struct
switch typ := typ.(type) {
switch typ := typ.Underlying().(type) {
case *types.Pointer:
var ok bool
structT, ok = typ.Elem().Underlying().(*types.Struct)
Expand Down Expand Up @@ -107,7 +107,7 @@ func destructuringOps(typ types.Type, expr ast.Expr) ([]interface{}, types.Type,
if err != nil {
return nil, nil, err
}
switch typ := typ.(type) {
switch typ := typ.Underlying().(type) {
case *types.Array:
out = append(out, "arrayelem")
return out, typ.Elem().Underlying(), nil
Expand Down
26 changes: 17 additions & 9 deletions go/pointer/query_test.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
package pointer

import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"reflect"
"testing"

"golang.org/x/tools/go/loader"
)

func TestParseExtendedQuery(t *testing.T) {
const myprog = `
package pkg
import "reflect"
type T []*int
var V1 *int
var V2 **int
var V3 []*int
var V4 chan []*int
var V5 struct {F1, F2 chan *int}
var V6 [1]chan *int
var V7 int
var V8 T
var V9 reflect.Value
`
tests := []struct {
in string
Expand All @@ -27,8 +32,10 @@ var V7 int
valid bool
}{
{`x`, []interface{}{"x"}, "V1", true},
{`x`, []interface{}{"x"}, "V9", true},
{`*x`, []interface{}{"x", "load"}, "V2", true},
{`x[0]`, []interface{}{"x", "sliceelem"}, "V3", true},
{`x[0]`, []interface{}{"x", "sliceelem"}, "V8", true},
{`<-x`, []interface{}{"x", "recv"}, "V4", true},
{`(<-x)[0]`, []interface{}{"x", "recv", "sliceelem"}, "V4", true},
{`<-x.F2`, []interface{}{"x", "field", 1, "recv"}, "V5", true},
Expand All @@ -40,19 +47,20 @@ var V7 int
{`close(x)`, nil, "V1", false},
}

fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "file.go", myprog, 0)
var conf loader.Config
f, err := conf.ParseFile("file.go", myprog)
if err != nil {
t.Fatal(err)
}
cfg := &types.Config{}
pkg, err := cfg.Check("main", fset, []*ast.File{f}, nil)
conf.CreateFromFiles("main", f)
lprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
pkg := lprog.Created[0].Pkg

for _, test := range tests {
typ := pkg.Scope().Lookup(test.v).Type().Underlying()
typ := pkg.Scope().Lookup(test.v).Type()
ops, _, err := parseExtendedQuery(typ, test.in)
if test.valid && err != nil {
t.Errorf("parseExtendedQuery(%q) = %s, expected no error", test.in, err)
Expand Down

0 comments on commit a434f64

Please sign in to comment.