Run linters from Go code -

Lint - run linters from Go

Build Status GoDoc Coverage StatusGo Report Card

Lint makes it easy to run linters from Go code. This allows lint checks to be part of a regular go build + go test workflow. False positives are easily ignored and linters are automatically integrated into CI pipelines without any extra effort. Check the project website to learn more about how it can be useful.

Quick Start

Download using

go get -t github.com/surullabs/lint

Run the default linters by adding a new test at the top level of your repository

func TestLint(t *testing.T) {
    // Run default linters
    err := lint.Default.Check("./...")
    
    // Ignore lint errors from auto-generated files
    err = lint.Skip(err, lint.RegexpMatch(`_string\.go`, `\.pb\.go`))
    
    if err != nil {
        t.Fatal("lint failures: %v", err)
    }
}

How it works

lint runs linters using the excellent os/exec package. It searches all Go binary directories for the needed binaries and when they don't exist it downloads them using go get. Errors generated by running linters are split by newline and can be skipped as needed.

Default linters

Using gometalinter

Gometalinter runs a number of linters concurrently. It also vendors each of these and uses the vendored versions automatically. A vendored version of gometalinter is included and can be used in the following manner. Please note that not all linters used by gometalinter have been tested.

import (
    "testing"
    "github.com/surullabs/lint/gometalinter"
)

func TestLint(t *testing.T) {
    // Run default linters
    metalinter := gometalinter.Check{
        Args: []string{
            // Arguments to gometalinter. Do not include the package names here.
        },
    }
    if err := metalinter.Check("./..."); err != nil {
        t.Fatal("lint failures: %v", err)
    }
}

Other available linters

Why lint?

There are a number of excellent linters available for Go and Lint makes it easy to run them from tests. While building our mobile calendar app TimeFerret, (which is built primarily in Go), including scripts that run linters as part of every repository grew tiresome very soon. Using lint to create tests that ran on each commit made the codebase much more stable, since any unneeded false positives were easily skipped. The main advantages of using lint over running tools manually is:

  • Skip false positives explicitly in your tests - This makes it easy to run only needed checks.
  • Enforce linter usage with no overhead - No special build scripts are needed to install linters on each developer machine as they are automatically downloaded.
  • Simple CI integration - Since linters are run as part of tests, there are no extra steps needed to integrate them into your CI pipeline.

Adding a custom linter

Please check if you can use the gometalinter package first. If not, adding a new linter is made dead simple by the github.com/surullabs/lint/checkers package. The entire source for the golint integration is

import "github.com/surullabs/lint/checkers"

type Check struct {
}

