github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/fmtcmd/fmt.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package fmtcmd implements the “go fmt” command. 6 package fmtcmd 7 8 import ( 9 "context" 10 "errors" 11 "fmt" 12 "os" 13 "path/filepath" 14 15 "github.com/go-asm/go/cmd/go/base" 16 "github.com/go-asm/go/cmd/go/cfg" 17 "github.com/go-asm/go/cmd/go/load" 18 "github.com/go-asm/go/cmd/go/modload" 19 "github.com/go-asm/go/cmd/sys" 20 ) 21 22 func init() { 23 base.AddBuildFlagsNX(&CmdFmt.Flag) 24 base.AddChdirFlag(&CmdFmt.Flag) 25 base.AddModFlag(&CmdFmt.Flag) 26 base.AddModCommonFlags(&CmdFmt.Flag) 27 } 28 29 var CmdFmt = &base.Command{ 30 Run: runFmt, 31 UsageLine: "go fmt [-n] [-x] [packages]", 32 Short: "gofmt (reformat) package sources", 33 Long: ` 34 Fmt runs the command 'gofmt -l -w' on the packages named 35 by the import paths. It prints the names of the files that are modified. 36 37 For more about gofmt, see 'go doc cmd/gofmt'. 38 For more about specifying packages, see 'go help packages'. 39 40 The -n flag prints commands that would be executed. 41 The -x flag prints commands as they are executed. 42 43 The -mod flag's value sets which module download mode 44 to use: readonly or vendor. See 'go help modules' for more. 45 46 To run gofmt with specific options, run gofmt itself. 47 48 See also: go fix, go vet. 49 `, 50 } 51 52 func runFmt(ctx context.Context, cmd *base.Command, args []string) { 53 printed := false 54 gofmt := gofmtPath() 55 56 gofmtArgs := []string{gofmt, "-l", "-w"} 57 gofmtArgLen := len(gofmt) + len(" -l -w") 58 59 baseGofmtArgs := len(gofmtArgs) 60 baseGofmtArgLen := gofmtArgLen 61 62 for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { 63 if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { 64 if !printed { 65 fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n") 66 printed = true 67 } 68 continue 69 } 70 if pkg.Error != nil { 71 var nogo *load.NoGoError 72 var embed *load.EmbedError 73 if (errors.As(pkg.Error, &nogo) || errors.As(pkg.Error, &embed)) && len(pkg.InternalAllGoFiles()) > 0 { 74 // Skip this error, as we will format 75 // all files regardless. 76 } else { 77 base.Errorf("%v", pkg.Error) 78 continue 79 } 80 } 81 // Use pkg.gofiles instead of pkg.Dir so that 82 // the command only applies to this package, 83 // not to packages in subdirectories. 84 files := base.RelPaths(pkg.InternalAllGoFiles()) 85 for _, file := range files { 86 gofmtArgs = append(gofmtArgs, file) 87 gofmtArgLen += 1 + len(file) // plus separator 88 if gofmtArgLen >= sys.ExecArgLengthLimit { 89 base.Run(gofmtArgs) 90 gofmtArgs = gofmtArgs[:baseGofmtArgs] 91 gofmtArgLen = baseGofmtArgLen 92 } 93 } 94 } 95 if len(gofmtArgs) > baseGofmtArgs { 96 base.Run(gofmtArgs) 97 } 98 } 99 100 func gofmtPath() string { 101 gofmt := "gofmt" + cfg.ToolExeSuffix() 102 103 gofmtPath := filepath.Join(cfg.GOBIN, gofmt) 104 if _, err := os.Stat(gofmtPath); err == nil { 105 return gofmtPath 106 } 107 108 gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt) 109 if _, err := os.Stat(gofmtPath); err == nil { 110 return gofmtPath 111 } 112 113 // fallback to looking for gofmt in $PATH 114 return "gofmt" 115 }