]> Cypherpunks repositories - gostls13.git/commitdiff
go/internal/gcimporter: set Pos attribute of decoded types.Objects
authorAlan Donovan <adonovan@google.com>
Mon, 9 May 2016 13:40:27 +0000 (09:40 -0400)
committerAlan Donovan <adonovan@google.com>
Thu, 13 Oct 2016 19:31:09 +0000 (19:31 +0000)
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>
src/go/internal/gcimporter/bimport.go
src/go/internal/gcimporter/gcimporter.go

index 2a8b98b66fe3eb33f16f78638e24de496016d345..ad28ef7735e3b2504c8cd379e159d8a865efbfd7 100644 (file)
@@ -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")
index 1e1102a451e1179fc5cb221262d8106c2076010b..f99f0f8befeec89b61755d48a5f79e180cc18455 100644 (file)
@@ -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: