GitXplorerGitXplorer
f

faillint

public
236 stars
20 forks
5 issues

Commits

List of commits on branch main.
Verified
24d8e46ee21be34778b85fce26fed0ad50210141

Merge pull request #44 from trevorwhitney/main

ffatih committed 3 months ago
Verified
bf42a79db7c90516e406800d3ffafed36de7242b

bump go version to 1.18

ttrevorwhitney committed 3 months ago
Verified
6cffdde9a529a941be22632e31df77284b1b936c

Merge pull request #43 from fatih/add-only-tests

ffatih committed 9 months ago
Unverified
42a2b64695483f309b6bd04e7f57dbb13266cc05

Add '--only-tests' support

ffatih committed 10 months ago
Verified
a9254ba1c3b4bf8681e1249b04c5629c00a598cd

Merge pull request #42 from fatih/update-ci-workflow

ffatih committed 10 months ago
Unverified
d6bd3ee66c3a087c8bc901b84320a012264c8e35

Update golang.org/x/tools

ffatih committed 10 months ago

README

The README file for this repository.

faillint

Faillint is a simple Go linter that fails when a specific set of import paths or exported path's functions, constant, vars or types are used. It's meant to be used in CI/CD environments to catch rules you want to enforce in your projects.

As an example, you could enforce the usage of github.com/pkg/errors instead of the errors package. To prevent the usage of the errors package, you can configure faillint to fail whenever someone imports the errors package in this case. To make sure fmt.Errorf is not used for creating errors as well, you can configure to fail on such single function of fmt as well.

faillint

Install

go install github.com/fatih/faillint@latest

Example

Assume we have the following file:

package a

import (
        "errors"
)

func foo() error {
        return errors.New("bar!")
}

Let's run faillint to check if errors import is used and report it:

$ faillint -paths "errors=github.com/pkg/errors" a.go
a.go:4:2: package "errors" shouldn't be imported, suggested: "github.com/pkg/errors"

Usage

faillint works on a file, directory or a Go package:

$ faillint -paths "errors,fmt.{Errorf}" foo.go # pass a file
$ faillint -paths "errors,fmt.{Errorf}" ./...  # recursively analyze all files
$ faillint -paths "errors,fmt.{Errorf}" github.com/fatih/gomodifytags # or pass a package

By default, faillint will not check any import paths. You need to explicitly define it with the -paths flag, which is comma-separated list. Some examples are:

# Fail if the errors package is used.
-paths "errors"

# Fail if the old context package is imported.
-paths "golang.org/x/net/context"

# Fail both on stdlib log and errors package to enforce other internal libraries.
-paths "log,errors"

# Fail if any of Print, Printf of Println function were used from fmt library.
-paths "fmt.{Print,Printf,Println}"

# Fail if the package is imported including sub paths starting with
  "golang.org/x/net/". In example: `golang.org/x/net/context`, 
  `golang.org/x/net/nettest`, .nettest`, ...
-paths "golang.org/x/net/..."

If you have a preferred import path to suggest, append the suggestion after a = character:

# Fail if the errors package is used and suggest to use github.com/pkg/errors.
-paths "errors=github.com/pkg/errors"

# Fail for the old context import path and suggest to use the stdlib context.
-paths "golang.org/x/net/context=context"

# Fail both on stdlib log and errors package to enforce other libraries.
-paths "log=go.uber.org/zap,errors=github.com/pkg/errors"

# Fail on fmt.Errorf and suggest the Errorf function from github.compkg/errors instead.
-paths "fmt.{Errorf}=github.com/pkg/errors.{Errorf}"

Ignoring problems

If you want to ignore a problem reported by faillint you can add a lint directive based on staticcheck's design.

Line-based lint directives

Line-based lint directives can be applied to imports or functions you want to tolerate. The format is,

//lint:ignore faillint reason

For example,

package a

import (
        //lint:ignore faillint Whatever your reason is.
        "errors"
        "fmt" //lint:ignore faillint Whatever your reason is.
)

func foo() error {
        //lint:ignore faillint Whatever your reason is.
        return errors.New("bar!")
}

File-based lint directives

File-based lint directives can be applied to ignore faillint problems in a whole file. The format is,

//lint:file-ignore faillint reason

This may be placed anywhere in the file but conventionally it should be placed at, or near, the top of the file.

For example,

//lint:file-ignore faillint This file should be ignored by faillint.

package a

import (
        "errors"
)

func foo() error {
        return errors.New("bar!")
}

The need for this tool?

Most of these checks should be probably detected during the review cycle. But it's totally normal to accidentally import them (we're all humans in the end).

Second, tools like goimports favors certain packages. As an example going forward if you decided to use github.com/pkg/errors in you project, and write errors.New() in a new file, goimports will automatically import the errors package (and not github.com/pkg/errors). The code will perfectly compile. faillint would be able to detect and report it to you.

Credits

This tool is built on top of the excellent go/analysis package that makes it easy to write custom analyzers in Go. If you're interested in writing a tool, check out my Using go/analysis to write a custom linter blog post.

Part of the code is modified and based on astutil.UsesImport