Skip to content

Commit fd68572

Browse files
pjweinbgogopherbot
authored andcommitted
internal/stdlib: find api directory more robustly
stdlib contains precomputed information about exported symbols in the standard library. The old code looked in runtime.GOROOT()/api for this information. This works on many systems, but not always. The new code runs go env, and looks first in GOROOT/api, and failing that, in GOPATH/api. (The situation seems to depend on mysterious details of the history of the user's Go environment.) This CL is on the path to adding function snippets for the standard library, for the new unimported completions code. Change-Id: If2853a3f26edf9d0f1603563104592b95eb466a1 Reviewed-on: https://go-review.googlesource.com/c/tools/+/664995 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Alan Donovan <adonovan@google.com> Commit-Queue: Alan Donovan <adonovan@google.com>
1 parent 7ceff13 commit fd68572

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

internal/stdlib/generate.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,22 @@ import (
2929
"os/exec"
3030
"path/filepath"
3131
"regexp"
32-
"runtime"
3332
"slices"
3433
"strings"
3534

3635
"golang.org/x/tools/go/packages"
3736
)
3837

3938
func main() {
40-
manifest()
39+
log.SetFlags(log.Lshortfile) // to identify the source of the log messages
40+
dir := apidir()
41+
manifest(dir)
4142
deps()
4243
}
4344

4445
// -- generate std manifest --
4546

46-
func manifest() {
47+
func manifest(apidir string) {
4748
pkgs := make(map[string]map[string]symInfo) // package -> symbol -> info
4849
symRE := regexp.MustCompile(`^pkg (\S+).*?, (var|func|type|const|method \([^)]*\)) ([\pL\p{Nd}_]+)(.*)`)
4950

@@ -111,15 +112,15 @@ func manifest() {
111112
if minor > 0 {
112113
base = fmt.Sprintf("go1.%d.txt", minor)
113114
}
114-
filename := filepath.Join(runtime.GOROOT(), "api", base)
115+
filename := filepath.Join(apidir, base)
115116
data, err := os.ReadFile(filename)
116117
if err != nil {
117118
if errors.Is(err, fs.ErrNotExist) {
118119
// All caught up.
119120
// Synthesize one final file from any api/next/*.txt fragments.
120121
// (They are consolidated into a go1.%d file some time between
121122
// the freeze and the first release candidate.)
122-
filenames, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "api/next/*.txt"))
123+
filenames, err := filepath.Glob(filepath.Join(apidir, "next", "*.txt"))
123124
if err != nil {
124125
log.Fatal(err)
125126
}
@@ -177,6 +178,28 @@ var PackageSymbols = map[string][]Symbol{
177178
}
178179
}
179180

181+
// find the api directory, In most situations it is in GOROOT/api, but not always.
182+
// TODO(pjw): understand where it might be, and if there could be newer and older versions
183+
func apidir() string {
184+
stdout := new(bytes.Buffer)
185+
cmd := exec.Command("go", "env", "GOROOT", "GOPATH")
186+
cmd.Stdout = stdout
187+
cmd.Stderr = os.Stderr
188+
if err := cmd.Run(); err != nil {
189+
log.Fatal(err)
190+
}
191+
// Prefer GOROOT/api over GOPATH/api.
192+
for line := range strings.SplitSeq(stdout.String(), "\n") {
193+
apidir := filepath.Join(line, "api")
194+
info, err := os.Stat(apidir)
195+
if err == nil && info.IsDir() {
196+
return apidir
197+
}
198+
}
199+
log.Fatal("could not find api dir")
200+
return ""
201+
}
202+
180203
type symInfo struct {
181204
kind string // e.g. "func"
182205
minor int // go1.%d

internal/stdlib/manifest.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)