func (Check) Check(pkgs ...string) error {
    return checkers.Lint("golint", "", github.com/golang/lint/golint", pkgs)
}

The github.com/surullabs/lint/testutil package contains utilities for testing custom linters.

You can also take a look at this CL which adds varcheck for an example of how to add a linter.

If you'd like to vendor the linter source, please use the same method as the gometalinter package.

License

Lint is available under the Apache License. See the LICENSE file for details.

Contributing

Pull requests are always welcome! Please ensure any changes you send have an accompanying test case.

Comments
  • go vet false positive with input from list of file `*.go`

    go vet false positive with input from list of file `*.go`

    I have default linter on top of 3 repository and it output false positive go vet error.

    ~/testlinter/src/meomap] 12s $ go test --run TestLint
    --- FAIL: TestLint (2.33s)
            lint_test.go:17: lint failures: govet.Check: /Users/meomap/testlinter/src/meomap/b/main.go:9: declaration of "foo" shadows declaration at /Users/meomap/testlinter/src/meomap/a/main.go:3
    FAIL
    exit status 1
    FAIL    meomap  2.342s
    

    It seems the linter run this go vet command

    $ go tool vet --shadow a/main.go b/main.go c/main.go 
    

    and I opened an issue at golang project here but it closed

    https://github.com/golang/go/issues/18018

    Is there any reason why the vet command have to run with list of *.go file instead of greedy argument . ?

  • Support vendoring linters

    Support vendoring linters

    As suggested by @fortytw2 in #2, vendoring linters (especially gometalinter) will make it much easier to run this as part of a test suite since no internet access is needed.

    Requirements

    • Vendoring will need to be done so that it can be easily overridden if necessary.
    • It should work independently of any package managers.
    • There is no requirement that it use the Go vendoring system
  • makes gofmt errors separate

    makes gofmt errors separate

    This PR to make gofmt errors separate. Currently it is treated as one error so if we use lint.Skip to ignore a file (that happens to have gofmt error), all other gofmt errors are ignored.

  • gosimple, gostaticcheck: no option for build tags

    gosimple, gostaticcheck: no option for build tags

    To test a package with staticcheck or gosimple, I would need to pass some build tags, as I could do with errcheck:

    errcheck.Check{
    	Tags: "tag",
    },
    

    but gosimple.Check or gostaticcheck.Check do not take any tags as parameters, even though the tools themselves support them:

    $ staticcheck --help
    Usage of staticcheck:
    	staticcheck [flags] # runs on package in current directory
    	staticcheck [flags] packages
    	staticcheck [flags] directory
    	staticcheck [flags] files... # must be a single package
    Flags:
      -ignore string
        	Space separated list of checks to ignore, in the following format: 'import/path/file.go:Check1,Check2,...' Both the import path and file name sections support globbing, e.g. 'os/exec/*_test.go'
      -min_confidence float
        	Deprecated; use -ignore instead
      -tags build tags
        	List of build tags
    
    $ gosimple --help
    Usage of gosimple:
    	gosimple [flags] # runs on package in current directory
    	gosimple [flags] packages
    	gosimple [flags] directory
    	gosimple [flags] files... # must be a single package
    Flags:
      -ignore string
        	Space separated list of checks to ignore, in the following format: 'import/path/file.go:Check1,Check2,...' Both the import path and file name sections support globbing, e.g. 'os/exec/*_test.go'
      -min_confidence float
        	Deprecated; use -ignore instead
      -tags build tags
        	List of build tags
    

    Is it just missing implementation or am I missing something?

  • Build failing on Travis but not locally

    Build failing on Travis but not locally

    https://travis-ci.org/surullabs/lint/builds/177229429

    --- FAIL: TestGosimple (0.98s)
    	testutil.go:55: Check 1 /tmp/gosimpletest794064390/src/gosimpletest/file.go:6:1: expected declaration, found 'IDENT' sfsff
    		/tmp/gosimpletest794064390/src/gosimpletest/file.go:4:2: "fmt" imported but not used
    		/tmp/gosimpletest794064390/src/gosimpletest/file.go:4:2: "fmt" imported but not used
    		2016/11/19 08:38:32 couldn't load packages due to errors: gosimpletest
    	testutil.go:55: Check 2 /tmp/gosimpletest512030637/src/gosimpletest/file.go:3:2: "fmt" imported but not used
    		/tmp/gosimpletest512030637/src/gosimpletest/file.go:3:2: "fmt" imported but not used
    		2016/11/19 08:38:32 couldn't load packages due to errors: gosimpletest
    FAIL
    coverage: 57.1% of statements in github.com/surullabs/lint/gosimple, github.com/surullabs/lint/checkers
    FAIL	github.com/surullabs/lint/gosimple	0.990s
    --- FAIL: TestGostaticcheck (0.99s)
    	testutil.go:55: Check 1 /tmp/gostaticchecktest241190326/src/gostaticchecktest/file.go:6:1: expected declaration, found 'IDENT' sfsff
    		/tmp/gostaticchecktest241190326/src/gostaticchecktest/file.go:4:2: "fmt" imported but not used
    		/tmp/gostaticchecktest241190326/src/gostaticchecktest/file.go:4:2: "fmt" imported but not used
    		2016/11/19 08:38:35 couldn't load packages due to errors: gostaticchecktest
    	testutil.go:55: Check 2 /tmp/gostaticchecktest611298205/src/gostaticchecktest/file.go:3:2: "fmt" imported but not used
    		/tmp/gostaticchecktest611298205/src/gostaticchecktest/file.go:3:2: "fmt" imported but not used
    		2016/11/19 08:38:35 couldn't load packages due to errors: gostaticchecktest
    

    The change that triggered this error hasn't touched any of the failing packages.

  • Update paths for staticcheck and gosimple

    Update paths for staticcheck and gosimple

    The paths have been changed:

    From https://groups.google.com/forum/#!topic/golang-nuts/fQQiO4OPdmQ

    
    I have consolidated all of my Go tools in one place at
    honnef.co/go/tools (backed by github.com/dominikh/go-tools)
    
    This has changed a number of import paths. The command lines for
    the tools now live at honnef.co/go/tools/cmd – for example,
    staticcheck has moved from
    honnef.co/go/staticcheck/cmd/staticcheck to
    honnef.co/go/tools/cmd/staticcheck. Similarly, the supporting
    libraries have moved to honnef.co/go/tools as well.
    
    In order to make the transition as pain-free as possible, the old
    import paths and GitHub repositories will keep working for a
    limited time. Concretely, the following deprecation schedule is in
    place:
    
    1. Beginning now, the authoritative place for all code, issues
    and pull requests is at github.com/dominikh/go-tools. The old
    repositories will not receive new features or bug fixes. The old
    import paths will – out of necessity – keep pointing to the old
    repositories.
    
    2. Starting March 1st, tools installed from the old locations
    will unconditionally exit with a non-zero status code and emit a
    deprecation warning. They will otherwise keep functioning like
    normal.
    
    3. Starting April 1st, all code in the old locations will be
    removed and replaced with a single file causing a build failure,
    instructing users to use the new location.
    
    I am sorry for the inconvenience this causes. However, developing
    all tools in a single repository will have benefits in the long
    run and is worth the disruption.
    
    Cheers,
    Dominik
    
  • defer raises 'return value not checked'

    defer raises 'return value not checked'

    internal/cert/utils.go:72:16: Error return value of `cmd.Wait` is not checked (errcheck)
            defer cmd.Wait()
                          ^
    

    I think this is a bug, since defer will check the error status. See https://golang.org/ref/spec#Defer_statements

    If a deferred function value evaluates to nil, execution panics.

