internal/cmd/qgo: port qgo from loader to packages

exclude ReplaceAll, for now

Change-Id: I2574bbbb3e1d72b64770fdee759c2d68b272902c
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2322
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/internal/cmd/qgo/qgo.go b/internal/cmd/qgo/qgo.go
index 7c2cbdf..4d5e57d 100644
--- a/internal/cmd/qgo/qgo.go
+++ b/internal/cmd/qgo/qgo.go
@@ -22,7 +22,6 @@
 	"go/ast"
 	"go/constant"
 	"go/format"
-	"go/parser"
 	"go/printer"
 	"go/token"
 	"go/types"
@@ -34,7 +33,7 @@
 	"regexp"
 	"strings"
 
-	"golang.org/x/tools/go/loader"
+	"golang.org/x/tools/go/packages"
 )
 
 const help = `
@@ -129,24 +128,22 @@
 }
 
 type extracter struct {
-	prog *loader.Program
-	pkg  *loader.PackageInfo
+	pkg *packages.Package
 }
 
 func extract(args []string) {
-
-	cfg := loader.Config{
-		ParserMode: parser.ParseComments,
+	cfg := &packages.Config{
+		Mode: packages.LoadFiles |
+			packages.LoadAllSyntax |
+			packages.LoadTypes,
 	}
-	cfg.FromArgs(args, false)
-
-	e := extracter{}
-	var err error
-	e.prog, err = cfg.Load()
+	pkgs, err := packages.Load(cfg, args...)
 	if err != nil {
 		log.Fatal(err)
 	}
 
+	e := extracter{}
+
 	lastPkg := ""
 	var w *bytes.Buffer
 	initExclusions()
@@ -165,18 +162,18 @@
 		w = &bytes.Buffer{}
 	}
 
-	for _, p := range e.prog.InitialPackages() {
+	for _, p := range pkgs {
 		e.pkg = p
-		for _, f := range p.Files {
-			if lastPkg != p.Pkg.Name() {
+		for _, f := range p.Syntax {
+			if lastPkg != p.Name {
 				flushFile()
-				lastPkg = p.Pkg.Name()
+				lastPkg = p.Name
 				fmt.Fprintln(w, copyright)
 				fmt.Fprintln(w, genLine)
 				fmt.Fprintln(w)
 				fmt.Fprintf(w, "package %s\n", pkgName())
 				fmt.Fprintln(w)
-				fmt.Fprintf(w, "import %q", p.Pkg.Path())
+				fmt.Fprintf(w, "import %q", p.PkgPath)
 				fmt.Fprintln(w)
 			}
 
@@ -197,7 +194,7 @@
 	if filter(x.Name.Name) {
 		return
 	}
-	pkgName := e.pkg.Pkg.Name()
+	pkgName := e.pkg.Name
 	override := ""
 	params := []ast.Expr{}
 	if x.Type.Params != nil {
@@ -261,14 +258,14 @@
 		default:
 			fmt.Printf("Skipping ")
 			x.Doc = nil
-			printer.Fprint(os.Stdout, e.prog.Fset, x)
+			printer.Fprint(os.Stdout, e.pkg.Fset, x)
 			fmt.Println()
 			return
 		}
 	}
 	fmt.Fprintln(w)
-	printer.Fprint(w, e.prog.Fset, x.Doc)
-	printer.Fprint(w, e.prog.Fset, x)
+	printer.Fprint(w, e.pkg.Fset, x.Doc)
+	printer.Fprint(w, e.pkg.Fset, x)
 	fmt.Fprint(w, "\n")
 	if override != "" {
 		fmt.Fprintf(w, "var %s = %s.%s\n\n", override, pkgName, x.Name.Name)
@@ -290,7 +287,7 @@
 				if _, ok := v.Values[i].(*ast.BasicLit); ok {
 					continue
 				}
-				tv, _ := types.Eval(e.prog.Fset, e.pkg.Pkg, v.Pos(), v.Names[0].Name)
+				tv, _ := types.Eval(e.pkg.Fset, e.pkg.Types, v.Pos(), v.Names[0].Name)
 				tok := token.ILLEGAL
 				switch tv.Value.Kind() {
 				case constant.Bool:
@@ -322,6 +319,6 @@
 		return
 	}
 	fmt.Fprintln(w)
-	printer.Fprint(w, e.prog.Fset, x)
+	printer.Fprint(w, e.pkg.Fset, x)
 	fmt.Fprintln(w)
 }
diff --git a/pkg/math/math.go b/pkg/math/math.go
index c20e405..a66f27a 100644
--- a/pkg/math/math.go
+++ b/pkg/math/math.go
@@ -446,7 +446,7 @@
 	return math.Remainder(x, y)
 }
 
-// Signbit returns true if x is negative or negative zero.
+// Signbit reports whether x is negative or negative zero.
 func Signbit(x float64) bool {
 	return math.Signbit(x)
 }
diff --git a/pkg/strconv/strconv.go b/pkg/strconv/strconv.go
index ecd73d5..fac12d8 100644
--- a/pkg/strconv/strconv.go
+++ b/pkg/strconv/strconv.go
@@ -86,7 +86,7 @@
 	return strconv.ParseInt(s, base, bitSize)
 }
 
-// Atoi returns the result of ParseInt(s, 10, 0) converted to type int.
+// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.
 func Atoi(s string) (int, error) {
 	return strconv.Atoi(s)
 }
diff --git a/pkg/strings/strings.go b/pkg/strings/strings.go
index 45c7b20..888cf1b 100644
--- a/pkg/strings/strings.go
+++ b/pkg/strings/strings.go
@@ -16,7 +16,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:generate qgo -exclude=Rune$,Func$,^Map$,Special$,EqualFold,Byte,Title$ extract strings
+//go:generate qgo -exclude=Rune$,Func$,^Map$,Special$,EqualFold,Byte,Title$,All$ extract strings
 
 package strings
 
diff --git a/pkg/tool/cli/doc.go b/pkg/tool/cli/doc.go
index 7199ea0..27dee9a 100644
--- a/pkg/tool/cli/doc.go
+++ b/pkg/tool/cli/doc.go
@@ -6,10 +6,29 @@
 //
 //     // Print sends text to the stdout of the current process.
 //     Print: {
-//     	kind: "tool/cli.Print"
+//     	kind: *"tool/cli.Print" | "print" // for backwards compatibility
 //
 //     	// text is the text to be printed.
 //     	text: string
 //     }
 //
+//     // TODO:
+//     // Ask prompts the current console with a message and waits for input.
+//     //
+//     // Example:
+//     //     task ask: cli.Ask({
+//     //         prompt:   "Are you okay?"
+//     //         repsonse: bool
+//     //     })
+//     // Ask: {
+//     //  kind: "tool/cli.Ask"
+//
+//     //  // prompt sends this message to the output.
+//     //  prompt: string
+//
+//     //  // response holds the user's response. If it is a boolean expression it
+//     //  // will interpret the answer using textual yes/ no.
+//     //  response: string | bool
+//     // }
+//
 package cli
diff --git a/pkg/tool/exec/doc.go b/pkg/tool/exec/doc.go
index 67632e0..90a0d09 100644
--- a/pkg/tool/exec/doc.go
+++ b/pkg/tool/exec/doc.go
@@ -6,7 +6,7 @@
 //
 //     // Run executes the given shell command.
 //     Run: {
-//     	kind: "tool/exec.Run"
+//     	kind: *"tool/exec.Run" | "exec" // exec for backwards compatibility
 //
 //     	// cmd is the command to run.
 //     	cmd: string | [string, ...string]
diff --git a/pkg/tool/file/doc.go b/pkg/tool/file/doc.go
index e52615f..6a86439 100644
--- a/pkg/tool/file/doc.go
+++ b/pkg/tool/file/doc.go
@@ -9,6 +9,9 @@
 //     	kind: "tool/file.Read"
 //
 //     	// filename names the file to read.
+//     	//
+//     	// Relative names are taken relative to the current working directory.
+//     	// Slashes are converted to the native OS path separator.
 //     	filename: !=""
 //
 //     	// contents is the read contents. If the contents are constraint to bytes
@@ -22,6 +25,9 @@
 //     	kind: "tool/file.Append"
 //
 //     	// filename names the file to append.
+//     	//
+//     	// Relative names are taken relative to the current working directory.
+//     	// Slashes are converted to the native OS path separator.
 //     	filename: !=""
 //
 //     	// permissions defines the permissions to use if the file does not yet exist.
@@ -36,6 +42,9 @@
 //     	kind: "tool/file.Create"
 //
 //     	// filename names the file to write.
+//     	//
+//     	// Relative names are taken relative to the current working directory.
+//     	// Slashes are converted to the native OS path separator.
 //     	filename: !=""
 //
 //     	// permissions defines the permissions to use if the file does not yet exist.
@@ -45,9 +54,14 @@
 //     	contents: bytes | string
 //     }
 //
+//     // Glob returns a list of files.
 //     Glob: {
 //     	kind: "tool/file.Glob"
 //
+//     	// glob specifies the pattern to match files with.
+//     	//
+//     	// A relative pattern is taken relative to the current working directory.
+//     	// Slashes are converted to the native OS path separator.
 //     	glob: !=""
 //     	files: [...string]
 //     }
diff --git a/pkg/tool/http/doc.go b/pkg/tool/http/doc.go
index 5827610..c587f90 100644
--- a/pkg/tool/http/doc.go
+++ b/pkg/tool/http/doc.go
@@ -10,7 +10,7 @@
 //     Delete: Do & {method: "DELETE"}
 //
 //     Do: {
-//     	kind: "tool/http.Do"
+//     	kind: *"tool/http.Do" | "http" // http for backwards compatibility
 //
 //     	method: string
 //     	url:    string // TODO: make url.URL type
@@ -30,4 +30,17 @@
 //     	}
 //     }
 //
+//     /* TODO: support serving once we have the cue serve command.
+//     Serve: {
+//     	port: int
+//
+//     	cert: string
+//     	key:  string
+//
+//     	handle <Pattern>: Message & {
+//     		pattern: Pattern
+//     	}
+//     }
+//     */
+//
 package http