mirror of
https://github.com/golang/go
synced 2024-11-18 11:55:01 -07:00
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/22936 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
d08c3d1329
commit
1da1da3d6a
@ -13,6 +13,7 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
@ -34,6 +35,8 @@ type importer struct {
|
||||
posInfoFormat bool
|
||||
prevFile string
|
||||
prevLine int
|
||||
fset *token.FileSet
|
||||
files map[string]*token.File
|
||||
|
||||
// debugging support
|
||||
debugFormat bool
|
||||
@ -44,7 +47,7 @@ type importer struct {
|
||||
// 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
|
||||
// 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
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
@ -60,6 +63,8 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (_
|
||||
path: path,
|
||||
version: -1, // unknown version
|
||||
strList: []string{""}, // empty string is mapped to 0
|
||||
fset: fset,
|
||||
files: make(map[string]*token.File),
|
||||
}
|
||||
|
||||
// read version info
|
||||
@ -219,37 +224,37 @@ func (p *importer) declare(obj types.Object) {
|
||||
func (p *importer) obj(tag int) {
|
||||
switch tag {
|
||||
case constTag:
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil)
|
||||
val := p.value()
|
||||
p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
|
||||
p.declare(types.NewConst(pos, pkg, name, typ, val))
|
||||
|
||||
case typeTag:
|
||||
_ = p.typ(nil)
|
||||
|
||||
case varTag:
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil)
|
||||
p.declare(types.NewVar(token.NoPos, pkg, name, typ))
|
||||
p.declare(types.NewVar(pos, pkg, name, typ))
|
||||
|
||||
case funcTag:
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
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:
|
||||
errorf("unexpected object tag %d", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) pos() {
|
||||
func (p *importer) pos() token.Pos {
|
||||
if !p.posInfoFormat {
|
||||
return
|
||||
return token.NoPos
|
||||
}
|
||||
|
||||
file := p.prevFile
|
||||
@ -265,9 +270,40 @@ func (p *importer) pos() {
|
||||
}
|
||||
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) {
|
||||
name = p.string()
|
||||
pkg = p.pkg()
|
||||
@ -303,14 +339,14 @@ func (p *importer) typ(parent *types.Package) types.Type {
|
||||
switch i {
|
||||
case namedTag:
|
||||
// read type object
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
parent, name := p.qualifiedName()
|
||||
scope := parent.Scope()
|
||||
obj := scope.Lookup(name)
|
||||
|
||||
// if the object doesn't exist yet, create and insert it
|
||||
if obj == nil {
|
||||
obj = types.NewTypeName(token.NoPos, parent, name, nil)
|
||||
obj = types.NewTypeName(pos, parent, name, nil)
|
||||
scope.Insert(obj)
|
||||
}
|
||||
|
||||
@ -336,7 +372,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
|
||||
// read associated methods
|
||||
for i := p.int(); i > 0; i-- {
|
||||
// TODO(gri) replace this with something closer to fieldName
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
name := p.string()
|
||||
if !exported(name) {
|
||||
p.pkg()
|
||||
@ -348,7 +384,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
|
||||
p.int() // go:nointerface pragma - discarded
|
||||
|
||||
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
|
||||
@ -483,7 +519,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [
|
||||
}
|
||||
|
||||
func (p *importer) field(parent *types.Package) *types.Var {
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
pkg, name := p.fieldName(parent)
|
||||
typ := p.typ(parent)
|
||||
|
||||
@ -502,7 +538,7 @@ func (p *importer) field(parent *types.Package) *types.Var {
|
||||
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) {
|
||||
@ -516,12 +552,12 @@ func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
|
||||
}
|
||||
|
||||
func (p *importer) method(parent *types.Package) *types.Func {
|
||||
p.pos()
|
||||
pos := p.pos()
|
||||
pkg, name := p.fieldName(parent)
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
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) {
|
||||
@ -613,6 +649,8 @@ func (p *importer) value() constant.Value {
|
||||
return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
|
||||
case stringTag:
|
||||
return constant.MakeString(p.string())
|
||||
case unknownTag:
|
||||
return constant.MakeUnknown()
|
||||
default:
|
||||
errorf("unexpected value tag %d", tag)
|
||||
panic("unreachable")
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -123,7 +124,10 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
|
||||
var data []byte
|
||||
data, err = ioutil.ReadAll(buf)
|
||||
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
|
||||
}
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user