internal/imports: use go/packages instead of cmd/api to compute symbols

The API of syscall/js package is generated by reusing cmd/api. That has
stopped being a runnable command after an internal refactor in Go 1.20.
Since cmd/api was never really supported or meant to be used outside of
GOROOT, switch to using go/packages and compute the API more directly
ourselves.

Also use the same approach to generate the API of package unsafe (whose
API is also not present in GOROOT/api files at this time) instead of a
fixed list that needs manual maintenance. This adds Add and Slice that
were added to package unsafe in Go 1.17. It also removes ArbitraryType,
since that symbol isn't a part of package unsafe's API but used in its
documentation—it seems like an oversight that it was added in CL 24463.

This CL intentionally leaves out unsafe's SliceData, String, StringData
that were added in Go 1.20, so I can test out the new relui workflow to
send a CL that regenerates this package.

Fixes golang/go#58245.
For golang/go#38706.

Change-Id: Ibe0d89bf0469691bd16e0d0f501e3762256f2239
Reviewed-on: https://go-review.googlesource.com/c/tools/+/464715
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/internal/imports/mkstdlib.go b/internal/imports/mkstdlib.go
index a73f024..470b93f 100644
--- a/internal/imports/mkstdlib.go
+++ b/internal/imports/mkstdlib.go
@@ -15,6 +15,7 @@
 	"bytes"
 	"fmt"
 	"go/format"
+	"go/token"
 	"io"
 	"io/ioutil"
 	"log"
@@ -25,7 +26,7 @@
 	"sort"
 	"strings"
 
-	exec "golang.org/x/sys/execabs"
+	"golang.org/x/tools/go/packages"
 )
 
 func mustOpen(name string) io.Reader {
@@ -42,8 +43,6 @@
 
 var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
 
-var unsafeSyms = map[string]bool{"Alignof": true, "ArbitraryType": true, "Offsetof": true, "Pointer": true, "Sizeof": true}
-
 func main() {
 	var buf bytes.Buffer
 	outf := func(format string, args ...interface{}) {
@@ -60,10 +59,13 @@
 	f := readAPI()
 	sc := bufio.NewScanner(f)
 
+	// The APIs of the syscall/js and unsafe packages need to be computed explicitly,
+	// because they're not included in the GOROOT/api/go1.*.txt files at this time.
 	pkgs := map[string]map[string]bool{
-		"unsafe": unsafeSyms,
+		"syscall/js": syms("syscall/js", "GOOS=js", "GOARCH=wasm"),
+		"unsafe":     syms("unsafe"),
 	}
-	paths := []string{"unsafe"}
+	paths := []string{"syscall/js", "unsafe"}
 
 	for sc.Scan() {
 		l := sc.Text()
@@ -118,23 +120,26 @@
 			readers = append(readers, mustOpen(api(name)))
 		}
 	}
-	// The API of the syscall/js package needs to be computed explicitly,
-	// because it's not included in the GOROOT/api/go1.*.txt files at this time.
-	readers = append(readers, syscallJSAPI())
 	return io.MultiReader(readers...)
 }
 
-// syscallJSAPI returns the API of the syscall/js package.
-// It's computed from the contents of $(go env GOROOT)/src/syscall/js.
-func syscallJSAPI() io.Reader {
-	var exeSuffix string
-	if runtime.GOOS == "windows" {
-		exeSuffix = ".exe"
+// syms computes the exported symbols in the specified package.
+func syms(pkg string, extraEnv ...string) map[string]bool {
+	var env []string
+	if len(extraEnv) != 0 {
+		env = append(os.Environ(), extraEnv...)
 	}
-	cmd := exec.Command("go"+exeSuffix, "run", "cmd/api", "-contexts", "js-wasm", "syscall/js")
-	out, err := cmd.Output()
+	pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedTypes, Env: env}, pkg)
 	if err != nil {
 		log.Fatalln(err)
+	} else if len(pkgs) != 1 {
+		log.Fatalf("got %d packages, want one package %q", len(pkgs), pkg)
 	}
-	return bytes.NewReader(out)
+	syms := make(map[string]bool)
+	for _, name := range pkgs[0].Types.Scope().Names() {
+		if token.IsExported(name) {
+			syms[name] = true
+		}
+	}
+	return syms
 }
diff --git a/internal/imports/zstdlib.go b/internal/imports/zstdlib.go
index 9339644..a03ff2c 100644
--- a/internal/imports/zstdlib.go
+++ b/internal/imports/zstdlib.go
@@ -11102,10 +11102,11 @@
 		"ValidString",
 	},
 	"unsafe": {
+		"Add",
 		"Alignof",
-		"ArbitraryType",
 		"Offsetof",
 		"Pointer",
 		"Sizeof",
+		"Slice",
 	},
 }