pairedbrackets

command module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2022 License: MIT Imports: 12 Imported by: 0

README

pairedbrackets
go.mod version CI Codecov Codebeat Maintainability Go Report Card License Go Reference

Linter checks formatting of paired brackets (inspired by this article).

Rule

According to the original notation, "a bracket should either start/end a line or be paired on the same line".
With modification for multiline items, the following cases are allowed:

  1. Both brackets and all items are in one line.
    fmt.Printf("%s, %s!", "Hello", "world")
    
  2. Left (opening) bracket is the last character on a line and right (closing) bracket starts a new line.
    fmt.Printf( // comments and whitespaces are ignored
    	"%s, %s!", "Hello", "world",
    )
    
  3. If the last item is multiline, it can start on the same line with the left bracket.
    In this case, the right bracket should be on the same line where the last item ends.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    	...
    })
    

Linter reports (wordings):

x.go:1:16: left parenthesis should either be the last character on a line or be on the same line with the last argument

               ⬇
http.HandleFunc("/",
	func(w http.ResponseWriter, r *http.Request) {
		...
	},
)

x.go:4:1: right parenthesis should be on the previous line

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	...
},
)
⬆

x.go:5:3: right parenthesis should be on the next line

http.HandleFunc(
	"/",
	func(w http.ResponseWriter, r *http.Request) {
		...
	})
	 ⬆

Examples

Function/method call
BadGood
fmt.Printf("%s, %s!",
	"Hello", "world")
fmt.Printf("%s, %s!",
	"Hello", "world",
)
fmt.Printf(
	"%s, %s!",
	"Hello", "world")
fmt.Printf("%s %s", "Last", `item
is multiline`,
)
fmt.Printf("%s, %s!", "Hello", "world")
fmt.Printf(
	"%s, %s!", "Hello", "world",
)
fmt.Printf(
	"%s, %s!",
	"Hello", "world",
)
fmt.Printf("%s %s", "Last", `item
is multiline`)

Functions from github.com/stretchr/testify/assert and github.com/stretchr/testify/require are ignored by default (see config).

Composite literal
BadGood
foo := []int{1,
	2, 3}
foo := []int{1,
	2, 3,
}
foo := []int{
	1,
	2,
	3}
foo := []string{"Last", "item", `is
multiline`,
}
bar := []int{1, 2, 3}
bar := []int{
	1,
	2,
	3,
}
bar := []int{
	1, 2, 3,
}
bar := []string{"Last", "item", `is
multiline`}
Function parameters
BadGood
func Foo(a int,
	b string, c bool) {
	...
}
func Foo(a int,
	b string, c bool,
) {
	...
}
func Foo(
	a int,
	b string,
	c bool) {
	...
}
func Foo(a int, b string,
) {
	...
}
func Foo(a int, b struct {
	X int
	Y string
},
) {
	...
}
func Bar(a int, b string) {
	...
}
func Bar(
	a int,
	b string,
	c bool,
) {
	...
}
func Bar(
	a int, b string, c bool,
) {
	...
}
func Bar(a int, b struct {
	X int
	Y string
}) {
	...
}
Function type parameters (generics)
BadGood
func Foo[T int,
	V string]() {
	...
}
func Foo[T int,
	V string,
]() {
	...
}
func Foo[
	T int,
	V string]() {
	...
}
func Foo[T int, V string,
]() {
	...
}
func Foo[T int, V interface {
	int | string
},
]() {
	...
}
func Bar[T int, V string]() {
	...
}
func Bar[
	T int,
	V string,
]() {
	...
}
func Bar[
	T int, V string,
]() {
	...
}
func Bar[T int, V interface {
	int | string
}]() {
	...
}
Function returns (output parameters)
BadGood
func Foo() (int,
	error) {
	...
}
func Foo() (int,
	error,
) {
	...
}
func Foo() (
	int,
	error) {
	...
}
func Foo() (int, error,
) {
	...
}
func Foo() (int, interface {
	Error()
},
) {
	...
}
func Bar() (int, error) {
	...
}
func Bar() (
	int,
	error,
) {
	...
}
func Bar() (
	int, error,
) {
	...
}
func Bar() (int, interface {
	Error()
}) {
	...
}

Other tools

gofmt

gofmt fixes many cases, which pairedbrackets complains about. But not all of them. All examples above formatted correctly according to gofmt.

gofumpt

gofumpt is just a slightly better than gofmt. It fixes some composite literal examples above. But not all of them, and it doesn't fix other examples.

Usage

You can use golangci-lint.
Unfortunately, v1 was rejected to be a built-in linter (hopefully v2 will be accepted). You can configure pairedbrackets as a plugin.

Install golangci-lint

Prebuilt binaries doesn't support plugins (see discussion), so you have to build golangci-lint:

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Install pairedbrackets
go install github.com/maratori/pairedbrackets@latest
Build plugin
pairedbrackets -build-golangci-lint-plugin

pairedbrackets.so will be created in current working directory. You can change the output path with flag -plugin-output (see other flags in help as well).

Config

pairedbrackets is disabled by default.
To enable it, add the following to your .golangci.yml:

linters-settings:
  custom:
     pairedbrackets:
        path: /path/to/plugin/pairedbrackets.so
        description: The linter checks formatting of paired brackets
        original-url: github.com/maratori/pairedbrackets
linters:
  enable:
     pairedbrackets
Run
golangci-lint run

Usage as standalone linter

Install
go install github.com/maratori/pairedbrackets@latest
Run
pairedbrackets ./...
Flag -ignore-func-calls

Flag -ignore-func-calls is a comma separated list of regexp patterns of fully qualified function calls to ignore. Default is github.com/stretchr/testify/assert,github.com/stretchr/testify/require.

Fully qualified function examples:

  • Function: github.com/stretchr/testify/require.Equal
  • Method: (*github.com/stretchr/testify/assert.Assertions).Equal

License

MIT License

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

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