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>
This commit is contained in:
Alan Donovan 2023-10-11 17:52:55 -04:00 коммит произвёл Gopher Robot
Родитель d9923f6970
Коммит 1d6d2400d4
8 изменённых файлов: 161 добавлений и 141 удалений

8
go.mod
Просмотреть файл

@ -2,6 +2,10 @@ module golang.org/x/example
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
)

32
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=

Просмотреть файл

@ -86,7 +86,7 @@ constant expressions, as we'll see in
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 @@ programs.
```
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 @@ ran a `go install` or `go build -i` command.
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 @@ Here's an example:
```
$ ./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 @@ The methods should behave the same as those on an *os.File.
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 @@ program starting from the single package, `pkgpath`:
```
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 @@ The rest of the program prints the output:
// 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 @@ helper function
[`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

Просмотреть файл

@ -4,12 +4,11 @@ package main
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 @@ func main() {
//!+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 @@ func main() {
// 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

3
gotypes/gen.go Normal file
Просмотреть файл

@ -0,0 +1,3 @@
//go:generate bash -c "go run ../internal/cmd/weave/weave.go ./go-types.md > README.md"
package gotypes

Просмотреть файл

@ -62,7 +62,7 @@ constant expressions, as we'll see in
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 @@ ran a `go install` or `go build -i` command.
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 @@ Here's an example:
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 @@ helper function
[`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

Просмотреть файл

@ -12,20 +12,19 @@ import (
"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 PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
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)
}
}

Просмотреть файл

@ -20,7 +20,7 @@ import (
"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 @@ func main() {
}
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)
}
}