Skip to content

Commit 1d6d240

Browse files
adonovangopherbot
authored andcommitted
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>
1 parent d9923f6 commit 1d6d240

File tree

8 files changed

+163
-143
lines changed

8 files changed

+163
-143
lines changed

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ module golang.org/x/example
22

33
go 1.18
44

5-
require golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0
5+
require golang.org/x/tools v0.14.0
66

7-
require gopkg.in/yaml.v3 v3.0.1 // indirect
7+
require (
8+
golang.org/x/mod v0.13.0 // indirect
9+
golang.org/x/sys v0.13.0 // indirect
10+
gopkg.in/yaml.v3 v3.0.1
11+
)

go.sum

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
1-
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
2-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
3-
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
4-
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
5-
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
6-
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
7-
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
8-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
9-
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
10-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
11-
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
12-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
13-
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
14-
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
15-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
16-
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
17-
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
18-
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
19-
golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0 h1:iZhiQWrjyEuXG495d9MXkcmhrlxbQyGp0uNBY+YBZDk=
20-
golang.org/x/tools v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
21-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
22-
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
23-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
24-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1+
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
2+
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
3+
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
4+
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
5+
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6+
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
7+
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
8+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
259
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2610
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2711
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

gotypes/README.md

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ constant expressions, as we'll see in
8686

8787

8888

