Skip to content

Commit

Permalink
exp/types: add more import tests
Browse files Browse the repository at this point in the history
Also simplified parsing of interface
types since they can only contain
methods (and no embedded interfaces)
in the export data.

R=rsc
CC=golang-dev
https://golang.org/cl/6446084
  • Loading branch information
griesemer committed Aug 9, 2012
1 parent f05a91e commit 0f25293
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 22 deletions.
30 changes: 9 additions & 21 deletions src/pkg/exp/types/gcimporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,33 +507,21 @@ func (p *gcParser) parseSignature() *Func {
return &Func{Params: params, Results: results, IsVariadic: isVariadic}
}

// MethodOrEmbedSpec = Name [ Signature ] .
// InterfaceType = "interface" "{" [ MethodList ] "}" .
// MethodList = Method { ";" Method } .
// Method = Name Signature .
//
func (p *gcParser) parseMethodOrEmbedSpec() *ast.Object {
name := p.parseName()
if p.tok == '(' {
typ := p.parseSignature()
obj := ast.NewObj(ast.Fun, name)
obj.Type = typ
return obj
}
// TODO lookup name and return that type
return ast.NewObj(ast.Typ, "_")
}

// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" .
// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } .
// (The methods of embedded interfaces are always "inlined"
// by the compiler and thus embedded interfaces are never
// visible in the export data.)
//
func (p *gcParser) parseInterfaceType() Type {
var methods ObjList

parseMethod := func() {
switch m := p.parseMethodOrEmbedSpec(); m.Kind {
case ast.Typ:
// TODO expand embedded methods
case ast.Fun:
methods = append(methods, m)
}
obj := ast.NewObj(ast.Fun, p.parseName())
obj.Type = p.parseSignature()
methods = append(methods, obj)
}

p.expectKeyword("interface")
Expand Down
41 changes: 40 additions & 1 deletion src/pkg/exp/types/gcimporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func init() {
gcPath = filepath.Join(build.ToolDir, gc)
}

func compile(t *testing.T, dirname, filename string) (outFn string) {
func compile(t *testing.T, dirname, filename string) string {
cmd := exec.Command(gcPath, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
Expand Down Expand Up @@ -113,3 +113,42 @@ func TestGcImport(t *testing.T) {
nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
t.Logf("tested %d imports", nimports)
}

var importedObjectTests = []struct {
name string
kind ast.ObjKind
typ string
}{
{"unsafe.Pointer", ast.Typ, "Pointer"},
{"math.Pi", ast.Con, "basicType"}, // TODO(gri) need to complete BasicType
{"io.Reader", ast.Typ, "interface{Read(p []byte) (n int, err error)}"},
{"io.ReadWriter", ast.Typ, "interface{Read(p []byte) (n int, err error); Write(p []byte) (n int, err error)}"},
{"math.Sin", ast.Fun, "func(x float64) (_ float64)"},
// TODO(gri) add more tests
}

func TestGcImportedTypes(t *testing.T) {
for _, test := range importedObjectTests {
s := strings.Split(test.name, ".")
if len(s) != 2 {
t.Fatal("inconsistent test data")
}
importPath := s[0]
objName := s[1]

pkg, err := GcImport(imports, importPath)
if err != nil {
t.Error(err)
continue
}

obj := pkg.Data.(*ast.Scope).Lookup(objName)
if obj.Kind != test.kind {
t.Errorf("%s: got kind = %q; want %q", test.name, obj.Kind, test.kind)
}
typ := TypeString(Underlying(obj.Type.(Type)))
if typ != test.typ {
t.Errorf("%s: got type = %q; want %q", test.name, typ, test.typ)
}
}
}

0 comments on commit 0f25293

Please sign in to comment.