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 / eg / eg.go
1 // The eg command performs example-based refactoring.
2 // For documentation, run the command, or see Help in
3 // golang.org/x/tools/refactor/eg.
4 package main // import "golang.org/x/tools/cmd/eg"
5
6 import (
7         "flag"
8         "fmt"
9         "go/build"
10         "go/format"
11         "go/parser"
12         "go/token"
13         "os"
14         "os/exec"
15         "strings"
16
17         "golang.org/x/tools/go/buildutil"
18         "golang.org/x/tools/go/loader"
19         "golang.org/x/tools/refactor/eg"
20 )
21
22 var (
23         beforeeditFlag = flag.String("beforeedit", "", "A command to exec before each file is edited (e.g. chmod, checkout).  Whitespace delimits argument words.  The string '{}' is replaced by the file name.")
24         helpFlag       = flag.Bool("help", false, "show detailed help message")
25         templateFlag   = flag.String("t", "", "template.go file specifying the refactoring")
26         transitiveFlag = flag.Bool("transitive", false, "apply refactoring to all dependencies too")
27         writeFlag      = flag.Bool("w", false, "rewrite input files in place (by default, the results are printed to standard output)")
28         verboseFlag    = flag.Bool("v", false, "show verbose matcher diagnostics")
29 )
30
31 func init() {
32         flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
33 }
34
35 const usage = `eg: an example-based refactoring tool.
36
37 Usage: eg -t template.go [-w] [-transitive] <args>...
38
39 -help            show detailed help message
40 -t template.go   specifies the template file (use -help to see explanation)
41 -w               causes files to be re-written in place.
42 -transitive      causes all dependencies to be refactored too.
43 -v               show verbose matcher diagnostics
44 -beforeedit cmd  a command to exec before each file is modified.
45                  "{}" represents the name of the file.
46 ` + loader.FromArgsUsage
47
48 func main() {
49         if err := doMain(); err != nil {
50                 fmt.Fprintf(os.Stderr, "eg: %s\n", err)
51                 os.Exit(1)
52         }
53 }
54
55 func doMain() error {
56         flag.Parse()
57         args := flag.Args()
58
59         if *helpFlag {
60                 fmt.Fprint(os.Stderr, eg.Help)
61                 os.Exit(2)
62         }
63
64         if len(args) == 0 {
65                 fmt.Fprint(os.Stderr, usage)
66                 os.Exit(1)
67         }
68
69         if *templateFlag == "" {
70                 return fmt.Errorf("no -t template.go file specified")
71         }
72
73         conf := loader.Config{
74                 Fset:       token.NewFileSet(),
75                 ParserMode: parser.ParseComments,
76         }
77
78         // The first Created package is the template.
79         conf.CreateFromFilenames("template", *templateFlag)
80
81         if _, err := conf.FromArgs(args, true); err != nil {
82                 return err
83         }
84
85         // Load, parse and type-check the whole program.
86         iprog, err := conf.Load()
87         if err != nil {
88                 return err
89         }
90
91         // Analyze the template.
92         template := iprog.Created[0]
93         xform, err := eg.NewTransformer(iprog.Fset, template.Pkg, template.Files[0], &template.Info, *verboseFlag)
94         if err != nil {
95                 return err
96         }
97
98         // Apply it to the input packages.
99         var pkgs []*loader.PackageInfo
100         if *transitiveFlag {
101                 for _, info := range iprog.AllPackages {
102                         pkgs = append(pkgs, info)
103                 }
104         } else {
105                 pkgs = iprog.InitialPackages()
106         }
107         var hadErrors bool
108         for _, pkg := range pkgs {
109                 if pkg == template {
110                         continue
111                 }
112                 for _, file := range pkg.Files {
113                         n := xform.Transform(&pkg.Info, pkg.Pkg, file)
114                         if n == 0 {
115                                 continue
116                         }
117                         filename := iprog.Fset.File(file.Pos()).Name()
118                         fmt.Fprintf(os.Stderr, "=== %s (%d matches)\n", filename, n)
119                         if *writeFlag {
120                                 // Run the before-edit command (e.g. "chmod +w",  "checkout") if any.
121                                 if *beforeeditFlag != "" {
122                                         args := strings.Fields(*beforeeditFlag)
123                                         // Replace "{}" with the filename, like find(1).
124                                         for i := range args {
125                                                 if i > 0 {
126                                                         args[i] = strings.Replace(args[i], "{}", filename, -1)
127                                                 }
128                                         }
129                                         cmd := exec.Command(args[0], args[1:]...)
130                                         cmd.Stdout = os.Stdout
131                                         cmd.Stderr = os.Stderr
132                                         if err := cmd.Run(); err != nil {
133                                                 fmt.Fprintf(os.Stderr, "Warning: edit hook %q failed (%s)\n",
134                                                         args, err)
135                                         }
136                                 }
137                                 if err := eg.WriteAST(iprog.Fset, filename, file); err != nil {
138                                         fmt.Fprintf(os.Stderr, "eg: %s\n", err)
139                                         hadErrors = true
140                                 }
141                         } else {
142                                 format.Node(os.Stdout, iprog.Fset, file)
143                         }
144                 }
145         }
146         if hadErrors {
147                 os.Exit(1)
148         }
149         return nil
150 }