go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/cli/cmds/lint/lint.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package lint implements 'lint' subcommand. 16 package lint 17 18 import ( 19 "context" 20 "fmt" 21 "os" 22 23 "github.com/maruel/subcommands" 24 25 "go.chromium.org/luci/common/cli" 26 luciflag "go.chromium.org/luci/common/flag" 27 28 "go.chromium.org/luci/lucicfg/buildifier" 29 "go.chromium.org/luci/lucicfg/cli/base" 30 ) 31 32 // Cmd is 'lint' subcommand. 33 func Cmd(params base.Parameters) *subcommands.Command { 34 return &subcommands.Command{ 35 UsageLine: "lint [options] [files...]", 36 ShortDesc: "applies linter checks to *.star files", 37 LongDesc: `Applies linter checks to the given Starlark files.`, 38 CommandRun: func() subcommands.CommandRun { 39 lr := &lintRun{checks: []string{"default"}} 40 lr.Init(params) 41 lr.Flags.Var(luciflag.CommaList(&lr.checks), "checks", "Apply these lint checks.") 42 return lr 43 }, 44 } 45 } 46 47 type lintRun struct { 48 base.Subcommand 49 50 checks []string 51 } 52 53 type lintResult struct { 54 // LinterFindings is all discovered linter warnings. 55 LinterFindings []*buildifier.Finding `json:"linter_findings,omitempty"` 56 } 57 58 func (lr *lintRun) Run(a subcommands.Application, args []string, env subcommands.Env) int { 59 if !lr.CheckArgs(args, 0, -1) { 60 return 1 61 } 62 ctx := cli.GetContext(a, lr, env) 63 return lr.Done(lr.run(ctx, args)) 64 } 65 66 func (lr *lintRun) run(ctx context.Context, inputs []string) (res *lintResult, err error) { 67 files, err := base.ExpandDirectories(inputs) 68 if err != nil { 69 return nil, err 70 } 71 72 rewriterFactory, err := base.GuessRewriterFactoryFunc(files) 73 if err != nil { 74 return nil, err 75 } 76 77 findings, err := buildifier.Lint(base.PathLoader, files, lr.checks, rewriterFactory.GetRewriter) 78 for _, f := range findings { 79 if text := f.Format(); text != "" { 80 fmt.Fprintf(os.Stderr, "%s", text) 81 } 82 } 83 return &lintResult{LinterFindings: findings}, err 84 }