From 00961cabba8a3310509272f07c5f9b81904f8ea4 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Sat, 22 Jan 2022 18:17:21 +0100 Subject: [PATCH 1/8] all: use cristalhq/acmd --- framework/lintmain/internal/check/check.go | 4 +- framework/lintmain/internal/lintdoc/doc.go | 11 ++-- framework/lintmain/lintmain.go | 60 +++++++--------------- go.mod | 1 + go.sum | 2 + 5 files changed, 33 insertions(+), 45 deletions(-) diff --git a/framework/lintmain/internal/check/check.go b/framework/lintmain/internal/check/check.go index f49bfc571..8e796a123 100644 --- a/framework/lintmain/internal/check/check.go +++ b/framework/lintmain/internal/check/check.go @@ -2,6 +2,7 @@ package check import ( "bytes" + "context" "errors" "flag" "fmt" @@ -27,7 +28,7 @@ import ( ) // Main implements sub-command entry point. -func Main() { +func Main(_ context.Context, _ []string) error { var p program p.infoList = linter.GetCheckersInfo() @@ -53,6 +54,7 @@ func Main() { log.Fatalf("%s: %v", step.name, err) } } + return nil } type program struct { diff --git a/framework/lintmain/internal/lintdoc/doc.go b/framework/lintmain/internal/lintdoc/doc.go index 331d3e568..08c760404 100644 --- a/framework/lintmain/internal/lintdoc/doc.go +++ b/framework/lintmain/internal/lintdoc/doc.go @@ -1,6 +1,7 @@ package lintdoc import ( + "context" "flag" "fmt" "log" @@ -12,10 +13,13 @@ import ( ) // Main implements sub-command entry point. -func Main() { - flag.Parse() +func Main(_ context.Context, args []string) error { + fs := flag.NewFlagSet("gocritic", flag.ContinueOnError) + if err := fs.Parse(args); err != nil { + return err + } - switch args := flag.Args(); len(args) { + switch args := fs.Args(); len(args) { case 0: printShortDoc() case 1: @@ -23,6 +27,7 @@ func Main() { default: log.Fatalf("expected 0 or 1 positional arguments") } + return nil } func printShortDoc() { diff --git a/framework/lintmain/lintmain.go b/framework/lintmain/lintmain.go index 77834f77f..5bd5baa1f 100644 --- a/framework/lintmain/lintmain.go +++ b/framework/lintmain/lintmain.go @@ -1,12 +1,12 @@ package lintmain import ( - "fmt" "log" - "github.com/go-critic/go-critic/framework/cmdutil" "github.com/go-critic/go-critic/framework/lintmain/internal/check" "github.com/go-critic/go-critic/framework/lintmain/internal/lintdoc" + + "github.com/cristalhq/acmd" ) // Config is used to parametrize the linter. @@ -20,44 +20,22 @@ type Config struct { func Run(cfg Config) { log.SetFlags(0) - printVersion := func() { - log.Println(cfg.Version) - } - - // makeExample replaces all ${linter} placeholders to a bound linter name. - makeExamples := func(examples ...string) []string { - for i := range examples { - examples[i] = fmt.Sprintf(examples[i], cfg.Name) - } - return examples - } - - subCommands := []*cmdutil.SubCommand{ - { - Main: check.Main, - Name: "check", - Short: "run linter over specified targets", - Examples: makeExamples( - "%s check -help", - "%s check -enable='paramTypeCombine,unslice' strings bytes", - "%s check -v -enable='#diagnostic' -disable='#experimental,#opinionated' ./..."), - }, - { - Main: printVersion, - Name: "version", - Short: "print linter version", - Examples: makeExamples("%s version"), - }, - { - Main: lintdoc.Main, - Name: "doc", - Short: "get installed checkers documentation", - Examples: makeExamples( - "%s doc -help", - "%s doc", - "%s doc checkerName"), - }, - } + r := acmd.RunnerOf(nil, acmd.Config{ + AppName: cfg.Name, + Version: cfg.Version, + }) + _ = r.Run() +} - cmdutil.DispatchCommand(subCommands) +var cmds = []acmd.Command{ + { + Name: "check", + Description: "run linter over specified targets", + Do: check.Main, + }, + { + Name: "doc", + Description: "get installed checkers documentation", + Do: lintdoc.Main, + }, } diff --git a/go.mod b/go.mod index 33d5838c0..9154ae734 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/go-critic/go-critic go 1.16 require ( + github.com/cristalhq/acmd v0.5.2 github.com/go-toolsmith/astcast v1.0.0 github.com/go-toolsmith/astcopy v1.0.0 github.com/go-toolsmith/astequal v1.0.1 diff --git a/go.sum b/go.sum index 963822a39..4453b315d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/cristalhq/acmd v0.5.2 h1:C4Rk7SfdSJviCmTrhSUrzHenAJaXPeijUr47waPMpkI= +github.com/cristalhq/acmd v0.5.2/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= From 594e2d66280aa8baf107b215752a3a9c535433bf Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Wed, 26 Jan 2022 18:01:26 +0100 Subject: [PATCH 2/8] fix --- framework/lintmain/lintmain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/lintmain/lintmain.go b/framework/lintmain/lintmain.go index 5bd5baa1f..311dc4c39 100644 --- a/framework/lintmain/lintmain.go +++ b/framework/lintmain/lintmain.go @@ -20,7 +20,7 @@ type Config struct { func Run(cfg Config) { log.SetFlags(0) - r := acmd.RunnerOf(nil, acmd.Config{ + r := acmd.RunnerOf(cmds, acmd.Config{ AppName: cfg.Name, Version: cfg.Version, }) From 02cdc62ca3242482cd22dd8861e1e5cb0b1bbd48 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Wed, 26 Jan 2022 18:29:41 +0100 Subject: [PATCH 3/8] fix --- framework/lintmain/internal/check/check.go | 41 ++++++++++++---------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/framework/lintmain/internal/check/check.go b/framework/lintmain/internal/check/check.go index 8e796a123..20d9443f9 100644 --- a/framework/lintmain/internal/check/check.go +++ b/framework/lintmain/internal/check/check.go @@ -28,8 +28,9 @@ import ( ) // Main implements sub-command entry point. -func Main(_ context.Context, _ []string) error { +func Main(_ context.Context, args []string) error { var p program + p.flagSet = flag.NewFlagSet("gocritic", flag.ContinueOnError) p.infoList = linter.GetCheckersInfo() steps := []struct { @@ -39,7 +40,7 @@ func Main(_ context.Context, _ []string) error { {"load plugin", p.loadPlugin}, {"bind checker params", p.bindCheckerParams}, {"bind default enabled list", p.bindDefaultEnabledList}, - {"parse args", p.parseArgs}, + {"parse args", func() error { return p.parseArgs(args) }}, {"start profiling", p.startProfiling}, {"assign checker params", p.assignCheckerParams}, {"load program", p.loadProgram}, @@ -60,6 +61,8 @@ func Main(_ context.Context, _ []string) error { type program struct { ctx *linter.Context + flagSet *flag.FlagSet + fset *token.FileSet loadedPackages []*packages.Package @@ -315,11 +318,11 @@ func (p *program) bindCheckerParams() error { key := p.checkerParamKey(info, pname) switch v := param.Value.(type) { case int: - intParams[key] = flag.Int(key, v, param.Usage) + intParams[key] = p.flagSet.Int(key, v, param.Usage) case bool: - boolParams[key] = flag.Bool(key, v, param.Usage) + boolParams[key] = p.flagSet.Bool(key, v, param.Usage) case string: - stringParams[key] = flag.String(key, v, param.Usage) + stringParams[key] = p.flagSet.String(key, v, param.Usage) default: panic("unreachable") // Checked in AddChecker } @@ -353,32 +356,34 @@ func (p *program) bindDefaultEnabledList() error { return nil } -func (p *program) parseArgs() error { - flag.BoolVar(&p.filters.enableAll, "enableAll", false, +func (p *program) parseArgs(args []string) error { + p.flagSet.BoolVar(&p.filters.enableAll, "enableAll", false, `identical to -enable with all checkers listed. If true, -enable is ignored`) - enable := flag.String("enable", strings.Join(p.filters.defaultCheckers, ","), + enable := p.flagSet.String("enable", strings.Join(p.filters.defaultCheckers, ","), `comma-separated list of enabled checkers. Can include #tags`) - disable := flag.String("disable", "", + disable := p.flagSet.String("disable", "", `comma-separated list of checkers to be disabled. Can include #tags`) - flag.IntVar(&p.exitCode, "exitCode", 1, + p.flagSet.IntVar(&p.exitCode, "exitCode", 1, `exit code to be used when lint issues are found`) - flag.BoolVar(&p.checkTests, "checkTests", true, + p.flagSet.BoolVar(&p.checkTests, "checkTests", true, `whether to check test files`) - flag.BoolVar(&p.shorterErrLocation, `shorterErrLocation`, true, + p.flagSet.BoolVar(&p.shorterErrLocation, `shorterErrLocation`, true, `whether to replace error location prefix with $GOROOT and $GOPATH`) - flag.BoolVar(&p.verbose, "v", false, + p.flagSet.BoolVar(&p.verbose, "v", false, `whether to print output useful during linter debugging`) - flag.StringVar(&p.goVersion, "go", "", + p.flagSet.StringVar(&p.goVersion, "go", "", `select the Go version to target. Leave as string for the latest`) - flag.StringVar(&p.memProfile, "memprofile", "", + p.flagSet.StringVar(&p.memProfile, "memprofile", "", `write memory profile to the specified file`) - flag.StringVar(&p.cpuProfile, "cpuprofile", "", + p.flagSet.StringVar(&p.cpuProfile, "cpuprofile", "", `write CPU profile to the specified file`) - flag.Parse() + if err := p.flagSet.Parse(args); err != nil { + return err + } - p.packages = flag.Args() + p.packages = p.flagSet.Args() p.filters.enable = strings.Split(*enable, ",") p.filters.disable = strings.Split(*disable, ",") From acb43d57345462016bdddc4bb872569e5564fdfd Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Wed, 26 Jan 2022 19:27:01 +0100 Subject: [PATCH 4/8] update --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9154ae734..8d3b6a931 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/go-critic/go-critic go 1.16 require ( - github.com/cristalhq/acmd v0.5.2 + github.com/cristalhq/acmd v0.5.3 github.com/go-toolsmith/astcast v1.0.0 github.com/go-toolsmith/astcopy v1.0.0 github.com/go-toolsmith/astequal v1.0.1 diff --git a/go.sum b/go.sum index 4453b315d..a8b24ec55 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/cristalhq/acmd v0.5.2 h1:C4Rk7SfdSJviCmTrhSUrzHenAJaXPeijUr47waPMpkI= -github.com/cristalhq/acmd v0.5.2/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= +github.com/cristalhq/acmd v0.5.3 h1:mKcPYdUpUELRQu84D6uklMFjU6nPTzUYXO8C1TgXpdI= +github.com/cristalhq/acmd v0.5.3/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= From 75de07b0b45f1dda122aed7683e1ad0333392480 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Wed, 26 Jan 2022 19:54:58 +0100 Subject: [PATCH 5/8] few fixes --- cmd/gocritic/main.go | 2 +- framework/lintmain/lintmain.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/gocritic/main.go b/cmd/gocritic/main.go index 40a7c6657..b469c89c2 100644 --- a/cmd/gocritic/main.go +++ b/cmd/gocritic/main.go @@ -5,7 +5,7 @@ import ( "github.com/go-critic/go-critic/framework/lintmain" ) -var Version string +var Version = "v0.0.0-SNAPSHOT" func main() { lintmain.Run(lintmain.Config{ diff --git a/framework/lintmain/lintmain.go b/framework/lintmain/lintmain.go index 311dc4c39..706ef97bb 100644 --- a/framework/lintmain/lintmain.go +++ b/framework/lintmain/lintmain.go @@ -24,7 +24,9 @@ func Run(cfg Config) { AppName: cfg.Name, Version: cfg.Version, }) - _ = r.Run() + if err := r.Run(); err != nil { + log.Print(err.Error()) + } } var cmds = []acmd.Command{ From b009699b543d0891c488f0594b5a90381c00b442 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Fri, 4 Feb 2022 09:43:47 +0100 Subject: [PATCH 6/8] wip --- framework/cmdutil/cmdutil.go | 72 ---------------------- framework/lintmain/internal/lintdoc/doc.go | 6 +- framework/lintmain/lintmain.go | 5 ++ go.mod | 2 + 4 files changed, 10 insertions(+), 75 deletions(-) delete mode 100644 framework/cmdutil/cmdutil.go diff --git a/framework/cmdutil/cmdutil.go b/framework/cmdutil/cmdutil.go deleted file mode 100644 index 6ca583290..000000000 --- a/framework/cmdutil/cmdutil.go +++ /dev/null @@ -1,72 +0,0 @@ -package cmdutil - -import ( - "log" - "os" -) - -// SubCommand is an implementation of a linter sub-command. -type SubCommand struct { - // Main is command entry point. - Main func() - - // Name is sub-command name used to execute it. - Name string - - // Short describes command in one line of text. - Short string - - // Examples shows one or more sub-command execution examples. - Examples []string -} - -// DispatchCommand runs sub command out of specified cmdList based on -// the first command line argument. -func DispatchCommand(cmdList []*SubCommand) { - argv := os.Args - if len(argv) < 2 { - log.Printf("not enough arguments, expected sub-command name\n\n") - printSubCommands(cmdList) - os.Exit(1) - } - - subIdx := 1 // [0] is program name - sub := os.Args[subIdx] - // Erase sub-command argument (index=1) to make it invisible for - // sub commands themselves. - os.Args = append(os.Args[:subIdx], os.Args[subIdx+1:]...) - - // Choose and run sub-command main. - cmd := findSubCommand(cmdList, sub) - if cmd == nil { - log.Printf("unknown sub-command: %s\n\n", sub) - printSubCommands(cmdList) - os.Exit(1) - } else { - // The called function may exit with non-zero status. - // No code should follow this call. - cmd.Main() - } -} - -// findSubCommand looks up SubCommand by its name. -// Returns nil if requested command not found. -func findSubCommand(cmdList []*SubCommand, name string) *SubCommand { - for _, cmd := range cmdList { - if cmd.Name == name { - return cmd - } - } - return nil -} - -// printSubCommands prints cmdList info to the logger (usually stderr). -func printSubCommands(cmdList []*SubCommand) { - log.Println("Supported sub-commands:") - for _, cmd := range cmdList { - log.Printf("\t%s - %s", cmd.Name, cmd.Short) - for _, ex := range cmd.Examples { - log.Printf("\t\t$ %s", ex) - } - } -} diff --git a/framework/lintmain/internal/lintdoc/doc.go b/framework/lintmain/internal/lintdoc/doc.go index 08c760404..460911445 100644 --- a/framework/lintmain/internal/lintdoc/doc.go +++ b/framework/lintmain/internal/lintdoc/doc.go @@ -14,12 +14,12 @@ import ( // Main implements sub-command entry point. func Main(_ context.Context, args []string) error { - fs := flag.NewFlagSet("gocritic", flag.ContinueOnError) - if err := fs.Parse(args); err != nil { + flagSet := flag.NewFlagSet("gocritic", flag.ContinueOnError) + if err := flagSet.Parse(args); err != nil { return err } - switch args := fs.Args(); len(args) { + switch args := flagSet.Args(); len(args) { case 0: printShortDoc() case 1: diff --git a/framework/lintmain/lintmain.go b/framework/lintmain/lintmain.go index 706ef97bb..e610aea90 100644 --- a/framework/lintmain/lintmain.go +++ b/framework/lintmain/lintmain.go @@ -40,4 +40,9 @@ var cmds = []acmd.Command{ Description: "get installed checkers documentation", Do: lintdoc.Main, }, + { + Name: "__complete", + Description: "get installed checkers documentation", + Do: acmd.AutocompleteFor, + }, } diff --git a/go.mod b/go.mod index 8d3b6a931..0bc0c61b6 100644 --- a/go.mod +++ b/go.mod @@ -19,3 +19,5 @@ require ( golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da ) + +replace github.com/cristalhq/acmd => /Users/olegkovalov/code/hq/acmd \ No newline at end of file From 9888fc7627dc2132daf84f85b6faa5a0b2021c39 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Tue, 19 Apr 2022 10:39:30 +0200 Subject: [PATCH 7/8] Update go.mod --- go.mod | 4 +--- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 0bc0c61b6..4e1ae5874 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/go-critic/go-critic go 1.16 require ( - github.com/cristalhq/acmd v0.5.3 + github.com/cristalhq/acmd v0.5.7 github.com/go-toolsmith/astcast v1.0.0 github.com/go-toolsmith/astcopy v1.0.0 github.com/go-toolsmith/astequal v1.0.1 @@ -19,5 +19,3 @@ require ( golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da ) - -replace github.com/cristalhq/acmd => /Users/olegkovalov/code/hq/acmd \ No newline at end of file diff --git a/go.sum b/go.sum index a8b24ec55..8c105bfb1 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/cristalhq/acmd v0.5.3 h1:mKcPYdUpUELRQu84D6uklMFjU6nPTzUYXO8C1TgXpdI= -github.com/cristalhq/acmd v0.5.3/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= +github.com/cristalhq/acmd v0.5.7 h1:QBPleWdW8kVsn6VuiCNXhtbjvFuHlTvfPu7GR6J7EXQ= +github.com/cristalhq/acmd v0.5.7/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= From 49aaf2ba7710d6ab24e82c2299c0a2b15d0aa0e4 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Tue, 19 Apr 2022 10:41:43 +0200 Subject: [PATCH 8/8] Remove autocomplete try --- framework/lintmain/lintmain.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework/lintmain/lintmain.go b/framework/lintmain/lintmain.go index e610aea90..706ef97bb 100644 --- a/framework/lintmain/lintmain.go +++ b/framework/lintmain/lintmain.go @@ -40,9 +40,4 @@ var cmds = []acmd.Command{ Description: "get installed checkers documentation", Do: lintdoc.Main, }, - { - Name: "__complete", - Description: "get installed checkers documentation", - Do: acmd.AutocompleteFor, - }, }