-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: new fmt
command with dedicated formatter configuration
#5357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
d4a00b0
refactor: split processor and matcher
ldez 49ee0ae
feat: formatters configuration structures
ldez d9ce3be
chore: simplify createBuildInfo
ldez b372f01
refactor: use isolate MetaFormatter from linters
ldez 399d55c
feat: new command
ldez a3ab7ff
feat: formatter settings overrides linter settings
ldez e890bb2
feat: propagate formatter exclusions to linter exclusions
ldez 4754086
feat: isolate formatter setting deprecations
ldez ffe0837
feat: add enabled formatters to enabled linters
ldez 6d22c72
review
ldez 42182f0
feat: add diff flag (with exit code)
ldez 492756f
chore: run fmt command
ldez e75afbf
chore: remove golang.org/x/exp/maps
ldez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/fatih/color" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
|
||
"github.com/golangci/golangci-lint/pkg/config" | ||
"github.com/golangci/golangci-lint/pkg/goformat" | ||
"github.com/golangci/golangci-lint/pkg/goformatters" | ||
"github.com/golangci/golangci-lint/pkg/logutils" | ||
"github.com/golangci/golangci-lint/pkg/result/processors" | ||
) | ||
|
||
type fmtOptions struct { | ||
config.LoaderOptions | ||
|
||
diff bool // Flag only. | ||
} | ||
|
||
type fmtCommand struct { | ||
viper *viper.Viper | ||
cmd *cobra.Command | ||
|
||
opts fmtOptions | ||
|
||
cfg *config.Config | ||
|
||
buildInfo BuildInfo | ||
|
||
runner *goformat.Runner | ||
|
||
log logutils.Log | ||
debugf logutils.DebugFunc | ||
} | ||
|
||
func newFmtCommand(logger logutils.Log, info BuildInfo) *fmtCommand { | ||
c := &fmtCommand{ | ||
viper: viper.New(), | ||
log: logger, | ||
debugf: logutils.Debug(logutils.DebugKeyExec), | ||
cfg: config.NewDefault(), | ||
buildInfo: info, | ||
} | ||
|
||
fmtCmd := &cobra.Command{ | ||
Use: "fmt", | ||
Short: "Format Go source files", | ||
RunE: c.execute, | ||
PreRunE: c.preRunE, | ||
PersistentPreRunE: c.persistentPreRunE, | ||
PersistentPostRun: c.persistentPostRun, | ||
SilenceUsage: true, | ||
} | ||
|
||
fmtCmd.SetOut(logutils.StdOut) // use custom output to properly color it in Windows terminals | ||
fmtCmd.SetErr(logutils.StdErr) | ||
|
||
fs := fmtCmd.Flags() | ||
fs.SortFlags = false // sort them as they are defined here | ||
|
||
setupConfigFileFlagSet(fs, &c.opts.LoaderOptions) | ||
|
||
setupFormattersFlagSet(c.viper, fs) | ||
|
||
fs.BoolVarP(&c.opts.diff, "diff", "d", false, color.GreenString("Display diffs instead of rewriting files")) | ||
|
||
c.cmd = fmtCmd | ||
|
||
return c | ||
} | ||
|
||
func (c *fmtCommand) persistentPreRunE(cmd *cobra.Command, args []string) error { | ||
c.log.Infof("%s", c.buildInfo.String()) | ||
|
||
loader := config.NewLoader(c.log.Child(logutils.DebugKeyConfigReader), c.viper, cmd.Flags(), c.opts.LoaderOptions, c.cfg, args) | ||
|
||
err := loader.Load(config.LoadOptions{CheckDeprecation: true, Validation: true}) | ||
if err != nil { | ||
return fmt.Errorf("can't load config: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *fmtCommand) preRunE(_ *cobra.Command, _ []string) error { | ||
metaFormatter, err := goformatters.NewMetaFormatter(c.log, &c.cfg.Formatters, &c.cfg.Run) | ||
if err != nil { | ||
return fmt.Errorf("failed to create meta-formatter: %w", err) | ||
} | ||
|
||
matcher := processors.NewGeneratedFileMatcher(c.cfg.Formatters.Exclusions.Generated) | ||
|
||
opts, err := goformat.NewRunnerOptions(c.cfg, c.opts.diff) | ||
if err != nil { | ||
return fmt.Errorf("build walk options: %w", err) | ||
} | ||
|
||
c.runner = goformat.NewRunner(c.log, metaFormatter, matcher, opts) | ||
|
||
return nil | ||
} | ||
|
||
func (c *fmtCommand) execute(_ *cobra.Command, args []string) error { | ||
paths, err := cleanArgs(args) | ||
if err != nil { | ||
return fmt.Errorf("failed to clean arguments: %w", err) | ||
} | ||
|
||
c.log.Infof("Formatting Go files...") | ||
|
||
err = c.runner.Run(paths) | ||
if err != nil { | ||
return fmt.Errorf("failed to process files: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *fmtCommand) persistentPostRun(_ *cobra.Command, _ []string) { | ||
if c.runner.ExitCode() != 0 { | ||
os.Exit(c.runner.ExitCode()) | ||
} | ||
} | ||
|
||
func cleanArgs(args []string) ([]string, error) { | ||
if len(args) == 0 { | ||
abs, err := filepath.Abs(".") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return []string{abs}, nil | ||
} | ||
|
||
var expanded []string | ||
for _, arg := range args { | ||
abs, err := filepath.Abs(strings.ReplaceAll(arg, "...", "")) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
expanded = append(expanded, abs) | ||
} | ||
|
||
return expanded, nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package config | ||
|
||
type Formatters struct { | ||
Enable []string `mapstructure:"enable"` | ||
Settings FormatterSettings `mapstructure:"settings"` | ||
Exclusions FormatterExclusions `mapstructure:"exclusions"` | ||
} | ||
|
||
type FormatterExclusions struct { | ||
Generated string `mapstructure:"generated"` | ||
Paths []string `mapstructure:"paths"` | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package config | ||
|
||
var defaultFormatterSettings = FormatterSettings{ | ||
GoFmt: GoFmtSettings{ | ||
Simplify: true, | ||
}, | ||
Gci: GciSettings{ | ||
Sections: []string{"standard", "default"}, | ||
SkipGenerated: true, | ||
}, | ||
} | ||
|
||
type FormatterSettings struct { | ||
Gci GciSettings `mapstructure:"gci"` | ||
GoFmt GoFmtSettings `mapstructure:"gofmt"` | ||
GoFumpt GoFumptSettings `mapstructure:"gofumpt"` | ||
ldez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
GoImports GoImportsSettings `mapstructure:"goimports"` | ||
} | ||
|
||
type GciSettings struct { | ||
Sections []string `mapstructure:"sections"` | ||
NoInlineComments bool `mapstructure:"no-inline-comments"` | ||
NoPrefixComments bool `mapstructure:"no-prefix-comments"` | ||
SkipGenerated bool `mapstructure:"skip-generated"` | ||
CustomOrder bool `mapstructure:"custom-order"` | ||
NoLexOrder bool `mapstructure:"no-lex-order"` | ||
|
||
// Deprecated: use Sections instead. | ||
LocalPrefixes string `mapstructure:"local-prefixes"` | ||
} | ||
|
||
type GoFmtSettings struct { | ||
Simplify bool | ||
RewriteRules []GoFmtRewriteRule `mapstructure:"rewrite-rules"` | ||
} | ||
|
||
type GoFmtRewriteRule struct { | ||
Pattern string | ||
Replacement string | ||
} | ||
|
||
type GoFumptSettings struct { | ||
ModulePath string `mapstructure:"module-path"` | ||
ExtraRules bool `mapstructure:"extra-rules"` | ||
|
||
// Deprecated: use the global `run.go` instead. | ||
LangVersion string `mapstructure:"lang-version"` | ||
} | ||
|
||
type GoImportsSettings struct { | ||
LocalPrefixes string `mapstructure:"local-prefixes"` | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.