89-
The [`golang.org/x/tools/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
89+
The [`golang.org/x/tools/go/packages` package](https://pkg.go.dev/golang.org/x/tools/go/packages)
9090
from the `x/tools` repository is a client of the type
9191
checker that loads, parses, and type-checks a complete Go program from
9292
source code.
@@ -2190,13 +2190,11 @@ programs.
21902190
```
21912191
var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
21922192
2193-
var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
2194-
2195-
func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
2193+
func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
21962194
checkTuple := func(descr string, tuple *types.Tuple) {
21972195
for i := 0; i < tuple.Len(); i++ {
21982196
v := tuple.At(i)
2199-
if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
2197+
if sz := sizes.Sizeof(v.Type()); sz > int64(*bytesFlag) {
22002198
fmt.Printf("%s: %q %s: %s = %d bytes\n",
22012199
fset.Position(v.Pos()),
22022200
v.Name(), descr, v.Type(), sz)
@@ -2296,25 +2294,28 @@ ran a `go install` or `go build -i` command.
22962294

22972295

22982296

2299-
The [`golang.org/tools/x/go/loader` package](https://pkg.go.dev/golang.org/x/tools/go/loader)
2300-
provides an alternative `Importer` that addresses
2301-
some of these problems.
2302-
It loads a complete program from source, performing
2303-
[`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if
2304-
necessary, followed by parsing and type-checking.
2297+
The [`golang.org/tools/x/go/packages`
2298+
package](https://pkg.go.dev/golang.org/x/tools/go/packages) provides
2299+
a comprehensive means of loading packages from source.
2300+
It runs `go list` to query the project metadata,
2301+
performs [`cgo`](https://golang.org/cmd/cgo/cgo) preprocessing if necessary,
2302+
reads and parses the source files,
2303+
and optionally type-checks each package.
2304+
It can load a whole program from source, or load just the initial
2305+
packages from source and load all their dependencies from export data.
23052306
It loads independent packages in parallel to hide I/O latency, and
23062307
detects and reports import cycles.
23072308
For each package, it provides the `types.Package` containing the
23082309
package's lexical environment, the list of `ast.File` syntax
23092310
trees for each file in the package, the `types.Info` containing
2310-
type information for each syntax node, and a list of type errors
2311-
associated with that package.
2312-
(Please be aware that the `go/loader` package's API is likely to
2313-
change before it finally stabilizes.)
2314-
2315-
2316-
2317-
The `doc` program below demonstrates a simple use of the loader.
2311+
type information for each syntax node, a list of type errors
2312+
associated with that package, and other information too.
2313+
Since some of this information is more costly to compute,
2314+
the API allows you to select which parts you need,
2315+
but since this is a tutorial we'll generally request complete
2316+
information so that it is easier to explore.
2317+
2318+
The `doc` program below demonstrates a simple use of `go/packages`.
23182319
It is a rudimentary implementation of `go doc` that prints the type,
23192320
methods, and documentation of the package-level object specified on
23202321
the command line.
@@ -2324,10 +2325,10 @@ Here's an example:
23242325
```
23252326
$ ./doc net/http File
23262327
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}
2327-
/go/src/io/io.go:92:2: method (net/http.File) Close() error
2328-
/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
2328+
$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
2329+
$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
23292330
/go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
2330-
/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
2331+
$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
23312332
/go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
23322333
23332334
A File is returned by a FileSystem's Open method and can be
@@ -2340,33 +2341,39 @@ The methods should behave the same as those on an *os.File.
23402341
Observe that it prints the correct location of each method
23412342
declaration, even though, due to embedding, some of
23422343
`http.File`'s methods were declared in another package.
2343-
Here's the first part of the program, showing how to load an entire
2344-
program starting from the single package, `pkgpath`:
2344+
Here's the first part of the program, showing how to load
2345+
complete type information including typed syntax,
2346+
for a single package `pkgpath`,
2347+
plus exported type information for its dependencies.
23452348

23462349

23472350
// go get golang.org/x/example/gotypes/doc
23482351

23492352
```
23502353
pkgpath, name := os.Args[1], os.Args[2]
23512354
2352-
// The loader loads a complete Go program from source code.
2353-
conf := loader.Config{ParserMode: parser.ParseComments}
2354-
conf.Import(pkgpath)
2355-
lprog, err := conf.Load()
2355+
// Load complete type information for the specified packages,
2356+
// along with type-annotated syntax.
2357+
// Types for dependencies are loaded from export data.
2358+
conf := &packages.Config{Mode: packages.LoadSyntax}
2359+
pkgs, err := packages.Load(conf, pkgpath)
23562360
if err != nil {
2357-
log.Fatal(err) // load error
2361+
log.Fatal(err) // failed to load anything
2362+
}
2363+
if packages.PrintErrors(pkgs) > 0 {
2364+
os.Exit(1) // some packages contained errors
23582365
}
23592366
23602367
// Find the package and package-level object.
2361-
pkg := lprog.Package(pkgpath).Pkg
2362-
obj := pkg.Scope().Lookup(name)
2368+
pkg := pkgs[0]
2369+
obj := pkg.Types.Scope().Lookup(name)
23632370
if obj == nil {
2364-
log.Fatalf("%s.%s not found", pkg.Path(), name)
2371+
log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
23652372
}
23662373
```
23672374

23682375

2369-
Notice that we instructed the parser to retain comments during parsing.
2376+
By default, `go/packages`, instructs the parser to retain comments during parsing.
23702377
The rest of the program prints the output:
23712378

23722379

@@ -2376,20 +2383,26 @@ The rest of the program prints the output:
23762383
// Print the object and its methods (incl. location of definition).
23772384
fmt.Println(obj)
23782385
for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
2379-
fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
2386+
fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
23802387
}
23812388
23822389
// Find the path from the root of the AST to the object's position.
23832390
// Walk up to the enclosing ast.Decl for the doc comment.
2384-
_, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
2385-
for _, n := range path {
2386-
switch n := n.(type) {
2387-
case *ast.GenDecl:
2388-
fmt.Println("\n", n.Doc.Text())
2389-
return
2390-
case *ast.FuncDecl:
2391-
fmt.Println("\n", n.Doc.Text())
2392-
return
2391+
for _, file := range pkg.Syntax {
2392+
pos := obj.Pos()
2393+
if !(file.FileStart <= pos && pos < file.FileEnd) {
2394+
continue // not in this file
2395+
}
2396+
path, _ := astutil.PathEnclosingInterval(file, pos, pos)
2397+
for _, n := range path {
2398+
switch n := n.(type) {
2399+
case *ast.GenDecl:
2400+
fmt.Println("\n", n.Doc.Text())
2401+
return
2402+
case *ast.FuncDecl:
2403+
fmt.Println("\n", n.Doc.Text())
2404+
return
2405+
}
23932406
}
23942407
}
23952408
```
@@ -2535,11 +2548,10 @@ helper function
25352548
[`astutil.PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/ast/astutil#PathEnclosingInterval).
25362549
It returns the enclosing `ast.Node`, and all its ancestors up to
25372550
the root of the file.
2538-
You must know which file `*ast.File` the `token.Pos` belongs to.
2539-
Alternatively, you can search an entire program loaded by the
2540-
`loader` package, using
2541-
[`(*loader.Program).PathEnclosingInterval`](https://pkg.go.dev/golang.org/x/tools/go/loader#Program.PathEnclosingInterval).
2542-
2551+
If you don't know which file `*ast.File` the `token.Pos` belongs to,
2552+
you can iterate over the parsed files of the package and quickly test
2553+
whether its position falls within the file's range,
2554+
from `File.FileStart` to `File.FileEnd`.
25432555

25442556

25452557
To map **from an `Object` to its declaring syntax**, call

gotypes/doc/main.go

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ package main
44
import (
55
"fmt"
66
"go/ast"
7-
"go/parser"
87
"log"
98
"os"
109

11-
// TODO: these will use std go/types after Feb 2016
12-
"golang.org/x/tools/go/loader"
10+
"golang.org/x/tools/go/ast/astutil"
11+
"golang.org/x/tools/go/packages"
1312
"golang.org/x/tools/go/types/typeutil"
1413
)
1514

@@ -20,53 +19,66 @@ func main() {
2019
//!+part1
2120
pkgpath, name := os.Args[1], os.Args[2]
2221

23-
// The loader loads a complete Go program from source code.
24-
conf := loader.Config{ParserMode: parser.ParseComments}
25-
conf.Import(pkgpath)
26-
lprog, err := conf.Load()
22+
// Load complete type information for the specified packages,
23+
// along with type-annotated syntax.
24+
// Types for dependencies are loaded from export data.
25+
conf := &packages.Config{Mode: packages.LoadSyntax}
26+
pkgs, err := packages.Load(conf, pkgpath)
2727
if err != nil {
28-
log.Fatal(err) // load error
28+
log.Fatal(err) // failed to load anything
29+
}
30+
if packages.PrintErrors(pkgs) > 0 {
31+
os.Exit(1) // some packages contained errors
2932
}
3033

3134
// Find the package and package-level object.
32-
pkg := lprog.Package(pkgpath).Pkg
33-
obj := pkg.Scope().Lookup(name)
35+
pkg := pkgs[0]
36+
obj := pkg.Types.Scope().Lookup(name)
3437
if obj == nil {
35-
log.Fatalf("%s.%s not found", pkg.Path(), name)
38+
log.Fatalf("%s.%s not found", pkg.Types.Path(), name)
3639
}
3740
//!-part1
3841
//!+part2
3942

4043
// Print the object and its methods (incl. location of definition).
4144
fmt.Println(obj)
4245
for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
43-
fmt.Printf("%s: %s\n", lprog.Fset.Position(sel.Obj().Pos()), sel)
46+
fmt.Printf("%s: %s\n", pkg.Fset.Position(sel.Obj().Pos()), sel)
4447
}
4548

4649
// Find the path from the root of the AST to the object's position.
4750
// Walk up to the enclosing ast.Decl for the doc comment.
48-
_, path, _ := lprog.PathEnclosingInterval(obj.Pos(), obj.Pos())
49-
for _, n := range path {
50-
switch n := n.(type) {
51-
case *ast.GenDecl:
52-
fmt.Println("\n", n.Doc.Text())
53-
return
54-
case *ast.FuncDecl:
55-
fmt.Println("\n", n.Doc.Text())
56-
return
51+
for _, file := range pkg.Syntax {
52+
pos := obj.Pos()
53+
if !(file.FileStart <= pos && pos < file.FileEnd) {
54+
continue // not in this file
55+
}
56+
path, _ := astutil.PathEnclosingInterval(file, pos, pos)
57+
for _, n := range path {
58+
switch n := n.(type) {
59+
case *ast.GenDecl:
60+
fmt.Println("\n", n.Doc.Text())
61+
return
62+
case *ast.FuncDecl:
63+
fmt.Println("\n", n.Doc.Text())
64+
return
65+
}
5766
}
5867
}
5968
//!-part2
6069
}
6170

71+
// (The $GOROOT below is the actual string that appears in file names
72+
// loaded from export data for packages in the standard library.)
73+
6274
/*
6375
//!+output
6476
$ ./doc net/http File
6577
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}
66-
/go/src/io/io.go:92:2: method (net/http.File) Close() error
67-
/go/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
78+
$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
79+
$GOROOT/src/io/io.go:71:2: method (net/http.File) Read(p []byte) (n int, err error)
6880
/go/src/net/http/fs.go:65:2: method (net/http.File) Readdir(count int) ([]os.FileInfo, error)
69-
/go/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
81+
$GOROOT/src/net/http/fs.go:66:2: method (net/http.File) Seek(offset int64, whence int) (int64, error)
7082
/go/src/net/http/fs.go:67:2: method (net/http.File) Stat() (os.FileInfo, error)
7183
7284
A File is returned by a FileSystem's Open method and can be

gotypes/gen.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//go:generate bash -c "go run ../internal/cmd/weave/weave.go ./go-types.md > README.md"
2+
3+
package gotypes

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy