aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/resolver_test.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2020-10-19 15:28:22 -0700
committerRobert Griesemer <gri@golang.org>2020-10-21 00:51:12 +0000
commitca36ba83ab86b9eb1ddc076f0ebfda648ce31d6b (patch)
treec061b8a1ffa5064e361e9ba58ea6693fab6ab0e0 /src/cmd/compile/internal/types2/resolver_test.go
parent6ff16fe3ee46f8e35c18226d04bd38a396eb4175 (diff)
downloadgo-ca36ba83ab86b9eb1ddc076f0ebfda648ce31d6b.tar.gz
go-ca36ba83ab86b9eb1ddc076f0ebfda648ce31d6b.zip
[dev.typeparams] cmd/compile/internal/importer, types2: initial check-in of types2 and importer
This is a copy of the importer and types2 (unreviewed) prototype version excluding the testdata directory containing tests (see below). Each file is marked with the comment // UNREVIEWED on the first line. The plan is to check in this code wholesale (it runs and passes all tests) and then review the code file-by-file via subsequent CLs and remove the "// UNREVIEWED" comments as we review the files. Since most tests are unchanged from the original go/types, the next CL will commit those tests as they don't need to be reviewed again. (Eventually we may want to factor them out and share them from a single place, e.g. the test directory.) The existing file fmtmap_test.go was updated. Change-Id: I9bd0ad1a7e7188b501423483a44d18e623c0fe71 Reviewed-on: https://go-review.googlesource.com/c/go/+/263624 Trust: Robert Griesemer <gri@golang.org> Trust: Keith Randall <khr@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types2/resolver_test.go')
-rw-r--r--src/cmd/compile/internal/types2/resolver_test.go223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/types2/resolver_test.go b/src/cmd/compile/internal/types2/resolver_test.go
new file mode 100644
index 0000000000..cdfdba6b43
--- /dev/null
+++ b/src/cmd/compile/internal/types2/resolver_test.go
@@ -0,0 +1,223 @@
+// UNREVIEWED
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2_test
+
+import (
+ "cmd/compile/internal/syntax"
+ "fmt"
+ "internal/testenv"
+ "sort"
+ "testing"
+
+ . "cmd/compile/internal/types2"
+)
+
+type resolveTestImporter struct {
+ importer ImporterFrom
+ imported map[string]bool
+}
+
+func (imp *resolveTestImporter) Import(string) (*Package, error) {
+ panic("should not be called")
+}
+
+func (imp *resolveTestImporter) ImportFrom(path, srcDir string, mode ImportMode) (*Package, error) {
+ if mode != 0 {
+ panic("mode must be 0")
+ }
+ if imp.importer == nil {
+ imp.importer = defaultImporter().(ImporterFrom)
+ imp.imported = make(map[string]bool)
+ }
+ pkg, err := imp.importer.ImportFrom(path, srcDir, mode)
+ if err != nil {
+ return nil, err
+ }
+ imp.imported[path] = true
+ return pkg, nil
+}
+
+func TestResolveIdents(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+
+ sources := []string{
+ `
+ package p
+ import "fmt"
+ import "math"
+ const pi = math.Pi
+ func sin(x float64) float64 {
+ return math.Sin(x)
+ }
+ var Println = fmt.Println
+ `,
+ `
+ package p
+ import "fmt"
+ type errorStringer struct { fmt.Stringer; error }
+ func f() string {
+ _ = "foo"
+ return fmt.Sprintf("%d", g())
+ }
+ func g() (x int) { return }
+ `,
+ `
+ package p
+ import . "go/parser"
+ import "sync"
+ func h() Mode { return ImportsOnly }
+ var _, x int = 1, 2
+ func init() {}
+ type T struct{ *sync.Mutex; a, b, c int}
+ type I interface{ m() }
+ var _ = T{a: 1, b: 2, c: 3}
+ func (_ T) m() {}
+ func (T) _() {}
+ var i I
+ var _ = i.m
+ func _(s []int) { for i, x := range s { _, _ = i, x } }
+ func _(x interface{}) {
+ switch x := x.(type) {
+ case int:
+ _ = x
+ }
+ switch {} // implicit 'true' tag
+ }
+ `,
+ `
+ package p
+ type S struct{}
+ func (T) _() {}
+ func (T) _() {}
+ `,
+ `
+ package p
+ func _() {
+ L0:
+ L1:
+ goto L0
+ for {
+ goto L1
+ }
+ if true {
+ goto L2
+ }
+ L2:
+ }
+ `,
+ }
+
+ pkgnames := []string{
+ "fmt",
+ "math",
+ }
+
+ // parse package files
+ var files []*syntax.File
+ for i, src := range sources {
+ f, err := parseSrc(fmt.Sprintf("sources[%d]", i), src)
+ if err != nil {
+ t.Fatal(err)
+ }
+ files = append(files, f)
+ }
+
+ // resolve and type-check package AST
+ importer := new(resolveTestImporter)
+ conf := Config{Importer: importer}
+ uses := make(map[*syntax.Name]Object)
+ defs := make(map[*syntax.Name]Object)
+ _, err := conf.Check("testResolveIdents", files, &Info{Defs: defs, Uses: uses})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // check that all packages were imported
+ for _, name := range pkgnames {
+ if !importer.imported[name] {
+ t.Errorf("package %s not imported", name)
+ }
+ }
+
+ // check that qualified identifiers are resolved
+ for _, f := range files {
+ Walk(f, func(n syntax.Node) bool {
+ if s, ok := n.(*syntax.SelectorExpr); ok {
+ if x, ok := s.X.(*syntax.Name); ok {
+ obj := uses[x]
+ if obj == nil {
+ t.Errorf("%s: unresolved qualified identifier %s", x.Pos(), x.Value)
+ return true
+ }
+ if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
+ t.Errorf("%s: unresolved selector %s", s.Sel.Pos(), s.Sel.Value)
+ return true
+ }
+ return true
+ }
+ return true
+ }
+ return false
+ })
+ }
+
+ for id, obj := range uses {
+ if obj == nil {
+ t.Errorf("%s: Uses[%s] == nil", id.Pos(), id.Value)
+ }
+ }
+
+ // Check that each identifier in the source is found in uses or defs or both.
+ // We need the foundUses/Defs maps (rather then just deleting the found objects
+ // from the uses and defs maps) because Walk traverses shared nodes multiple
+ // times (e.g. types in field lists such as "a, b, c int").
+ foundUses := make(map[*syntax.Name]bool)
+ foundDefs := make(map[*syntax.Name]bool)
+ var both []string
+ for _, f := range files {
+ Walk(f, func(n syntax.Node) bool {
+ if x, ok := n.(*syntax.Name); ok {
+ var objects int
+ if _, found := uses[x]; found {
+ objects |= 1
+ foundUses[x] = true
+ }
+ if _, found := defs[x]; found {
+ objects |= 2
+ foundDefs[x] = true
+ }
+ switch objects {
+ case 0:
+ t.Errorf("%s: unresolved identifier %s", x.Pos(), x.Value)
+ case 3:
+ both = append(both, x.Value)
+ }
+ return true
+ }
+ return false
+ })
+ }
+
+ // check the expected set of idents that are simultaneously uses and defs
+ sort.Strings(both)
+ if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
+ t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
+ }
+
+ // any left-over identifiers didn't exist in the source
+ for x := range uses {
+ if !foundUses[x] {
+ t.Errorf("%s: identifier %s not present in source", x.Pos(), x.Value)
+ }
+ }
+ for x := range defs {
+ if !foundDefs[x] {
+ t.Errorf("%s: identifier %s not present in source", x.Pos(), x.Value)
+ }
+ }
+
+ // TODO(gri) add tests to check ImplicitObj callbacks
+}