// TestVeryLongFile tests the position of an import object declared in // a very long input file. Line numbers greater than maxlines are // reported as line 1, not garbage or token.NoPos. func TestVeryLongFile(t *testing.T) { // parse and typecheck longFile := "package foo" + strings.Repeat("\n", 123456) + "var X int" fset1 := token.NewFileSet() f, err := parser.ParseFile(fset1, "foo.go", longFile, 0) if err != nil { t.Fatal(err) } var conf types.Config pkg, err := conf.Check("foo", fset1, []*ast.File{f}, nil) if err != nil { t.Fatal(err) } // 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) } // compare posn1 := fset1.Position(pkg.Scope().Lookup("X").Pos()) posn2 := fset2.Position(pkg2.Scope().Lookup("X").Pos()) if want := "foo.go:1:1"; posn2.String() != want { t.Errorf("X position = %s, want %s (orig was %s)", posn2, want, posn1) } }
// Read reads export data from in, decodes it, and returns type // information for the package. // The package name is specified by path. // File position information is added to fset. // // Read may inspect and add to the imports map to ensure that references // within the export data to other packages are consistent. The caller // must ensure that imports[path] does not exist, or exists but is // incomplete (see types.Package.Complete), and Read inserts the // resulting package into this map entry. // // On return, the state of the reader is undefined. func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) { data, err := ioutil.ReadAll(in) if err != nil { return nil, fmt.Errorf("reading export data for %q: %v", path, err) } // The App Engine Go runtime v1.6 uses the old export data format. // TODO(adonovan): delete once v1.7 has been around for a while. if bytes.HasPrefix(data, []byte("package ")) { return gcimporter.ImportData(imports, path, path, bytes.NewReader(data)) } _, pkg, err := gcimporter.BImportData(fset, imports, data, path) return pkg, err }
func disabledTestInvalidAlias(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()) } }
func TestBExportData_stdlib(t *testing.T) { if runtime.GOOS == "android" { t.Skipf("incomplete std lib on %s", runtime.GOOS) } // Load, parse and type-check the program. ctxt := build.Default // copy ctxt.GOPATH = "" // disable GOPATH conf := loader.Config{ Build: &ctxt, AllowErrors: true, } for _, path := range buildutil.AllPackages(conf.Build) { conf.Import(path) } // Create a package containing type and value errors to ensure // they are properly encoded/decoded. f, err := conf.ParseFile("haserrors/haserrors.go", `package haserrors const UnknownValue = "" + 0 type UnknownType undefined `) if err != nil { t.Fatal(err) } conf.CreateFromFiles("haserrors", f) prog, err := conf.Load() if err != nil { t.Fatalf("Load failed: %v", err) } numPkgs := len(prog.AllPackages) if want := 248; numPkgs < want { t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want) } for pkg, info := range prog.AllPackages { if info.Files == nil { continue // empty directory } exportdata := gcimporter.BExportData(conf.Fset, pkg) imports := make(map[string]*types.Package) fset2 := token.NewFileSet() n, pkg2, err := gcimporter.BImportData(fset2, imports, exportdata, pkg.Path()) if err != nil { t.Errorf("BImportData(%s): %v", pkg.Path(), err) continue } if n != len(exportdata) { t.Errorf("BImportData(%s) decoded %d bytes, want %d", pkg.Path(), n, len(exportdata)) } // Compare the packages' corresponding members. for _, name := range pkg.Scope().Names() { if !ast.IsExported(name) { continue } obj1 := pkg.Scope().Lookup(name) obj2 := pkg2.Scope().Lookup(name) if obj2 == nil { t.Errorf("%s.%s not found, want %s", pkg.Path(), name, obj1) continue } fl1 := fileLine(conf.Fset, obj1) fl2 := fileLine(fset2, obj2) if fl1 != fl2 { t.Errorf("%s.%s: got posn %s, want %s", pkg.Path(), name, fl2, fl1) } if err := equalObj(obj1, obj2); err != nil { t.Errorf("%s.%s: %s\ngot: %s\nwant: %s", pkg.Path(), name, err, obj2, obj1) } } } }