mirror of
https://github.com/golang/go
synced 2024-11-18 11:04:42 -07:00
go/gcimporter15: support export/import of invalid aliases
+ test Tested on 1.6, 1.7, and 1.8. Fixes golang/go#17731. Change-Id: I06dff4a72ff08ed5e8ae1d23a1e65fe719c03180 Reviewed-on: https://go-review.googlesource.com/32581 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
c3ce94f8a8
commit
f08d70c2ed
@ -177,24 +177,6 @@ func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
||||
}
|
||||
|
||||
func (p *exporter) obj(obj types.Object) {
|
||||
if orig := original(obj); orig != obj {
|
||||
if orig == nil {
|
||||
// invalid alias - don't export for now (issue 17731)
|
||||
return
|
||||
}
|
||||
|
||||
if !p.reexported[orig] {
|
||||
p.obj(orig)
|
||||
p.reexported[orig] = true
|
||||
}
|
||||
|
||||
p.tag(aliasTag)
|
||||
p.pos(obj)
|
||||
p.string(obj.Name())
|
||||
p.qualifiedName(orig)
|
||||
return
|
||||
}
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *types.Const:
|
||||
p.tag(constTag)
|
||||
@ -221,6 +203,20 @@ func (p *exporter) obj(obj types.Object) {
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
|
||||
case *types_Alias:
|
||||
// make sure the original is exported before the alias
|
||||
// (if the alias declaration was invalid, orig will be nil)
|
||||
orig := original(obj)
|
||||
if orig != nil && !p.reexported[orig] {
|
||||
p.obj(orig)
|
||||
p.reexported[orig] = true
|
||||
}
|
||||
|
||||
p.tag(aliasTag)
|
||||
p.pos(obj)
|
||||
p.string(obj.Name())
|
||||
p.qualifiedName(orig)
|
||||
|
||||
default:
|
||||
log.Fatalf("gcimporter: unexpected object %v (%T)", obj, obj)
|
||||
}
|
||||
@ -280,6 +276,10 @@ func commonPrefixLen(a, b string) int {
|
||||
}
|
||||
|
||||
func (p *exporter) qualifiedName(obj types.Object) {
|
||||
if obj == nil {
|
||||
p.string("")
|
||||
return
|
||||
}
|
||||
p.string(obj.Name())
|
||||
p.pkg(obj.Pkg(), false)
|
||||
}
|
||||
|
59
go/gcimporter15/bexport18_test.go
Normal file
59
go/gcimporter15/bexport18_test.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package gcimporter_test
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"testing"
|
||||
|
||||
gcimporter "golang.org/x/tools/go/gcimporter15"
|
||||
)
|
||||
|
||||
func TestInvalidAlias(t *testing.T) {
|
||||
// parse and typecheck
|
||||
const src = "package p; func InvalidAlias => foo.f"
|
||||
fset1 := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset1, "p.go", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var conf types.Config
|
||||
pkg, err := conf.Check("p", fset1, []*ast.File{f}, nil)
|
||||
if err == nil {
|
||||
t.Fatal("invalid source type-checked without error")
|
||||
}
|
||||
if pkg == nil {
|
||||
t.Fatal("nil package returned")
|
||||
}
|
||||
|
||||
// export
|
||||
exportdata := gcimporter.BExportData(fset1, pkg)
|
||||
|
||||
// import
|
||||
imports := make(map[string]*types.Package)
|
||||
fset2 := token.NewFileSet()
|
||||
_, pkg2, err := gcimporter.BImportData(fset2, imports, exportdata, pkg.Path())
|
||||
if err != nil {
|
||||
t.Fatalf("BImportData(%s): %v", pkg.Path(), err)
|
||||
}
|
||||
|
||||
// pkg2 must contain InvalidAlias as an invalid Alias
|
||||
obj := pkg2.Scope().Lookup("InvalidAlias")
|
||||
if obj == nil {
|
||||
t.Fatal("InvalidAlias not found")
|
||||
}
|
||||
alias, ok := obj.(*types.Alias)
|
||||
if !ok {
|
||||
t.Fatalf("got %v; want alias", alias)
|
||||
}
|
||||
if alias.Type() != types.Typ[types.Invalid] || alias.Orig() != nil {
|
||||
t.Fatalf("got %v (orig = %v); want invalid alias", alias, alias.Orig())
|
||||
}
|
||||
}
|
@ -282,11 +282,13 @@ func (p *importer) obj(tag int) {
|
||||
p.declare(types.NewFunc(pos, pkg, name, sig))
|
||||
|
||||
case aliasTag:
|
||||
aliasPos := p.pos()
|
||||
aliasName := p.string()
|
||||
pkg, name := p.qualifiedName()
|
||||
obj := pkg.Scope().Lookup(name)
|
||||
p.declare(newAlias(aliasPos, p.pkgList[0], aliasName,obj))
|
||||
pos := p.pos()
|
||||
name := p.string()
|
||||
var orig types.Object
|
||||
if pkg, name := p.qualifiedName(); pkg != nil {
|
||||
orig = pkg.Scope().Lookup(name)
|
||||
}
|
||||
p.declare(types_NewAlias(pos, p.pkgList[0], name, orig))
|
||||
|
||||
default:
|
||||
errorf("unexpected object tag %d", tag)
|
||||
@ -347,7 +349,9 @@ var (
|
||||
|
||||
func (p *importer) qualifiedName() (pkg *types.Package, name string) {
|
||||
name = p.string()
|
||||
pkg = p.pkg()
|
||||
if name != "" {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,18 @@ import (
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func newAlias(pos token.Pos, pkg *types.Package, name string, orig types.Object) types.Object {
|
||||
errorf("unexpected alias in non-Go1.8 export data: %s.%s => %v", pkg.Name(), name, orig)
|
||||
type types_Alias struct {
|
||||
types.Object
|
||||
dummy int
|
||||
} // satisfies types.Object but will never be encountered
|
||||
|
||||
func types_NewAlias(pos token.Pos, pkg *types.Package, name string, orig types.Object) types.Object {
|
||||
errorf("unexpected alias in non-Go1.8 export data: %s.%s => %v", pkg.Name(), name, orig) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func original(obj types.Object) types.Object {
|
||||
return obj // don't know about aliases
|
||||
func original(types.Object) types.Object {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
const testfile = "exports17.go"
|
||||
|
@ -8,7 +8,9 @@ package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
func newAlias => types.NewAlias
|
||||
type types_Alias => types.Alias
|
||||
|
||||
func types_NewAlias => types.NewAlias
|
||||
|
||||
// TODO(gri) Consider exporting this functionality from go/types (issue 17730).
|
||||
func original(obj types.Object) types.Object {
|
||||
|
Loading…
Reference in New Issue
Block a user