diff options
author | Robert Griesemer <gri@golang.org> | 2020-10-19 15:28:22 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2020-10-21 00:51:12 +0000 |
commit | ca36ba83ab86b9eb1ddc076f0ebfda648ce31d6b (patch) | |
tree | c061b8a1ffa5064e361e9ba58ea6693fab6ab0e0 /src/cmd/compile/internal/types2/resolver_test.go | |
parent | 6ff16fe3ee46f8e35c18226d04bd38a396eb4175 (diff) | |
download | go-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.go | 223 |
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 +} |