diff --git a/checks/go.star b/checks/go.star index 6e50c28..fe24628 100644 --- a/checks/go.star +++ b/checks/go.star @@ -262,3 +262,62 @@ def no_fork_without_lock(ctx): col = int(match.groups[3]), message = finding["message"], ) + +def govet( + ctx, + # `go vet` has a lot of overlap with other linters, only include + # analyzers that aren't enforced by the other linters. + analyzers = [ + "copylocks", + ]): + """Checks that exec.Command Start() and Run() aren't called directly. + + Instead, callers should use the `execsupport` package, which provides appropriate + locks to make sure forks are safe. + + Args: + ctx: A ctx instance. + analyzers: Names of analyzers to run (run `go tool vet help` to see all + options). + """ + output = ctx.os.exec( + [ + "go", + "vet", + "-json", + ] + + ["-" + a for a in analyzers] + + ["./..."], + env = go_env(), + ).wait().stderr + + # output is of the form: + # # pkg1 + # {} + # # pkg2 + # { + # ... + # } + findings_by_package = {} + current_package_lines = [] + lines = output.splitlines() + for i, line in enumerate(lines): + if not line.startswith("# "): + current_package_lines.append(line) + if i + 1 < len(lines): + continue + if current_package_lines: + findings_by_package.update(json.decode("\n".join(current_package_lines))) + current_package_lines = [] + + for pkg_findings in findings_by_package.values(): + for check_findings in pkg_findings.values(): + for finding in check_findings: + match = ctx.re.match(r"^%s/(.+):(\d+):(\d+)$" % ctx.scm.root, finding["posn"]) + ctx.emit.finding( + level = "error", + filepath = match.groups[1], + line = int(match.groups[2]), + col = int(match.groups[3]), + message = finding["message"], + ) diff --git a/shac.star b/shac.star index 8605c4b..21132d9 100644 --- a/shac.star +++ b/shac.star @@ -19,7 +19,7 @@ This file will evolve as new shac functionality is being added. load("//checks/buildifier.star", "buildifier") load("//checks/check_doc.star", "check_docs") -load("//checks/go.star", "gofmt", "gosec", "ineffassign", "no_fork_without_lock", "shadow", "staticcheck") +load("//checks/go.star", "gofmt", "gosec", "govet", "ineffassign", "no_fork_without_lock", "shadow", "staticcheck") load("//checks/licenses.star", "check_license_headers") def suggest_version_bump(ctx): @@ -74,6 +74,7 @@ shac.register_check(check_docs) shac.register_check(check_license_headers) shac.register_check(gofmt) shac.register_check(gosec) +shac.register_check(govet) shac.register_check(ineffassign) shac.register_check(new_todos) shac.register_check(no_fork_without_lock)