Related tags
Fast linters Runner for Go
Fast linters Runner for Go

golangci-lint Fast linters runner for Go golangci-lint is a fast Go linters runner. It runs linters in parallel, uses caching, supports yaml config, h

Jan 8, 2023
Custom linters

Raftt Raftt linters This package contains Go linters for use in Raftt projects. Linters discardedreturn This linter checks for discarded return values

Dec 5, 2021
octocov is a tool for collecting code metrics (code coverage, code to test ratio and test execution time).

octocov is a tool for collecting code metrics (code coverage, code to test ratio and test execution time).

Jan 9, 2023
The most opinionated Go source code linter for code audit.
The most opinionated Go source code linter for code audit.

go-critic Highly extensible Go source code linter providing checks currently missing from other linters. There is never too much static code analysis.

Jan 6, 2023
🐶 Automated code review tool integrated with any code analysis tools regardless of programming language
🐶 Automated code review tool integrated with any code analysis tools regardless of programming language

reviewdog - A code review dog who keeps your codebase healthy. reviewdog provides a way to post review comments to code hosting service, such as GitHu

Jan 2, 2023
A Golang tool that does static analysis, unit testing, code review and generate code quality report.
A Golang tool that does static analysis, unit testing, code review and generate code quality report.

goreporter A Golang tool that does static analysis, unit testing, code review and generate code quality report. This is a tool that concurrently runs

Jan 8, 2023
Sloc, Cloc and Code: scc is a very fast accurate code counter with complexity calculations and COCOMO estimates written in pure Go
Sloc, Cloc and Code: scc is a very fast accurate code counter with complexity calculations and COCOMO estimates written in pure Go

Sloc Cloc and Code (scc) A tool similar to cloc, sloccount and tokei. For counting physical the lines of code, blank lines, comment lines, and physica

Jan 4, 2023
🐶 Automated code review tool integrated with any code analysis tools regardless of programming language
🐶 Automated code review tool integrated with any code analysis tools regardless of programming language

reviewdog - A code review dog who keeps your codebase healthy. reviewdog provides a way to post review comments to code hosting service, such as GitHu

Jan 7, 2023
a tool for code clone detection

dupl dupl is a tool written in Go for finding code clones. So far it can find clones only in the Go source files. The method uses suffix tree for seri

Dec 12, 2022
[mirror] This is a linter for Go source code.

Golint is a linter for Go source code. Installation Golint requires a supported release of Go. go get -u golang.org/x/lint/golint To find out where g

Dec 23, 2022
depth is tool to retrieve and visualize Go source code dependency trees.

depth is tool to retrieve and visualize Go source code dependency trees. Install Download the appropriate binary for your platform from the Rele

Dec 30, 2022
A reference for the Go community that covers the fundamentals of writing clean code and discusses concrete refactoring examples specific to Go.

A reference for the Go community that covers the fundamentals of writing clean code and discusses concrete refactoring examples specific to Go.

Jan 1, 2023
Tool to populate your code with traceable and secure error codes

Essential part of any project, especially customer facing is proper and secure error handling. When error happens and customer reports it, it would be nice to know the context of the error and where it exactly occured.

Sep 28, 2022
A static code analyzer for annotated TODO comments
A static code analyzer for annotated TODO comments

todocheck todocheck is a static code analyzer for annotated TODO comments. It let's you create actionable TODOs by annotating them with issues from an

Dec 7, 2022
A little fast cloc(Count Lines Of Code)

gocloc A little fast cloc(Count Lines Of Code), written in Go. Inspired by tokei. Installation $ go get -u github.com/hhatto/gocloc/cmd/gocloc Usage

Jan 6, 2023
🔒🌍 Security scanner for your Terraform code
🔒🌍 Security scanner for your Terraform code

????tfsec uses static analysis of your terraform templates to spot potential security issues.

Dec 30, 2022
Know when GC runs from inside your golang code

gcnotifier gcnotifier provides a way to receive notifications after every run of the garbage collector (GC). Knowing when GC runs is useful to instruc

Dec 26, 2022
a Go code to detect leaks in JS files via regex patterns

a Go code to detect leaks in JS files via regex patterns

Nov 13, 2022
a simple golang SSA viewer tool use for code analysis or make a linter
a simple golang SSA viewer tool use for code analysis or make a linter

ssaviewer A simple golang SSA viewer tool use for code analysis or make a linter ssa.html generate code modify from src/cmd/compile/internal/ssa/html.

May 17, 2022