Commit 1da1da3d authored by Alan Donovan's avatar Alan Donovan

go/internal/gcimporter: set Pos attribute of decoded types.Objects

This change is a copy of CL 22788 in x/tools.
It has no observable effect yet, but brings the two packages in synch.

Change-Id: I266c77547cb46deb69b1a36e1674dfebc430e3a5
Reviewed-on: https://go-review.googlesource.com/22936Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent d08c3d13
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
...@@ -34,6 +35,8 @@ type importer struct { ...@@ -34,6 +35,8 @@ type importer struct {
posInfoFormat bool posInfoFormat bool
prevFile string prevFile string
prevLine int prevLine int
fset *token.FileSet
files map[string]*token.File
// debugging support // debugging support
debugFormat bool debugFormat bool
...@@ -44,7 +47,7 @@ type importer struct { ...@@ -44,7 +47,7 @@ type importer struct {
// and returns the number of bytes consumed and a reference to the package. // and returns the number of bytes consumed and a reference to the package.
// If the export data version is not recognized or the format is otherwise // If the export data version is not recognized or the format is otherwise
// compromised, an error is returned. // compromised, an error is returned.
func BImportData(imports map[string]*types.Package, data []byte, path string) (_ int, _ *types.Package, err error) { func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, _ *types.Package, err error) {
// catch panics and return them as errors // catch panics and return them as errors
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
...@@ -60,6 +63,8 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (_ ...@@ -60,6 +63,8 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (_
path: path, path: path,
version: -1, // unknown version version: -1, // unknown version
strList: []string{""}, // empty string is mapped to 0 strList: []string{""}, // empty string is mapped to 0
fset: fset,
files: make(map[string]*token.File),
} }
// read version info // read version info
...@@ -219,37 +224,37 @@ func (p *importer) declare(obj types.Object) { ...@@ -219,37 +224,37 @@ func (p *importer) declare(obj types.Object) {
func (p *importer) obj(tag int) { func (p *importer) obj(tag int) {
switch tag { switch tag {
case constTag: case constTag:
p.pos() pos := p.pos()
pkg, name := p.qualifiedName() pkg, name := p.qualifiedName()
typ := p.typ(nil) typ := p.typ(nil)
val := p.value() val := p.value()
p.declare(types.NewConst(token.NoPos, pkg, name, typ, val)) p.declare(types.NewConst(pos, pkg, name, typ, val))
case typeTag: case typeTag:
_ = p.typ(nil) _ = p.typ(nil)
case varTag: case varTag:
p.pos() pos := p.pos()
pkg, name := p.qualifiedName() pkg, name := p.qualifiedName()
typ := p.typ(nil) typ := p.typ(nil)
p.declare(types.NewVar(token.NoPos, pkg, name, typ)) p.declare(types.NewVar(pos, pkg, name, typ))
case funcTag: case funcTag:
p.pos() pos := p.pos()
pkg, name := p.qualifiedName() pkg, name := p.qualifiedName()
params, isddd := p.paramList() params, isddd := p.paramList()
result, _ := p.paramList() result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd) sig := types.NewSignature(nil, params, result, isddd)
p.declare(types.NewFunc(token.NoPos, pkg, name, sig)) p.declare(types.NewFunc(pos, pkg, name, sig))
default: default:
errorf("unexpected object tag %d", tag) errorf("unexpected object tag %d", tag)
} }
} }
func (p *importer) pos() { func (p *importer) pos() token.Pos {
if !p.posInfoFormat { if !p.posInfoFormat {
return return token.NoPos
} }
file := p.prevFile file := p.prevFile
...@@ -265,9 +270,40 @@ func (p *importer) pos() { ...@@ -265,9 +270,40 @@ func (p *importer) pos() {
} }
p.prevLine = line p.prevLine = line
// TODO(gri) register new position // Synthesize a token.Pos
// Since we don't know the set of needed file positions, we
// reserve maxlines positions per file.
const maxlines = 64 * 1024
f := p.files[file]
if f == nil {
f = p.fset.AddFile(file, -1, maxlines)
p.files[file] = f
// Allocate the fake linebreak indices on first use.
// TODO(adonovan): opt: save ~512KB using a more complex scheme?
fakeLinesOnce.Do(func() {
fakeLines = make([]int, maxlines)
for i := range fakeLines {
fakeLines[i] = i
}
})
f.SetLines(fakeLines)
}
if line > maxlines {
line = 1
}
// Treat the file as if it contained only newlines
// and column=1: use the line number as the offset.
return f.Pos(line - 1)
} }
var (
fakeLines []int
fakeLinesOnce sync.Once
)
func (p *importer) qualifiedName() (pkg *types.Package, name string) { func (p *importer) qualifiedName() (pkg *types.Package, name string) {
name = p.string() name = p.string()
pkg = p.pkg() pkg = p.pkg()
...@@ -303,14 +339,14 @@ func (p *importer) typ(parent *types.Package) types.Type { ...@@ -303,14 +339,14 @@ func (p *importer) typ(parent *types.Package) types.Type {
switch i { switch i {
case namedTag: case namedTag:
// read type object // read type object
p.pos() pos := p.pos()
parent, name := p.qualifiedName() parent, name := p.qualifiedName()
scope := parent.Scope() scope := parent.Scope()
obj := scope.Lookup(name) obj := scope.Lookup(name)
// if the object doesn't exist yet, create and insert it // if the object doesn't exist yet, create and insert it
if obj == nil { if obj == nil {
obj = types.NewTypeName(token.NoPos, parent, name, nil) obj = types.NewTypeName(pos, parent, name, nil)
scope.Insert(obj) scope.Insert(obj)
} }
...@@ -336,7 +372,7 @@ func (p *importer) typ(parent *types.Package) types.Type { ...@@ -336,7 +372,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
// read associated methods // read associated methods
for i := p.int(); i > 0; i-- { for i := p.int(); i > 0; i-- {
// TODO(gri) replace this with something closer to fieldName // TODO(gri) replace this with something closer to fieldName
p.pos() pos := p.pos()
name := p.string() name := p.string()
if !exported(name) { if !exported(name) {
p.pkg() p.pkg()
...@@ -348,7 +384,7 @@ func (p *importer) typ(parent *types.Package) types.Type { ...@@ -348,7 +384,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
p.int() // go:nointerface pragma - discarded p.int() // go:nointerface pragma - discarded
sig := types.NewSignature(recv.At(0), params, result, isddd) sig := types.NewSignature(recv.At(0), params, result, isddd)
t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) t0.AddMethod(types.NewFunc(pos, parent, name, sig))
} }
return t return t
...@@ -483,7 +519,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [ ...@@ -483,7 +519,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [
} }
func (p *importer) field(parent *types.Package) *types.Var { func (p *importer) field(parent *types.Package) *types.Var {
p.pos() pos := p.pos()
pkg, name := p.fieldName(parent) pkg, name := p.fieldName(parent)
typ := p.typ(parent) typ := p.typ(parent)
...@@ -502,7 +538,7 @@ func (p *importer) field(parent *types.Package) *types.Var { ...@@ -502,7 +538,7 @@ func (p *importer) field(parent *types.Package) *types.Var {
anonymous = true anonymous = true
} }
return types.NewField(token.NoPos, pkg, name, typ, anonymous) return types.NewField(pos, pkg, name, typ, anonymous)
} }
func (p *importer) methodList(parent *types.Package) (methods []*types.Func) { func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
...@@ -516,12 +552,12 @@ func (p *importer) methodList(parent *types.Package) (methods []*types.Func) { ...@@ -516,12 +552,12 @@ func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
} }
func (p *importer) method(parent *types.Package) *types.Func { func (p *importer) method(parent *types.Package) *types.Func {
p.pos() pos := p.pos()
pkg, name := p.fieldName(parent) pkg, name := p.fieldName(parent)
params, isddd := p.paramList() params, isddd := p.paramList()
result, _ := p.paramList() result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd) sig := types.NewSignature(nil, params, result, isddd)
return types.NewFunc(token.NoPos, pkg, name, sig) return types.NewFunc(pos, pkg, name, sig)
} }
func (p *importer) fieldName(parent *types.Package) (*types.Package, string) { func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
...@@ -613,6 +649,8 @@ func (p *importer) value() constant.Value { ...@@ -613,6 +649,8 @@ func (p *importer) value() constant.Value {
return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
case stringTag: case stringTag:
return constant.MakeString(p.string()) return constant.MakeString(p.string())
case unknownTag:
return constant.MakeUnknown()
default: default:
errorf("unexpected value tag %d", tag) errorf("unexpected value tag %d", tag)
panic("unreachable") panic("unreachable")
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"go/build" "go/build"
"go/token"
"go/types" "go/types"
"io/ioutil" "io/ioutil"
"os" "os"
...@@ -123,7 +124,10 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types ...@@ -123,7 +124,10 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
var data []byte var data []byte
data, err = ioutil.ReadAll(buf) data, err = ioutil.ReadAll(buf)
if err == nil { if err == nil {
_, pkg, err = BImportData(packages, data, id) // TODO(gri): allow clients of go/importer to provide a FileSet.
// Or, define a new standard go/types/gcexportdata package.
fset := token.NewFileSet()
_, pkg, err = BImportData(fset, packages, data, id)
return return
} }
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment