gotypes: stop directing people to golang.org/x/tools/go/loader
It is very obsolete. Use go/packages instead.
Also, add a go generate command to weave the README.
Fixes golang/go#60593
Change-Id: Ifaf3ffa588dc3e65fb1e96b39b249a9084d66451
Reviewed-on: https://go-review.googlesource.com/c/example/+/534695
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Commit-Queue: Alan Donovan <adonovan@google.com>
diff --git a/go.mod b/go.mod
index 1996732..e876fb9 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,10 @@
go 1.18
-require golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0
+require golang.org/x/tools v0.14.0
-require gopkg.in/yaml.v3 v3.0.1 // indirect
+require (
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1
+)
diff --git a/go.sum b/go.sum
index 114d0dc..25e95bd 100644
--- a/go.sum
+++ b/go.sum
@@ -1,27 +1,11 @@
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0 h1:iZhiQWrjyEuXG495d9MXkcmhrlxbQyGp0uNBY+YBZDk=
-golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/gotypes/README.md b/gotypes/README.md
index ee12bef..9923e10 100644
--- a/gotypes/README.md
+++ b/gotypes/README.md
@@ -86,7 +86,7 @@
-The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
+The [`golang.org/x/tools/go/packages` package](https://pkg.go.dev/golang.org/x/tools/go/packages)
from the `x/tools` repository is a client of the type
checker that loads, parses, and type-checks a complete Go program from
source code.
@@ -2190,13 +2190,11 @@
```
var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
-var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
-
-func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
+func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
checkTuple := func(descr string, tuple *types.Tuple) {
for i := 0; i < tuple.Len(); i++ {
v := tuple.At(i)
- if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
+ if sz := sizes.Sizeof(v.Type()); sz > int64(*bytesFlag) {
fmt.Printf("%s: %q %s: %s = %d bytes\n",
fset.Position(v.Pos()),
v.Name(), descr, v.Type(), sz)
@@ -2296,25 +2294,28 @@
-The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
-provides an alternative `Importer` that addresses
-some of these problems.
-It loads a complete program from source, performing
-[`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
-necessary, followed by parsing and type-checking.
+The [`golang.org/tools/x/go/packages`
+package](https://pkg.go.dev/golang.org/x/tools/go/packages) provides
+a comprehensive means of loading packages from source.
+It runs `go list` to query the project metadata,
+performs [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if necessary,
+reads and parses the source files,
+and optionally type-checks each package.
+It can load a whole program from source, or load just the initial
+packages from source and load all their dependencies from export data.
It loads independent packages in parallel to hide I/O latency, and
detects and reports import cycles.
For each package, it provides the `types.Package` containing the
package's lexical environment, the list of `ast.File` syntax
trees for each file in the package, the `types.Info` containing
-type information for each syntax node, and a list of type errors
-associated with that package.
-(Please be aware that the `go/loader` package's API is likely to
-change before it finally stabilizes.)
+type information for each syntax node, a list of type errors
+associated with that package, and other information too.
+Since some of this information is more costly to compute,
+the API allows you to select which parts you need,
+but since this is a tutorial we'll generally request complete
+information so that it is easier to explore.
-
-
-The `doc` program below demonstrates a simple use of the loader.
+The `doc` program below demonstrates a simple use of `go/packages`.
It is a rudimentary implementation of `go doc` that prints the type,
methods, and documentation of the package-level object specified on
the command line.
@@ -2324,10 +2325,10 @@
```
$ ./doc net/http File
type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
-/go/src/io/io.go:92:2: method (net/http.File) Close() error
-/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
+$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
+$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
/go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
-/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
+$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
/go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
A File is returned by a FileSystem's Open method and can be
@@ -2340,8 +2341,10 @@
Observe that it prints the correct location of each method
declaration, even though, due to embedding, some of
`http.File`'s methods were declared in another package.
-Here's the first part of the program, showing how to load an entire
-program starting from the single package, `pkgpath`:
+Here's the first part of the program, showing how to load
+complete type information including typed syntax,
+for a single package `pkgpath`,
+plus exported type information for its dependencies.
// go get golang.org/x/example/gotypes/doc
@@ -2349,24 +2352,28 @@
```
pkgpath, name := os.Args[1], os.Args[2]
-// The loader loads a complete Go program from source code.
-conf := loader.Config{ParserMode: parser.ParseComments}
-conf.Import(pkgpath)
-lprog, err := conf.Load()
+// Load complete type information for the specified packages,
+// along with type-annotated syntax.
+// Types for dependencies are loaded from export data.
+conf := &packages.Config{Mode: packages.LoadSyntax}
+pkgs, err := packages.Load(conf, pkgpath)
if err != nil {
- log.Fatal(err) // load error
+ log.Fatal(err) // failed to load anything
+}
+if packages.PrintErrors(pkgs) > 0 {
+ os.Exit(1) // some packages contained errors
}
// Find the package and package-level object.
-pkg := lprog.Package(pkgpath).Pkg
-obj := pkg.Scope().Lookup(name)
+pkg := pkgs[0]
+obj := pkg.Types.Scope().Lookup(name)
if obj == nil {
- log.Fatalf("%s.%s not found", pkg.Path(), name)
+ log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
}
```
-Notice that we instructed the parser to retain comments during parsing.
+By default, `go/packages`, instructs the parser to retain comments during parsing.
The rest of the program prints the output:
@@ -2376,20 +2383,26 @@
// Print the object and its methods (incl. location of definition).
fmt.Println(obj)
for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
- fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
+ fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
}
// Find the path from the root of the AST to the object's position.
// Walk up to the enclosing ast.Decl for the doc comment.
-_, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
-for _, n := range path {
- switch n := n.(type) {
- case *ast.GenDecl:
- fmt.Println("\n", n.Doc.Text())
- return
- case *ast.FuncDecl:
- fmt.Println("\n", n.Doc.Text())
- return
+for _, file := range pkg.Syntax {
+ pos := obj.Pos()
+ if !(file.FileStart <= pos && pos < file.FileEnd) {
+ continue // not in this file
+ }
+ path, _ := astutil.PathEnclosingInterval(file, pos, pos)
+ for _, n := range path {
+ switch n := n.(type) {
+ case *ast.GenDecl:
+ fmt.Println("\n", n.Doc.Text())
+ return
+ case *ast.FuncDecl:
+ fmt.Println("\n", n.Doc.Text())
+ return
+ }
}
}
```
@@ -2535,11 +2548,10 @@
[`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
It returns the enclosing `ast.Node`, and all its ancestors up to
the root of the file.
-You must know which file `*ast.File` the `token.Pos` belongs to.
-Alternatively, you can search an entire program loaded by the
-`loader` package, using
-[`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
-
+If you don't know which file `*ast.File` the `token.Pos` belongs to,
+you can iterate over the parsed files of the package and quickly test
+whether its position falls within the file's range,
+from `File.FileStart` to `File.FileEnd`.
To map **from an `Object` to its declaring syntax**, call
diff --git a/gotypes/doc/main.go b/gotypes/doc/main.go
index 3140f47..8e7027f 100644
--- a/gotypes/doc/main.go
+++ b/gotypes/doc/main.go
@@ -4,12 +4,11 @@
import (
"fmt"
"go/ast"
- "go/parser"
"log"
"os"
- // TODO: these will use std go/types after Feb 2016
- "golang.org/x/tools/go/loader"
+ "golang.org/x/tools/go/ast/astutil"
+ "golang.org/x/tools/go/packages"
"golang.org/x/tools/go/types/typeutil"
)
@@ -20,19 +19,23 @@
//!+part1
pkgpath, name := os.Args[1], os.Args[2]
- // The loader loads a complete Go program from source code.
- conf := loader.Config{ParserMode: parser.ParseComments}
- conf.Import(pkgpath)
- lprog, err := conf.Load()
+ // Load complete type information for the specified packages,
+ // along with type-annotated syntax.
+ // Types for dependencies are loaded from export data.
+ conf := &packages.Config{Mode: packages.LoadSyntax}
+ pkgs, err := packages.Load(conf, pkgpath)
if err != nil {
- log.Fatal(err) // load error
+ log.Fatal(err) // failed to load anything
+ }
+ if packages.PrintErrors(pkgs) > 0 {
+ os.Exit(1) // some packages contained errors
}
// Find the package and package-level object.
- pkg := lprog.Package(pkgpath).Pkg
- obj := pkg.Scope().Lookup(name)
+ pkg := pkgs[0]
+ obj := pkg.Types.Scope().Lookup(name)
if obj == nil {
- log.Fatalf("%s.%s not found", pkg.Path(), name)
+ log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
}
//!-part1
//!+part2
@@ -40,33 +43,42 @@
// Print the object and its methods (incl. location of definition).
fmt.Println(obj)
for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
- fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
+ fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
}
// Find the path from the root of the AST to the object's position.
// Walk up to the enclosing ast.Decl for the doc comment.
- _, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
- for _, n := range path {
- switch n := n.(type) {
- case *ast.GenDecl:
- fmt.Println("\n", n.Doc.Text())
- return
- case *ast.FuncDecl:
- fmt.Println("\n", n.Doc.Text())
- return
+ for _, file := range pkg.Syntax {
+ pos := obj.Pos()
+ if !(file.FileStart <= pos && pos < file.FileEnd) {
+ continue // not in this file
+ }
+ path, _ := astutil.PathEnclosingInterval(file, pos, pos)
+ for _, n := range path {
+ switch n := n.(type) {
+ case *ast.GenDecl:
+ fmt.Println("\n", n.Doc.Text())
+ return
+ case *ast.FuncDecl:
+ fmt.Println("\n", n.Doc.Text())
+ return
+ }
}
}
//!-part2
}
+// (The $GOROOT below is the actual string that appears in file names
+// loaded from export data for packages in the standard library.)
+
/*
//!+output
$ ./doc net/http File
type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
-/go/src/io/io.go:92:2: method (net/http.File) Close() error
-/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
+$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
+$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
/go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
-/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
+$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
/go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
A File is returned by a FileSystem's Open method and can be
diff --git a/gotypes/gen.go b/gotypes/gen.go
new file mode 100644
index 0000000..bce6efe
--- /dev/null
+++ b/gotypes/gen.go
@@ -0,0 +1,3 @@
+//go:generate bash -c "go run ../internal/cmd/weave/weave.go ./go-types.md > README.md"
+
+package gotypes
diff --git a/gotypes/go-types.md b/gotypes/go-types.md
index 4cd3d81..ce5a430 100644
--- a/gotypes/go-types.md
+++ b/gotypes/go-types.md
@@ -62,7 +62,7 @@
-The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
+The [`golang.org/x/tools/go/packages` package](https://pkg.go.dev/golang.org/x/tools/go/packages)
from the `x/tools` repository is a client of the type
checker that loads, parses, and type-checks a complete Go program from
source code.
@@ -1850,25 +1850,28 @@
-The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
-provides an alternative `Importer` that addresses
-some of these problems.
-It loads a complete program from source, performing
-[`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
-necessary, followed by parsing and type-checking.
+The [`golang.org/tools/x/go/packages`
+package](https://pkg.go.dev/golang.org/x/tools/go/packages) provides
+a comprehensive means of loading packages from source.
+It runs `go list` to query the project metadata,
+performs [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if necessary,
+reads and parses the source files,
+and optionally type-checks each package.
+It can load a whole program from source, or load just the initial
+packages from source and load all their dependencies from export data.
It loads independent packages in parallel to hide I/O latency, and
detects and reports import cycles.
For each package, it provides the `types.Package` containing the
package's lexical environment, the list of `ast.File` syntax
trees for each file in the package, the `types.Info` containing
-type information for each syntax node, and a list of type errors
-associated with that package.
-(Please be aware that the `go/loader` package's API is likely to
-change before it finally stabilizes.)
+type information for each syntax node, a list of type errors
+associated with that package, and other information too.
+Since some of this information is more costly to compute,
+the API allows you to select which parts you need,
+but since this is a tutorial we'll generally request complete
+information so that it is easier to explore.
-
-
-The `doc` program below demonstrates a simple use of the loader.
+The `doc` program below demonstrates a simple use of `go/packages`.
It is a rudimentary implementation of `go doc` that prints the type,
methods, and documentation of the package-level object specified on
the command line.
@@ -1881,14 +1884,16 @@
Observe that it prints the correct location of each method
declaration, even though, due to embedding, some of
`http.File`'s methods were declared in another package.
-Here's the first part of the program, showing how to load an entire
-program starting from the single package, `pkgpath`:
+Here's the first part of the program, showing how to load
+complete type information including typed syntax,
+for a single package `pkgpath`,
+plus exported type information for its dependencies.
%include doc/main.go part1
-Notice that we instructed the parser to retain comments during parsing.
+By default, `go/packages`, instructs the parser to retain comments during parsing.
The rest of the program prints the output:
@@ -2035,11 +2040,10 @@
[`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
It returns the enclosing `ast.Node`, and all its ancestors up to
the root of the file.
-You must know which file `*ast.File` the `token.Pos` belongs to.
-Alternatively, you can search an entire program loaded by the
-`loader` package, using
-[`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
-
+If you don't know which file `*ast.File` the `token.Pos` belongs to,
+you can iterate over the parsed files of the package and quickly test
+whether its position falls within the file's range,
+from `File.FileStart` to `File.FileEnd`.
To map **from an `Object` to its declaring syntax**, call
diff --git a/gotypes/hugeparam/main.go b/gotypes/hugeparam/main.go
index 80fc47e..9577a09 100644
--- a/gotypes/hugeparam/main.go
+++ b/gotypes/hugeparam/main.go
@@ -12,20 +12,19 @@
"go/token"
"go/types"
"log"
+ "os"
- "golang.org/x/tools/go/loader"
+ "golang.org/x/tools/go/packages"
)
// !+
var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
-var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
-
-func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
+func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
checkTuple := func(descr string, tuple *types.Tuple) {
for i := 0; i < tuple.Len(); i++ {
v := tuple.At(i)
- if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
+ if sz := sizes.Sizeof(v.Type()); sz > int64(*bytesFlag) {
fmt.Printf("%s: %q %s: %s = %d bytes\n",
fset.Position(v.Pos()),
v.Name(), descr, v.Type(), sz)
@@ -54,19 +53,20 @@
func main() {
flag.Parse()
- // The loader loads a complete Go program from source code.
- var conf loader.Config
- _, err := conf.FromArgs(flag.Args(), false)
+ // Load complete type information for the specified packages,
+ // along with type-annotated syntax and the "sizeof" function.
+ // Types for dependencies are loaded from export data.
+ conf := &packages.Config{Mode: packages.LoadSyntax}
+ pkgs, err := packages.Load(conf, flag.Args()...)
if err != nil {
- log.Fatal(err) // command syntax error
+ log.Fatal(err) // failed to load anything
}
- lprog, err := conf.Load()
- if err != nil {
- log.Fatal(err) // load error
+ if packages.PrintErrors(pkgs) > 0 {
+ os.Exit(1) // some packages contained errors
}
- for _, info := range lprog.InitialPackages() {
- PrintHugeParams(lprog.Fset, &info.Info, info.Files)
+ for _, pkg := range pkgs {
+ PrintHugeParams(pkg.Fset, pkg.TypesInfo, pkg.TypesSizes, pkg.Syntax)
}
}
diff --git a/gotypes/skeleton/main.go b/gotypes/skeleton/main.go
index 1e6ee82..ab79b2c 100644
--- a/gotypes/skeleton/main.go
+++ b/gotypes/skeleton/main.go
@@ -20,7 +20,7 @@
"unicode"
"unicode/utf8"
- "golang.org/x/tools/go/loader"
+ "golang.org/x/tools/go/packages"
)
const usage = "Usage: skeleton <package> <interface> <concrete>"
@@ -76,15 +76,16 @@
}
pkgpath, ifacename, concname := os.Args[1], os.Args[2], os.Args[3]
- // The loader loads a complete Go program from source code.
- var conf loader.Config
- conf.Import(pkgpath)
- lprog, err := conf.Load()
+ // Load only exported type information for the specified package.
+ conf := &packages.Config{Mode: packages.NeedTypes}
+ pkgs, err := packages.Load(conf, pkgpath)
if err != nil {
- log.Fatal(err) // load error
+ log.Fatal(err) // failed to load anything
}
- pkg := lprog.Package(pkgpath).Pkg
- if err := PrintSkeleton(pkg, ifacename, concname); err != nil {
+ if packages.PrintErrors(pkgs) > 0 {
+ os.Exit(1) // some packages contained errors
+ }
+ if err := PrintSkeleton(pkgs[0].Types, ifacename, concname); err != nil {
log.Fatal(err)
}
}