lint

package module
Version: v0.0.0-...-f90256a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2017 License: Apache-2.0 Imports: 10 Imported by: 0

README

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.

Documentation

Overview

Package lint runs linters as part of go test.

It is intended to be used as a substitute for an external build step that runs tools such as go vet or golint.

Example
package main

import (
	"log"

	"github.com/surullabs/lint"
)

func main() {
	// Run the default set of linters
	err := lint.Default.Check("./...")

	// Ignore all errors from the file unused.go.
	//
	// This is intended as an example of how to skip errors and not a
	// recommendation that you skip these kinds of errors.
	err = lint.Skip(err, lint.RegexpMatch(
		`unused\.go:4:2: a blank import`,
		`unused\.go:7:7: don't use underscores in Go names`,
	))

	if err != nil {
		// Record lint failures.
		// Use t.Fatal(err) when running in a test
		log.Fatal(err)
	}
}
Output:

Example (Custom)
package main

import (
	"log"

	"github.com/surullabs/lint"
	"github.com/surullabs/lint/gofmt"
	"github.com/surullabs/lint/govet"
)

func main() {
	// Run a custom set of linters
	custom := lint.Group{
		gofmt.Check{}, govet.Check{},
	}
	if err := custom.Check("./..."); err != nil {
		// Record lint failures.
		// Use t.Fatal(err) when running in a test
		log.Fatal(err)
	}
}
Output:

Example (Packages)
package main

import (
	"log"

	"github.com/surullabs/lint"
	"github.com/surullabs/lint/gofmt"
	"github.com/surullabs/lint/govet"
)

func main() {
	custom := lint.Group{gofmt.Check{}, govet.Check{}}

	// Specify a list of packages instead of the wildcard
	if err := custom.Check(".", "./checkers"); err != nil {
		// Record lint failures.
		// Use t.Fatal(err) when running in a test
		log.Fatal(err)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

Default holds a default list of lint tools for convenient use. These include

- gofmt -d
- go tool vet -shadow
- golint
- gosimple (https://github.com/dominikh/go-simple)
- gostaticcheck (https://github.com/dominikh/go-staticcheck)
- errcheck (https://github.com/kisielk/errcheck)

Functions

func Skip

func Skip(err error, skippers ...Skipper) error

Skip filters errors using skippers. If err satisfies the below interface

type errors interface {
	Errors() []string
}

the filters are applied to each string returned by Errors and then concatenated. If the error implements the above interface, it is guaranteed that any returned error will also implement the same.

Skippers are run in the order provided and a single skipper returning true will result in that error being skipped.

Types

type Checker

type Checker interface {
	Check(pkgs ...string) error
}

Checker is the interface that wraps the Check method.

Check lints all files in pkgs. Each item in pkgs may be a fully qualified import path, relative import path or a path with the wildcard suffix ...

type Group

type Group []Checker

Group is a Checker list that is applied in sequence. See Check for details on how it is applied.

func (Group) Check

func (g Group) Check(pkgs ...string) error

Check applies each of checkers in g in the order provided.

The error returned is either nil or contains errors returned by each Checker. These are exposed using the errors interface described in Skip and prefixed with the type of the Checker that generated the error. For example, the following error generated by govet.Checker:

file.go:23: err is unintentionally shadowed.

is converted to:

govet.Checker: file.go:23: err is unintentionally shadowed.

A checker is not shorted-circuited by a previous checker returning an error.

Any error that implements errors is flattened into the final error list.

func (Group) With

func (g Group) With(checkers ...Checker) Group

With returns a copy of g with checkers appended

type Skipper

type Skipper interface {
	Skip(err string) bool
}

Skipper is the interface that wraps the Skip method.

Skip returns true if err is an error that must be ignored.

func RegexpMatch

func RegexpMatch(regexps ...string) Skipper

RegexpMatch returns a Skipper that skips all errors which match any of the provided regular expression patterns. SkipRegexpMatch expects all patterns to be valid regexps and panics otherwise.

type StringSkipper

type StringSkipper struct {
	Strings []string
	Matcher func(err, str string) bool
}

StringSkipper implements Skipper and skips an error if Matcher(err, str) == true for any of Strings

func (StringSkipper) Skip

func (s StringSkipper) Skip(check string) bool

Skip returns true if Matcher(check, str) == true for any of Strings.

Directories

Path Synopsis
Package aligncheck provides lint integration for the aligncheck linter
Package aligncheck provides lint integration for the aligncheck linter
Package checkers provides utilities for implementing lint checkers.
Package checkers provides utilities for implementing lint checkers.
Package errcheck provides lint integration for the errcheck linter
Package errcheck provides lint integration for the errcheck linter
_vendored/src/github.com/alecthomas/template
Package template implements data-driven templates for generating textual output.
Package template implements data-driven templates for generating textual output.
_vendored/src/github.com/alecthomas/template/parse
Package parse builds parse trees for templates as defined by text/template and html/template.
Package parse builds parse trees for templates as defined by text/template and html/template.
_vendored/src/github.com/alecthomas/units
Package units provides helpful unit multipliers and functions for Go.
Package units provides helpful unit multipliers and functions for Go.
_vendored/src/github.com/google/shlex
Package shlex implements a simple lexer which splits input in to tokens using shell-style rules for quoting and commenting.
Package shlex implements a simple lexer which splits input in to tokens using shell-style rules for quoting and commenting.
_vendored/src/github.com/stretchr/testify/assert
Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
_vendored/src/gopkg.in/alecthomas/kingpin.v2
Package kingpin provides command line interfaces like this: $ chat usage: chat [<flags>] <command> [<flags>] [<args> ...] Flags: --debug enable debug mode --help Show help.
Package kingpin provides command line interfaces like this: $ chat usage: chat [<flags>] <command> [<flags>] [<args> ...] Flags: --debug enable debug mode --help Show help.
Package structcheck provides lint integration for the structcheck linter
Package structcheck provides lint integration for the structcheck linter
Package testutil contains methods to test checkers.
Package testutil contains methods to test checkers.
Package varcheck provides lint integration for the varcheck linter
Package varcheck provides lint integration for the varcheck linter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL