Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / cmd / bundle / main.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/cmd/bundle/main.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/cmd/bundle/main.go
new file mode 100644 (file)
index 0000000..8e5ad2c
--- /dev/null
@@ -0,0 +1,457 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Bundle creates a single-source-file version of a source package
+// suitable for inclusion in a particular target package.
+//
+// Usage:
+//
+//     bundle [-o file] [-dst path] [-pkg name] [-prefix p] [-import old=new] [-tags build_constraints] <src>
+//
+// The src argument specifies the import path of the package to bundle.
+// The bundling of a directory of source files into a single source file
+// necessarily imposes a number of constraints.
+// The package being bundled must not use cgo; must not use conditional
+// file compilation, whether with build tags or system-specific file names
+// like code_amd64.go; must not depend on any special comments, which
+// may not be preserved; must not use any assembly sources;
+// must not use renaming imports; and must not use reflection-based APIs
+// that depend on the specific names of types or struct fields.
+//
+// By default, bundle writes the bundled code to standard output.
+// If the -o argument is given, bundle writes to the named file
+// and also includes a ``//go:generate'' comment giving the exact
+// command line used, for regenerating the file with ``go generate.''
+//
+// Bundle customizes its output for inclusion in a particular package, the destination package.
+// By default bundle assumes the destination is the package in the current directory,
+// but the destination package can be specified explicitly using the -dst option,
+// which takes an import path as its argument.
+// If the source package imports the destination package, bundle will remove
+// those imports and rewrite any references to use direct references to the
+// corresponding symbols.
+// Bundle also must write a package declaration in the output and must
+// choose a name to use in that declaration.
+// If the -pkg option is given, bundle uses that name.
+// Otherwise, the name of the destination package is used.
+// Build constraints for the generated file can be specified using the -tags option.
+//
+// To avoid collisions, bundle inserts a prefix at the beginning of
+// every package-level const, func, type, and var identifier in src's code,
+// updating references accordingly. The default prefix is the package name
+// of the source package followed by an underscore. The -prefix option
+// specifies an alternate prefix.
+//
+// Occasionally it is necessary to rewrite imports during the bundling
+// process. The -import option, which may be repeated, specifies that
+// an import of "old" should be rewritten to import "new" instead.
+//
+// Example
+//
+// Bundle archive/zip for inclusion in cmd/dist:
+//
+//     cd $GOROOT/src/cmd/dist
+//     bundle -o zip.go archive/zip
+//
+// Bundle golang.org/x/net/http2 for inclusion in net/http,
+// prefixing all identifiers by "http2" instead of "http2_", and
+// including a "!nethttpomithttp2" build constraint:
+//
+//     cd $GOROOT/src/net/http
+//     bundle -o h2_bundle.go -prefix http2 -tags '!nethttpomithttp2' golang.org/x/net/http2
+//
+// Update the http2 bundle in net/http:
+//
+//     go generate net/http
+//
+// Update all bundles in the standard library:
+//
+//     go generate -run bundle std
+//
+package main
+
+import (
+       "bytes"
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/format"
+       "go/printer"
+       "go/token"
+       "go/types"
+       "io/ioutil"
+       "log"
+       "os"
+       "strconv"
+       "strings"
+
+       "golang.org/x/tools/go/packages"
+)
+
+var (
+       outputFile = flag.String("o", "", "write output to `file` (default standard output)")
+       dstPath    = flag.String("dst", ".", "set destination import `path`")
+       pkgName    = flag.String("pkg", "", "set destination package `name`")
+       prefix     = flag.String("prefix", "&_", "set bundled identifier prefix to `p` (default is \"&_\", where & stands for the original name)")
+       buildTags  = flag.String("tags", "", "the build constraints to be inserted into the generated file")
+
+       importMap = map[string]string{}
+)
+
+func init() {
+       flag.Var(flagFunc(addImportMap), "import", "rewrite import using `map`, of form old=new (can be repeated)")
+}
+
+func addImportMap(s string) {
+       if strings.Count(s, "=") != 1 {
+               log.Fatal("-import argument must be of the form old=new")
+       }
+       i := strings.Index(s, "=")
+       old, new := s[:i], s[i+1:]
+       if old == "" || new == "" {
+               log.Fatal("-import argument must be of the form old=new; old and new must be non-empty")
+       }
+       importMap[old] = new
+}
+
+func usage() {
+       fmt.Fprintf(os.Stderr, "Usage: bundle [options] <src>\n")
+       flag.PrintDefaults()
+}
+
+func main() {
+       log.SetPrefix("bundle: ")
+       log.SetFlags(0)
+
+       flag.Usage = usage
+       flag.Parse()
+       args := flag.Args()
+       if len(args) != 1 {
+               usage()
+               os.Exit(2)
+       }
+
+       cfg := &packages.Config{Mode: packages.NeedName}
+       pkgs, err := packages.Load(cfg, *dstPath)
+       if err != nil {
+               log.Fatalf("cannot load destination package: %v", err)
+       }
+       if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
+               log.Fatalf("failed to load destination package")
+       }
+       if *pkgName == "" {
+               *pkgName = pkgs[0].Name
+       }
+
+       code, err := bundle(args[0], pkgs[0].PkgPath, *pkgName, *prefix, *buildTags)
+       if err != nil {
+               log.Fatal(err)
+       }
+       if *outputFile != "" {
+               err := ioutil.WriteFile(*outputFile, code, 0666)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       } else {
+               _, err := os.Stdout.Write(code)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
+
+// isStandardImportPath is copied from cmd/go in the standard library.
+func isStandardImportPath(path string) bool {
+       i := strings.Index(path, "/")
+       if i < 0 {
+               i = len(path)
+       }
+       elem := path[:i]
+       return !strings.Contains(elem, ".")
+}
+
+var testingOnlyPackagesConfig *packages.Config
+
+func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
+       // Load the initial package.
+       cfg := &packages.Config{}
+       if testingOnlyPackagesConfig != nil {
+               *cfg = *testingOnlyPackagesConfig
+       } else {
+               // Bypass default vendor mode, as we need a package not available in the
+               // std module vendor folder.
+               cfg.Env = append(os.Environ(), "GOFLAGS=-mod=mod")
+       }
+       cfg.Mode = packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo
+       pkgs, err := packages.Load(cfg, src)
+       if err != nil {
+               return nil, err
+       }
+       if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
+               return nil, fmt.Errorf("failed to load source package")
+       }
+       pkg := pkgs[0]
+
+       if strings.Contains(prefix, "&") {
+               prefix = strings.Replace(prefix, "&", pkg.Syntax[0].Name.Name, -1)
+       }
+
+       objsToUpdate := make(map[types.Object]bool)
+       var rename func(from types.Object)
+       rename = func(from types.Object) {
+               if !objsToUpdate[from] {
+                       objsToUpdate[from] = true
+
+                       // Renaming a type that is used as an embedded field
+                       // requires renaming the field too. e.g.
+                       //      type T int // if we rename this to U..
+                       //      var s struct {T}
+                       //      print(s.T) // ...this must change too
+                       if _, ok := from.(*types.TypeName); ok {
+                               for id, obj := range pkg.TypesInfo.Uses {
+                                       if obj == from {
+                                               if field := pkg.TypesInfo.Defs[id]; field != nil {
+                                                       rename(field)
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // Rename each package-level object.
+       scope := pkg.Types.Scope()
+       for _, name := range scope.Names() {
+               rename(scope.Lookup(name))
+       }
+
+       var out bytes.Buffer
+       if buildTags != "" {
+               fmt.Fprintf(&out, "// +build %s\n\n", buildTags)
+       }
+
+       fmt.Fprintf(&out, "// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.\n")
+       if *outputFile != "" && buildTags == "" {
+               fmt.Fprintf(&out, "//go:generate bundle %s\n", strings.Join(os.Args[1:], " "))
+       } else {
+               fmt.Fprintf(&out, "//   $ bundle %s\n", strings.Join(os.Args[1:], " "))
+       }
+       fmt.Fprintf(&out, "\n")
+
+       // Concatenate package comments from all files...
+       for _, f := range pkg.Syntax {
+               if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
+                       for _, line := range strings.Split(doc, "\n") {
+                               fmt.Fprintf(&out, "// %s\n", line)
+                       }
+               }
+       }
+       // ...but don't let them become the actual package comment.
+       fmt.Fprintln(&out)
+
+       fmt.Fprintf(&out, "package %s\n\n", dstpkg)
+
+       // BUG(adonovan,shurcooL): bundle may generate incorrect code
+       // due to shadowing between identifiers and imported package names.
+       //
+       // The generated code will either fail to compile or
+       // (unlikely) compile successfully but have different behavior
+       // than the original package. The risk of this happening is higher
+       // when the original package has renamed imports (they're typically
+       // renamed in order to resolve a shadow inside that particular .go file).
+
+       // TODO(adonovan,shurcooL):
+       // - detect shadowing issues, and either return error or resolve them
+       // - preserve comments from the original import declarations.
+
+       // pkgStd and pkgExt are sets of printed import specs. This is done
+       // to deduplicate instances of the same import name and path.
+       var pkgStd = make(map[string]bool)
+       var pkgExt = make(map[string]bool)
+       for _, f := range pkg.Syntax {
+               for _, imp := range f.Imports {
+                       path, err := strconv.Unquote(imp.Path.Value)
+                       if err != nil {
+                               log.Fatalf("invalid import path string: %v", err) // Shouldn't happen here since packages.Load succeeded.
+                       }
+                       if path == dst {
+                               continue
+                       }
+                       if newPath, ok := importMap[path]; ok {
+                               path = newPath
+                       }
+
+                       var name string
+                       if imp.Name != nil {
+                               name = imp.Name.Name
+                       }
+                       spec := fmt.Sprintf("%s %q", name, path)
+                       if isStandardImportPath(path) {
+                               pkgStd[spec] = true
+                       } else {
+                               pkgExt[spec] = true
+                       }
+               }
+       }
+
+       // Print a single declaration that imports all necessary packages.
+       fmt.Fprintln(&out, "import (")
+       for p := range pkgStd {
+               fmt.Fprintf(&out, "\t%s\n", p)
+       }
+       if len(pkgExt) > 0 {
+               fmt.Fprintln(&out)
+       }
+       for p := range pkgExt {
+               fmt.Fprintf(&out, "\t%s\n", p)
+       }
+       fmt.Fprint(&out, ")\n\n")
+
+       // Modify and print each file.
+       for _, f := range pkg.Syntax {
+               // Update renamed identifiers.
+               for id, obj := range pkg.TypesInfo.Defs {
+                       if objsToUpdate[obj] {
+                               id.Name = prefix + obj.Name()
+                       }
+               }
+               for id, obj := range pkg.TypesInfo.Uses {
+                       if objsToUpdate[obj] {
+                               id.Name = prefix + obj.Name()
+                       }
+               }
+
+               // For each qualified identifier that refers to the
+               // destination package, remove the qualifier.
+               // The "@@@." strings are removed in postprocessing.
+               ast.Inspect(f, func(n ast.Node) bool {
+                       if sel, ok := n.(*ast.SelectorExpr); ok {
+                               if id, ok := sel.X.(*ast.Ident); ok {
+                                       if obj, ok := pkg.TypesInfo.Uses[id].(*types.PkgName); ok {
+                                               if obj.Imported().Path() == dst {
+                                                       id.Name = "@@@"
+                                               }
+                                       }
+                               }
+                       }
+                       return true
+               })
+
+               last := f.Package
+               if len(f.Imports) > 0 {
+                       imp := f.Imports[len(f.Imports)-1]
+                       last = imp.End()
+                       if imp.Comment != nil {
+                               if e := imp.Comment.End(); e > last {
+                                       last = e
+                               }
+                       }
+               }
+
+               // Pretty-print package-level declarations.
+               // but no package or import declarations.
+               var buf bytes.Buffer
+               for _, decl := range f.Decls {
+                       if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {
+                               continue
+                       }
+
+                       beg, end := sourceRange(decl)
+
+                       printComments(&out, f.Comments, last, beg)
+
+                       buf.Reset()
+                       format.Node(&buf, pkg.Fset, &printer.CommentedNode{Node: decl, Comments: f.Comments})
+                       // Remove each "@@@." in the output.
+                       // TODO(adonovan): not hygienic.
+                       out.Write(bytes.Replace(buf.Bytes(), []byte("@@@."), nil, -1))
+
+                       last = printSameLineComment(&out, f.Comments, pkg.Fset, end)
+
+                       out.WriteString("\n\n")
+               }
+
+               printLastComments(&out, f.Comments, last)
+       }
+
+       // Now format the entire thing.
+       result, err := format.Source(out.Bytes())
+       if err != nil {
+               log.Fatalf("formatting failed: %v", err)
+       }
+
+       return result, nil
+}
+
+// sourceRange returns the [beg, end) interval of source code
+// belonging to decl (incl. associated comments).
+func sourceRange(decl ast.Decl) (beg, end token.Pos) {
+       beg = decl.Pos()
+       end = decl.End()
+
+       var doc, com *ast.CommentGroup
+
+       switch d := decl.(type) {
+       case *ast.GenDecl:
+               doc = d.Doc
+               if len(d.Specs) > 0 {
+                       switch spec := d.Specs[len(d.Specs)-1].(type) {
+                       case *ast.ValueSpec:
+                               com = spec.Comment
+                       case *ast.TypeSpec:
+                               com = spec.Comment
+                       }
+               }
+       case *ast.FuncDecl:
+               doc = d.Doc
+       }
+
+       if doc != nil {
+               beg = doc.Pos()
+       }
+       if com != nil && com.End() > end {
+               end = com.End()
+       }
+
+       return beg, end
+}
+
+func printComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos, end token.Pos) {
+       for _, cg := range comments {
+               if pos <= cg.Pos() && cg.Pos() < end {
+                       for _, c := range cg.List {
+                               fmt.Fprintln(out, c.Text)
+                       }
+                       fmt.Fprintln(out)
+               }
+       }
+}
+
+const infinity = 1 << 30
+
+func printLastComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos token.Pos) {
+       printComments(out, comments, pos, infinity)
+}
+
+func printSameLineComment(out *bytes.Buffer, comments []*ast.CommentGroup, fset *token.FileSet, pos token.Pos) token.Pos {
+       tf := fset.File(pos)
+       for _, cg := range comments {
+               if pos <= cg.Pos() && tf.Line(cg.Pos()) == tf.Line(pos) {
+                       for _, c := range cg.List {
+                               fmt.Fprintln(out, c.Text)
+                       }
+                       return cg.End()
+               }
+       }
+       return pos
+}
+
+type flagFunc func(string)
+
+func (f flagFunc) Set(s string) error {
+       f(s)
+       return nil
+}
+
+func (f flagFunc) String() string { return "" }