Bump wsl to v1.2.7
This commit is contained in:
parent
1248f098de
commit
14ebae2906
@ -223,10 +223,12 @@ linters-settings:
|
||||
allow-assign-and-call: true
|
||||
# Allow multiline assignments to be cuddled. Default is true.
|
||||
allow-multiline-assign: true
|
||||
# Allow case blocks to end with a whitespace.
|
||||
allow-case-traling-whitespace: true
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: false
|
||||
# Allow trailing comments in ending of blocks
|
||||
allow-trailing-comment: false
|
||||
# Force newlines in end of case at this limit (0 = never).
|
||||
force-case-trailing-whitespace: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
|
@ -824,10 +824,12 @@ linters-settings:
|
||||
allow-assign-and-call: true
|
||||
# Allow multiline assignments to be cuddled. Default is true.
|
||||
allow-multiline-assign: true
|
||||
# Allow case blocks to end with a whitespace.
|
||||
allow-case-traling-whitespace: true
|
||||
# Allow declarations (var) to be cuddled.
|
||||
allow-cuddle-declarations: false
|
||||
# Allow trailing comments in ending of blocks
|
||||
allow-trailing-comment: false
|
||||
# Force newlines in end of case at this limit (0 = never).
|
||||
force-case-trailing-whitespace: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
|
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/OpenPeeDeeP/depguard v1.0.1
|
||||
github.com/bombsimon/wsl v1.2.5
|
||||
github.com/bombsimon/wsl v1.2.7
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db
|
||||
github.com/go-lintpack/lintpack v0.5.2
|
||||
|
4
go.sum
4
go.sum
@ -11,8 +11,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bombsimon/wsl v1.2.5 h1:9gTOkIwVtoDZywvX802SDHokeX4kW1cKnV8ZTVAPkRs=
|
||||
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
|
||||
github.com/bombsimon/wsl v1.2.7 h1:hckBZYt27e6Ff6yqV/SurMUe48BmXzJk/KVjxDyWtUE=
|
||||
github.com/bombsimon/wsl v1.2.7/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
|
@ -255,11 +255,12 @@ type GocognitSettings struct {
|
||||
}
|
||||
|
||||
type WSLSettings struct {
|
||||
StrictAppend bool `mapstructure:"strict-append"`
|
||||
AllowAssignAndCallCuddle bool `mapstructure:"allow-assign-and-call"`
|
||||
AllowMultiLineAssignCuddle bool `mapstructure:"allow-multiline-assign"`
|
||||
AllowCaseTrailingWhitespace bool `mapstructure:"allow-case-trailing-whitespace"`
|
||||
AllowCuddleDeclaration bool `mapstructure:"allow-cuddle-declarations"`
|
||||
StrictAppend bool `mapstructure:"strict-append"`
|
||||
AllowAssignAndCallCuddle bool `mapstructure:"allow-assign-and-call"`
|
||||
AllowMultiLineAssignCuddle bool `mapstructure:"allow-multiline-assign"`
|
||||
AllowCuddleDeclaration bool `mapstructure:"allow-cuddle-declarations"`
|
||||
AllowTrailingComment bool `mapstructure:"allow-trailing-comment"`
|
||||
CaseForceTrailingWhitespaceLimit int `mapstructure:"force-case-trailing-whitespace:"`
|
||||
}
|
||||
|
||||
var defaultLintersSettings = LintersSettings{
|
||||
@ -291,11 +292,12 @@ var defaultLintersSettings = LintersSettings{
|
||||
MinComplexity: 30,
|
||||
},
|
||||
WSL: WSLSettings{
|
||||
StrictAppend: true,
|
||||
AllowAssignAndCallCuddle: true,
|
||||
AllowMultiLineAssignCuddle: true,
|
||||
AllowCaseTrailingWhitespace: true,
|
||||
AllowCuddleDeclaration: false,
|
||||
StrictAppend: true,
|
||||
AllowAssignAndCallCuddle: true,
|
||||
AllowMultiLineAssignCuddle: true,
|
||||
AllowCuddleDeclaration: false,
|
||||
AllowTrailingComment: false,
|
||||
CaseForceTrailingWhitespaceLimit: 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,14 @@ func NewWSL() *goanalysis.Linter {
|
||||
files = []string{}
|
||||
linterCfg = lintCtx.Cfg.LintersSettings.WSL
|
||||
processorCfg = wsl.Configuration{
|
||||
StrictAppend: linterCfg.StrictAppend,
|
||||
AllowAssignAndCallCuddle: linterCfg.AllowAssignAndCallCuddle,
|
||||
AllowMultiLineAssignCuddle: linterCfg.AllowMultiLineAssignCuddle,
|
||||
AllowCaseTrailingWhitespace: linterCfg.AllowCaseTrailingWhitespace,
|
||||
AllowCuddleDeclaration: linterCfg.AllowCuddleDeclaration,
|
||||
AllowCuddleWithCalls: []string{"Lock", "RLock"},
|
||||
AllowCuddleWithRHS: []string{"Unlock", "RUnlock"},
|
||||
StrictAppend: linterCfg.StrictAppend,
|
||||
AllowAssignAndCallCuddle: linterCfg.AllowAssignAndCallCuddle,
|
||||
AllowMultiLineAssignCuddle: linterCfg.AllowMultiLineAssignCuddle,
|
||||
AllowCuddleDeclaration: linterCfg.AllowCuddleDeclaration,
|
||||
AllowTrailingComment: linterCfg.AllowTrailingComment,
|
||||
CaseForceTrailingWhitespaceLimit: linterCfg.CaseForceTrailingWhitespaceLimit,
|
||||
AllowCuddleWithCalls: []string{"Lock", "RLock"},
|
||||
AllowCuddleWithRHS: []string{"Unlock", "RUnlock"},
|
||||
}
|
||||
)
|
||||
|
||||
|
40
test/testdata/wsl.go
vendored
40
test/testdata/wsl.go
vendored
@ -159,7 +159,7 @@ func allowTrailing(i int) {
|
||||
|
||||
case 2:
|
||||
fmt.Println("two")
|
||||
|
||||
// Comments OK too!
|
||||
case 3:
|
||||
fmt.Println("three")
|
||||
}
|
||||
@ -172,3 +172,41 @@ func ExampleSomeOutput() {
|
||||
// Output:
|
||||
// Hello, world
|
||||
}
|
||||
|
||||
func IncDecStmt() {
|
||||
counter := 0
|
||||
for range make([]int, 5) {
|
||||
counter++
|
||||
}
|
||||
|
||||
type t struct {
|
||||
counter int
|
||||
}
|
||||
|
||||
x := t{5}
|
||||
|
||||
x.counter--
|
||||
if x.counter > 0 {
|
||||
fmt.Println("not yet 0")
|
||||
}
|
||||
}
|
||||
|
||||
func AnonymousBlock() {
|
||||
func(a, b int) { // ERROR "block should not start with a whitespace"
|
||||
|
||||
fmt.Println(a + b)
|
||||
}(1, 1)
|
||||
}
|
||||
|
||||
func MultilineComment() {
|
||||
if true {
|
||||
/*
|
||||
Ok to start block with
|
||||
a
|
||||
long
|
||||
multiline
|
||||
cmoment
|
||||
*/
|
||||
fmt.Println("true")
|
||||
}
|
||||
}
|
||||
|
6
vendor/github.com/bombsimon/wsl/.travis.yml
generated
vendored
6
vendor/github.com/bombsimon/wsl/.travis.yml
generated
vendored
@ -2,9 +2,9 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.13"
|
||||
- "1.12"
|
||||
- "1.11"
|
||||
- 1.13.x
|
||||
- 1.12.x
|
||||
- 1.11.x
|
||||
|
||||
env:
|
||||
global:
|
||||
|
670
vendor/github.com/bombsimon/wsl/README.md
generated
vendored
670
vendor/github.com/bombsimon/wsl/README.md
generated
vendored
@ -21,595 +21,105 @@ might be bugs or unintentional false positives so I would love an
|
||||
[issue](https://github.com/bombsimon/wsl/issues/new) to fix, discuss, change or
|
||||
make something configurable!
|
||||
|
||||
## Installation
|
||||
|
||||
### By `go get` (local installation)
|
||||
|
||||
You can do that by using:
|
||||
|
||||
```sh
|
||||
go get -u github.com/bombsimon/wsl/cmd/...
|
||||
```
|
||||
|
||||
### By golangci-lint (CI automation)
|
||||
|
||||
`wsl` is already integrated with
|
||||
[golangci-lint](https://github.com/golangci/golangci-lint). Please refer to the
|
||||
instructions there.
|
||||
|
||||
## Usage
|
||||
|
||||
Install by using `go get -u github.com/bombsimon/wsl/cmd/...`.
|
||||
How to use depends on how you install `wsl`.
|
||||
|
||||
Run with `wsl [--no-test] <file1> [files...]` or `wsl ./package/...`. The "..."
|
||||
wildcard is not used like other `go` commands but instead can only be to a
|
||||
relative or absolute path.
|
||||
### With local binary
|
||||
|
||||
The general command format for `wsl` is:
|
||||
|
||||
```sh
|
||||
$ wsl [flags] <file1> [files...]
|
||||
$ wsl [flags] </path/to/package/...>
|
||||
|
||||
# Examples
|
||||
|
||||
$ wsl ./main.go
|
||||
$ wsl --no-test ./main.go
|
||||
$ wsl -allow-declaration ./main.go
|
||||
$ wsl --no-test --allow-cuddle-declaration ./main.go
|
||||
$ wsl --no-test --allow-trailing-comment ./myProject/...
|
||||
```
|
||||
|
||||
The "..." wildcard is not used like other `go` commands but instead can only
|
||||
be to a relative or absolute path.
|
||||
|
||||
By default, the linter will run on `./...` which means all go files in the
|
||||
current path and all subsequent paths, including test files. To disable linting
|
||||
test files, use `-n` or `--no-test`.
|
||||
|
||||
This linter can also be used as a part of
|
||||
[golangci-lint](https://github.com/golangci/golangci-lint)
|
||||
### By `golangci-lint` (CI automation)
|
||||
|
||||
## Rules
|
||||
The recommended command is:
|
||||
|
||||
Note that this linter doesn't take in consideration the issues that will be
|
||||
fixed with `gofmt` so ensure that the code is properly formatted.
|
||||
|
||||
### Never use empty lines
|
||||
|
||||
Even though this linter was built to **promote** the usage of empty lines, there
|
||||
are a few places where they should never be used.
|
||||
|
||||
Never use empty lines in the start or end of a block!
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
if someBooleanValue {
|
||||
|
||||
fmt.Println("i like starting newlines")
|
||||
}
|
||||
|
||||
if someOtherBooleanValue {
|
||||
fmt.Println("also trailing")
|
||||
|
||||
}
|
||||
|
||||
switch {
|
||||
|
||||
case 1:
|
||||
fmt.Println("switch is also a block")
|
||||
}
|
||||
|
||||
switch {
|
||||
case 1:
|
||||
|
||||
fmt.Println("not in a case")
|
||||
case 2:
|
||||
fmt.Println("or at the end")
|
||||
|
||||
}
|
||||
|
||||
func neverNewlineAfterReturn() {
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
func notEvenWithComments() {
|
||||
return false
|
||||
// I just forgot to say this...
|
||||
}
|
||||
```sh
|
||||
golangci-lint --disable-all --enable wsl
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
if someBooleanValue {
|
||||
fmt.Println("this is tight and nice")
|
||||
}
|
||||
|
||||
switch {
|
||||
case 1:
|
||||
fmt.Println("no blank lines here")
|
||||
case 2:
|
||||
// Comments are fine here!
|
||||
fmt.Println("or here")
|
||||
}
|
||||
|
||||
func returnCuddleded() {
|
||||
// My comment goes above the last statement!
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
### Use empty lines
|
||||
|
||||
There's an easy way to improve logic and readability by enforcing whitespaces at
|
||||
the right places. Usually this is around blocks and after declarations.
|
||||
|
||||
#### If
|
||||
|
||||
If statements should only be cuddled with assignments/declarations of variables
|
||||
used in the condition and only one assignment should be cuddled. Never cuddle if
|
||||
with anything but assignments.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
notConditional := "x"
|
||||
if somethingElse == "y" {
|
||||
fmt.Println("what am i checking?")
|
||||
}
|
||||
|
||||
first := 1
|
||||
second := 2
|
||||
third := 3
|
||||
forever := 4
|
||||
if forever {
|
||||
return true
|
||||
}
|
||||
|
||||
if false {
|
||||
fmt.Println("first if")
|
||||
}
|
||||
if true {
|
||||
fmt.Println("second if is cuddled")
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
val, err := SomeThing()
|
||||
if err != nil {
|
||||
// err is assigned on line above
|
||||
}
|
||||
|
||||
first := 1
|
||||
second := 2
|
||||
third := 3
|
||||
forever := 4
|
||||
|
||||
if forever > 3 {
|
||||
return fmt.Sprintf("group multiple assignments away from if")
|
||||
}
|
||||
|
||||
// Or separate from your condition.
|
||||
first := 1
|
||||
second := 2
|
||||
third := 3
|
||||
|
||||
forever := 4
|
||||
if forever > 3 {
|
||||
return fmt.Sprintf("group multiple assignments away from if")
|
||||
}
|
||||
|
||||
if false {
|
||||
// This is one statement
|
||||
}
|
||||
|
||||
if true {
|
||||
// This is another one, don't cuddled them!
|
||||
}
|
||||
```
|
||||
|
||||
#### Return
|
||||
|
||||
Return should be placed on a separate line from other statement unless the block
|
||||
consists of only two lines (including the return).
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
doSomething()
|
||||
add := 1+2
|
||||
fmt.Sprintf(add)
|
||||
return false
|
||||
|
||||
if true {
|
||||
stmt.X = true
|
||||
stmt.Y = false
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
doSomething()
|
||||
|
||||
add := 1+2
|
||||
fmt.Sprintf(add))
|
||||
|
||||
return false
|
||||
|
||||
if true {
|
||||
stmt.X = "only one line without return, may cuddled"
|
||||
return true
|
||||
}
|
||||
|
||||
if thisWorksToo {
|
||||
whitespace := true
|
||||
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
#### Branch statement
|
||||
|
||||
The same rule as for return
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
for i := range make([]int, 5) {
|
||||
if i > 2 {
|
||||
sendToOne(i)
|
||||
sendToSecond(i)
|
||||
continue
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
for i := range make([]int, 5) {
|
||||
if i > 2 {
|
||||
sendToOne(i)
|
||||
sendToSecond(i)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if statement == "is short" {
|
||||
sendToOne(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Assignment
|
||||
|
||||
Assignments may only be cuddled with other assignments.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
assignOne := "one"
|
||||
callFunc(assignOne)
|
||||
assignTwo := "two")
|
||||
callFunc(assignTwo)
|
||||
|
||||
if true {
|
||||
return
|
||||
}
|
||||
assigningClose := "bad"
|
||||
|
||||
var x = 2
|
||||
y := 3
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
assignOne := "one"
|
||||
assignTwo := "two")
|
||||
|
||||
callFunc(assignOne)
|
||||
callFunc(assignTwo)
|
||||
|
||||
// Or group assignment and call by usage.
|
||||
assignOne := "one"
|
||||
callFunc(assignOne)
|
||||
|
||||
assignTwo := "two")
|
||||
callFunc(assignTwo)
|
||||
|
||||
if true {
|
||||
return
|
||||
}
|
||||
|
||||
notAssigningClose := "not bad"
|
||||
|
||||
var x = 2
|
||||
|
||||
y := 3
|
||||
```
|
||||
|
||||
#### Declarations
|
||||
|
||||
Declarations should never be cuddled with anything, not even other declarations.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
var x int
|
||||
var y int
|
||||
|
||||
z := 2
|
||||
var a
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
// Group declarations, they'll align nice and tidy!
|
||||
var (
|
||||
x int
|
||||
y int
|
||||
)
|
||||
|
||||
z := 2
|
||||
|
||||
var a
|
||||
```
|
||||
|
||||
#### Expressions
|
||||
|
||||
Expressions (function calls) may never be cuddled with declarations or return
|
||||
statements. Expressions may also not be cuddled with assignments if not passed
|
||||
to the expression func.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
var a bool
|
||||
fmt.Println(a)
|
||||
|
||||
foo := true
|
||||
someFunc(false)
|
||||
|
||||
if someBool() {
|
||||
fmt.Println("doing things")
|
||||
}
|
||||
x.Calling()
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
var b bool
|
||||
|
||||
fmt.Println(b)
|
||||
|
||||
foo := true
|
||||
someFunc(foo)
|
||||
|
||||
bar := false
|
||||
|
||||
someFunc(true)
|
||||
|
||||
if someBool() {
|
||||
fmt.Println("doing things")
|
||||
}
|
||||
|
||||
x.Calling()
|
||||
```
|
||||
|
||||
#### Ranges
|
||||
|
||||
Range statements may only be cuddled with assignments that are used in the
|
||||
range. Just like if statements this only applies if it's a single assignment
|
||||
cuddled and not multiple.
|
||||
|
||||
Ranges may also be cuddled with assignments that are used directly in the block
|
||||
as first statement.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
noRangeList := []string{"a", "b", "c"}
|
||||
for _, x := range anotherList {
|
||||
fmt.Println(x)
|
||||
}
|
||||
|
||||
oneList := []int{1, 2, 3}
|
||||
twoList := []int{4, 5, 6}
|
||||
for i := range twoList {
|
||||
fmt.Println("too much assignments!")
|
||||
}
|
||||
|
||||
myCount := 0
|
||||
for _, v := range aList {
|
||||
fmt.Sprintf("first statement doesn't use assignment")
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
rangeList := []string{"a", "b", "c"}
|
||||
for _, x := range rangeList {
|
||||
fmt.Println(x)
|
||||
}
|
||||
|
||||
oneList := []int{1, 2, 3}
|
||||
|
||||
twoList := []int{4, 5, 6}
|
||||
for i := range twoList {
|
||||
fmt.Println("too much assignments!")
|
||||
}
|
||||
|
||||
myCount := 0
|
||||
for _, v := range aList {
|
||||
myCount += v
|
||||
|
||||
fmt.Sprintf("first statement uses cuddled assignment")
|
||||
}
|
||||
```
|
||||
|
||||
#### Defer
|
||||
|
||||
Defer is almost handled like return statements but there are cases where
|
||||
grouping defer statements with each other or expression calls may improve
|
||||
readability.
|
||||
|
||||
Defer statements may be cuddled with other defer statements as many times as you
|
||||
like. It may also be cuddled with assignments above or expression variables on
|
||||
the line above.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
first := getFirst()
|
||||
defer first.Close()
|
||||
second := getSecond() // This will fail
|
||||
defer second.Close()
|
||||
|
||||
first := getFirst()
|
||||
second := getSecond()
|
||||
defer first.Close() // Too many assignments above
|
||||
defer second.Close()
|
||||
|
||||
m1.Lock()
|
||||
defer m2.RUnlock() // Not the expression above
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
first := getFirst()
|
||||
second := getSecond()
|
||||
|
||||
defer first.Close()
|
||||
defer second.Close()
|
||||
|
||||
// Or group by usage.
|
||||
first := getFirst()
|
||||
defer first.Close()
|
||||
|
||||
second := getSecond()
|
||||
defer second.Close()
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
```
|
||||
|
||||
#### For loops
|
||||
|
||||
For statements works similar like ranges except that anonymous (infinite) loops
|
||||
may never be cuddled. Just like the range statement, variables used in the for
|
||||
or in first statement in the body may be cuddled.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
t := true
|
||||
for notT {
|
||||
fmt.Println("where's t used?")
|
||||
}
|
||||
|
||||
n := 0
|
||||
m := 1
|
||||
for x < 100 {
|
||||
n += x // m not used in for or body
|
||||
}
|
||||
|
||||
n := 1
|
||||
for {
|
||||
fmt.Println("never cuddled for without condition")
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
t := true
|
||||
for t {
|
||||
fmt.Println("t used in for")
|
||||
}
|
||||
|
||||
n := 0
|
||||
for x < 100 {
|
||||
n += x // n used in first block statement.
|
||||
}
|
||||
|
||||
n := 1
|
||||
|
||||
for {
|
||||
fmt.Println("never cuddled for without condition")
|
||||
}
|
||||
```
|
||||
|
||||
#### Go
|
||||
|
||||
Go routines may only be executed if there's a maximum of one assignments above
|
||||
and that assignment is used in the expression.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
first := func() {}
|
||||
second := func() {}
|
||||
go second()
|
||||
|
||||
notUsed := func() {}
|
||||
go first()
|
||||
|
||||
x := "1"
|
||||
go func() {
|
||||
fmt.Println("where's x used!=")
|
||||
}()
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
first := func() {}
|
||||
go first()
|
||||
|
||||
notUsed := func() {}
|
||||
|
||||
first := func() {}
|
||||
go first()
|
||||
```
|
||||
|
||||
#### Switch and Type switch
|
||||
|
||||
The same rules applies for switch and type switch statements with the exception
|
||||
of anonymous type switches. That means type switches where a new variable is not
|
||||
assigned. It's also allowed to cuddled type switches with variables used if it's
|
||||
used as the first argument in the first case.
|
||||
|
||||
Type switches may only be cuddled with one assignment above and if that
|
||||
assignment is used in the switch.
|
||||
|
||||
**Don't**
|
||||
|
||||
```go
|
||||
notSome := SomeInt()
|
||||
switch some {
|
||||
case 1:
|
||||
fmt.Println("1")
|
||||
default:
|
||||
fmt.Println("not 1")
|
||||
}
|
||||
|
||||
notSwitched := SomeInt()
|
||||
switch {
|
||||
case 1 > 2:
|
||||
fmt.Println("whitespace between assignments")
|
||||
}
|
||||
|
||||
n := 0
|
||||
switch v := some.(type):
|
||||
case typeOne:
|
||||
x := v.X // n not used in switch or body
|
||||
case typeTwo:
|
||||
x := v.X
|
||||
}
|
||||
```
|
||||
|
||||
**Do**
|
||||
|
||||
```go
|
||||
some := SomeInt()
|
||||
switch some {
|
||||
case 1:
|
||||
fmt.Println("1")
|
||||
default:
|
||||
fmt.Println("not 1")
|
||||
}
|
||||
|
||||
notSwitched := SomeInt()
|
||||
|
||||
switch {
|
||||
case 1 > 2:
|
||||
fmt.Println("whitespace between assignments")
|
||||
}
|
||||
|
||||
n := 0
|
||||
switch v := some.(type):
|
||||
case typeOne:
|
||||
n = v.X // n is used first in block, OK to cuddle
|
||||
case typeTwo:
|
||||
n = v.Y
|
||||
}
|
||||
```
|
||||
For more information, please refer to
|
||||
[golangci-lint](https://github.com/golangci/golangci-lint)'s documentation.
|
||||
|
||||
## Issues and configuration
|
||||
|
||||
The linter suppers a few ways to configure it to satisfy more than one kind of
|
||||
code style. These settings could be set either with flags or with YAML
|
||||
configuration if used via `golangci-lint`.
|
||||
|
||||
The supported configuration can be found [in the documentation](doc/configuration.md).
|
||||
|
||||
Below are the available checklist for any hit from `wsl`. If you do not see any,
|
||||
feel free to raise an [issue](https://github.com/bombsimon/wsl/issues/new).
|
||||
|
||||
> **Note**: this linter doesn't take in consideration the issues that will be
|
||||
> fixed with `go fmt -s` so ensure that the code is properly formatted before
|
||||
> use.
|
||||
|
||||
* [Anonymous switch statements should never be cuddled](doc/rules.md#anonymous-switch-statements-should-never-be-cuddled)
|
||||
* [Append only allowed to cuddle with appended value](doc/rules.md#append-only-allowed-to-cuddle-with-appended-value)
|
||||
* [Assignments should only be cuddled with other assignments](doc/rules.md#assignments-should-only-be-cuddled-with-other-assignments)
|
||||
* [Block should not end with a whitespace (or comment)](doc/rules.md#block-should-not-end-with-a-whitespace-or-comment)
|
||||
* [Block should not start with a whitespace](doc/rules.md#block-should-not-start-with-a-whitespace)
|
||||
* [Case block should end with newline at this size](doc/rules.md#case-block-should-end-with-newline-at-this-size)
|
||||
* [Branch statements should not be cuddled if block has more than two lines](doc/rules.md#branch-statements-should-not-be-cuddled-if-block-has-more-than-two-lines)
|
||||
* [Declarations should never be cuddled](doc/rules.md#declarations-should-never-be-cuddled)
|
||||
* [Defer statements should only be cuddled with expressions on same variable](doc/rules.md#defer-statements-should-only-be-cuddled-with-expressions-on-same-variable)
|
||||
* [Expressions should not be cuddled with blocks](doc/rules.md#expressions-should-not-be-cuddled-with-blocks)
|
||||
* [Expressions should not be cuddled with declarations or returns](doc/rules.md#expressions-should-not-be-cuddled-with-declarations-or-returns)
|
||||
* [For statement without condition should never be cuddled](doc/rules.md#for-statement-without-condition-should-never-be-cuddled)
|
||||
* [For statements should only be cuddled with assignments used in the iteration](doc/rules.md#for-statements-should-only-be-cuddled-with-assignments-used-in-the-iteration)
|
||||
* [Go statements can only invoke functions assigned on line above](doc/rules.md#go-statements-can-only-invoke-functions-assigned-on-line-above)
|
||||
* [If statements should only be cuddled with assignments](doc/rules.md#if-statements-should-only-be-cuddled-with-assignments)
|
||||
* [If statements should only be cuddled with assignments used in the if
|
||||
statement
|
||||
itself](doc/rules.md#if-statements-should-only-be-cuddled-with-assignments-used-in-the-if-statement-itself)
|
||||
* [Only cuddled expressions if assigning variable or using from line
|
||||
above](doc/rules.md#only-cuddled-expressions-if-assigning-variable-or-using-from-line-above)
|
||||
* [Only one cuddle assignment allowed before defer statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-defer-statement)
|
||||
* [Only one cuddle assginment allowed before for statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-for-statement)
|
||||
* [Only one cuddle assignment allowed before go statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-go-statement)
|
||||
* [Only one cuddle assignment allowed before if statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-if-statement)
|
||||
* [Only one cuddle assignment allowed before range statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-range-statement)
|
||||
* [Only one cuddle assignment allowed before switch statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-switch-statement)
|
||||
* [Only one cuddle assignment allowed before type switch statement](doc/rules.md#only-one-cuddle-assignment-allowed-before-type-switch-statement)
|
||||
* [Ranges should only be cuddled with assignments used in the iteration](doc/rules.md#ranges-should-only-be-cuddled-with-assignments-used-in-the-iteration)
|
||||
* [Return statements should not be cuddled if block has more than two lines](doc/rules.md#return-statements-should-not-be-cuddled-if-block-has-more-than-two-lines)
|
||||
* [Stmt type not implemented](doc/rules.md#stmt-type-not-implemented)
|
||||
* [Switch statements should only be cuddled with variables switched](doc/rules.md#switch-statements-should-only-be-cuddled-with-variables-switched)
|
||||
* [Type switch statements should only be cuddled with variables switched](doc/rules.md#type-switch-statements-should-only-be-cuddled-with-variables-switched)
|
||||
|
209
vendor/github.com/bombsimon/wsl/wsl.go
generated
vendored
209
vendor/github.com/bombsimon/wsl/wsl.go
generated
vendored
@ -50,21 +50,12 @@ type Configuration struct {
|
||||
// }
|
||||
AllowMultiLineAssignCuddle bool
|
||||
|
||||
// AllowCaseTrailingWhitespace will allow case blocks to end with a
|
||||
// whitespace. Sometimes this might actually improve readability. This
|
||||
// defaults to false but setting it to true will enable the following
|
||||
// example:
|
||||
// switch {
|
||||
// case 1:
|
||||
// fmt.Println(1)
|
||||
//
|
||||
// case 2:
|
||||
// fmt.Println(2)
|
||||
//
|
||||
// case 3:
|
||||
// fmt:println(3)
|
||||
// }
|
||||
AllowCaseTrailingWhitespace bool
|
||||
// If the number of lines in a case block is equal to or lager than this
|
||||
// number, the case *must* end white a newline.
|
||||
CaseForceTrailingWhitespaceLimit int
|
||||
|
||||
// AllowTrailingComment will allow blocks to end with comments.
|
||||
AllowTrailingComment bool
|
||||
|
||||
// AllowCuddleDeclaration will allow multiple var/declaration statements to
|
||||
// be cuddled. This defaults to false but setting it to true will enable the
|
||||
@ -93,12 +84,13 @@ type Configuration struct {
|
||||
// DefaultConfig returns default configuration
|
||||
func DefaultConfig() Configuration {
|
||||
return Configuration{
|
||||
StrictAppend: true,
|
||||
AllowAssignAndCallCuddle: true,
|
||||
AllowMultiLineAssignCuddle: true,
|
||||
AllowCaseTrailingWhitespace: false,
|
||||
AllowCuddleWithCalls: []string{"Lock", "RLock"},
|
||||
AllowCuddleWithRHS: []string{"Unlock", "RUnlock"},
|
||||
StrictAppend: true,
|
||||
AllowAssignAndCallCuddle: true,
|
||||
AllowMultiLineAssignCuddle: true,
|
||||
AllowTrailingComment: false,
|
||||
CaseForceTrailingWhitespaceLimit: 0,
|
||||
AllowCuddleWithCalls: []string{"Lock", "RLock"},
|
||||
AllowCuddleWithRHS: []string{"Unlock", "RUnlock"},
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,14 +195,12 @@ func (p *Processor) parseBlockBody(ident *ast.Ident, block *ast.BlockStmt) {
|
||||
// nolint: gocognit
|
||||
func (p *Processor) parseBlockStatements(statements []ast.Stmt) {
|
||||
for i, stmt := range statements {
|
||||
// TODO: How to tell when and where func literals may exist to enforce
|
||||
// linting.
|
||||
if as, isAssignStmt := stmt.(*ast.AssignStmt); isAssignStmt {
|
||||
for _, rhs := range as.Rhs {
|
||||
if fl, isFuncLit := rhs.(*ast.FuncLit); isFuncLit {
|
||||
p.parseBlockBody(nil, fl.Body)
|
||||
}
|
||||
}
|
||||
// Start by checking if this statement is another block (other than if,
|
||||
// for and range). This could be assignment to a function, defer or go
|
||||
// call with an inline function or similar. If this is found we start by
|
||||
// parsing this body block before moving on.
|
||||
for _, stmtBlocks := range p.findBlockStmt(stmt) {
|
||||
p.parseBlockBody(nil, stmtBlocks)
|
||||
}
|
||||
|
||||
firstBodyStatement := p.firstBodyStatement(i, statements)
|
||||
@ -322,11 +312,15 @@ func (p *Processor) parseBlockStatements(statements []ast.Stmt) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) {
|
||||
if !atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) {
|
||||
p.addError(t.Pos(), "if statements should only be cuddled with assignments used in the if statement itself")
|
||||
}
|
||||
if atLeastOneInListsMatch(rightAndLeftHandSide, assignedOnLineAbove) {
|
||||
continue
|
||||
}
|
||||
|
||||
if atLeastOneInListsMatch(assignedOnLineAbove, assignedFirstInBlock) {
|
||||
continue
|
||||
}
|
||||
|
||||
p.addError(t.Pos(), "if statements should only be cuddled with assignments used in the if statement itself")
|
||||
case *ast.ReturnStmt:
|
||||
if isLastStatementInBlockOfOnlyTwoLines() {
|
||||
continue
|
||||
@ -473,6 +467,10 @@ func (p *Processor) parseBlockStatements(statements []ast.Stmt) {
|
||||
}
|
||||
}
|
||||
case *ast.GoStmt:
|
||||
if _, ok := previousStatement.(*ast.GoStmt); ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if moreThanOneStatementAbove() {
|
||||
p.addError(t.Pos(), "only one cuddle assignment allowed before go statement")
|
||||
|
||||
@ -595,9 +593,10 @@ func (p *Processor) findLHS(node ast.Node) []string {
|
||||
*ast.ReturnStmt, *ast.GoStmt, *ast.CaseClause,
|
||||
*ast.CommClause, *ast.CallExpr, *ast.UnaryExpr,
|
||||
*ast.BranchStmt, *ast.TypeSpec, *ast.ChanType,
|
||||
*ast.DeferStmt, *ast.TypeAssertExpr, *ast.IncDecStmt,
|
||||
*ast.RangeStmt:
|
||||
// Nothing to add to LHS
|
||||
*ast.DeferStmt, *ast.TypeAssertExpr, *ast.RangeStmt:
|
||||
// Nothing to add to LHS
|
||||
case *ast.IncDecStmt:
|
||||
return p.findLHS(t.X)
|
||||
case *ast.Ident:
|
||||
return []string{t.Name}
|
||||
case *ast.AssignStmt:
|
||||
@ -722,6 +721,33 @@ func (p *Processor) findRHS(node ast.Node) []string {
|
||||
return rhs
|
||||
}
|
||||
|
||||
func (p *Processor) findBlockStmt(node ast.Node) []*ast.BlockStmt {
|
||||
var blocks []*ast.BlockStmt
|
||||
|
||||
switch t := node.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, x := range t.Rhs {
|
||||
blocks = append(blocks, p.findBlockStmt(x)...)
|
||||
}
|
||||
case *ast.CallExpr:
|
||||
blocks = append(blocks, p.findBlockStmt(t.Fun)...)
|
||||
case *ast.FuncLit:
|
||||
blocks = append(blocks, t.Body)
|
||||
case *ast.ExprStmt:
|
||||
blocks = append(blocks, p.findBlockStmt(t.X)...)
|
||||
case *ast.ReturnStmt:
|
||||
for _, x := range t.Results {
|
||||
blocks = append(blocks, p.findBlockStmt(x)...)
|
||||
}
|
||||
case *ast.DeferStmt:
|
||||
blocks = append(blocks, p.findBlockStmt(t.Call)...)
|
||||
case *ast.GoStmt:
|
||||
blocks = append(blocks, p.findBlockStmt(t.Call)...)
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
// maybeX extracts the X field from an AST node and returns it with a true value
|
||||
// if it exists. If the node doesn't have an X field nil and false is returned.
|
||||
// Known fields with X that are handled:
|
||||
@ -839,7 +865,10 @@ func (p *Processor) findLeadingAndTrailingWhitespaces(ident *ast.Ident, stmt, ne
|
||||
break
|
||||
}
|
||||
|
||||
allowedLinesBeforeFirstStatement += len(commentGroup.List)
|
||||
// Support both /* multiline */ and //single line comments
|
||||
for _, c := range commentGroup.List {
|
||||
allowedLinesBeforeFirstStatement += len(strings.Split(c.Text, "\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -850,38 +879,92 @@ func (p *Processor) findLeadingAndTrailingWhitespaces(ident *ast.Ident, stmt, ne
|
||||
)
|
||||
}
|
||||
|
||||
// If the blockEndLine is 0 we're a case clause. If we don't have any
|
||||
// nextStatement the trailing whitespace will be handled when parsing the
|
||||
// switch. If we do have a next statement we can see where it starts by
|
||||
// getting it's colon position.
|
||||
if blockEndLine == 0 {
|
||||
if nextStatement == nil {
|
||||
return
|
||||
// If the blockEndLine is not 0 we're a regular block (not case).
|
||||
if blockEndLine != 0 {
|
||||
if p.config.AllowTrailingComment {
|
||||
if lastComment, ok := commentMap[lastStatement]; ok {
|
||||
var (
|
||||
lastCommentGroup = lastComment[len(lastComment)-1]
|
||||
lastCommentLine = lastCommentGroup.List[len(lastCommentGroup.List)-1]
|
||||
countNewlines = 0
|
||||
)
|
||||
|
||||
countNewlines += len(strings.Split(lastCommentLine.Text, "\n"))
|
||||
|
||||
// No newlines between trailing comments and end of block.
|
||||
if p.nodeStart(lastCommentLine)+countNewlines != blockEndLine-1 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we allow case to end white whitespace just return.
|
||||
if p.config.AllowCaseTrailingWhitespace {
|
||||
return
|
||||
if p.nodeEnd(lastStatement) != blockEndLine-1 && !isExampleFunc(ident) {
|
||||
p.addError(blockEndPos, "block should not end with a whitespace (or comment)")
|
||||
}
|
||||
|
||||
switch n := nextStatement.(type) {
|
||||
case *ast.CaseClause:
|
||||
blockEndPos = n.Case
|
||||
case *ast.CommClause:
|
||||
blockEndPos = n.Case
|
||||
default:
|
||||
// We're not at the end of the case?
|
||||
return
|
||||
}
|
||||
|
||||
blockEndLine = p.fileSet.Position(blockEndPos).Line
|
||||
return
|
||||
}
|
||||
|
||||
if p.nodeEnd(lastStatement) != blockEndLine-1 && !isExampleFunc(ident) {
|
||||
p.addError(
|
||||
blockEndPos,
|
||||
"block should not end with a whitespace (or comment)",
|
||||
)
|
||||
// If we don't have any nextStatement the trailing whitespace will be
|
||||
// handled when parsing the switch. If we do have a next statement we can
|
||||
// see where it starts by getting it's colon position. We set the end of the
|
||||
// current case to the position of the next case.
|
||||
switch n := nextStatement.(type) {
|
||||
case *ast.CaseClause:
|
||||
blockEndPos = n.Case
|
||||
case *ast.CommClause:
|
||||
blockEndPos = n.Case
|
||||
default:
|
||||
// No more cases
|
||||
return
|
||||
}
|
||||
|
||||
blockEndLine = p.fileSet.Position(blockEndPos).Line - 1
|
||||
|
||||
var (
|
||||
blockSize = blockEndLine - blockStartLine
|
||||
caseTrailingCommentLines int
|
||||
)
|
||||
|
||||
// TODO: I don't know what comments are bound to in cases. For regular
|
||||
// blocks the last comment is bound to the last statement but for cases
|
||||
// they are bound to the case clause expression. This will however get us all
|
||||
// comments and depending on the case expression this gets tricky.
|
||||
//
|
||||
// To handle this I get the comment map from the current statement (the case
|
||||
// itself) and iterate through all groups and all comment within all groups.
|
||||
// I then get the comments after the last statement but before the next case
|
||||
// clause and just map each line of comment that way.
|
||||
for _, commentGroups := range commentMap {
|
||||
for _, commentGroup := range commentGroups {
|
||||
for _, comment := range commentGroup.List {
|
||||
commentLine := p.fileSet.Position(comment.Pos()).Line
|
||||
|
||||
// Ignore comments before the last statement.
|
||||
if commentLine <= p.nodeStart(lastStatement) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Ignore comments after the end of this case.
|
||||
if commentLine > blockEndLine {
|
||||
continue
|
||||
}
|
||||
|
||||
// This allows /* multiline */ comments with newlines as well
|
||||
// as regular (//) ones
|
||||
caseTrailingCommentLines += len(strings.Split(comment.Text, "\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasTrailingWhitespace := p.nodeEnd(lastStatement)+caseTrailingCommentLines != blockEndLine
|
||||
|
||||
// If the force trailing limit is configured and we don't end with a newline.
|
||||
if p.config.CaseForceTrailingWhitespaceLimit > 0 && !hasTrailingWhitespace {
|
||||
// Check if the block size is too big to miss the newline.
|
||||
if blockSize >= p.config.CaseForceTrailingWhitespaceLimit {
|
||||
p.addError(lastStatement.Pos(), "case block should end with newline at this size")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -4,7 +4,7 @@ github.com/BurntSushi/toml
|
||||
github.com/OpenPeeDeeP/depguard
|
||||
# github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6
|
||||
github.com/StackExchange/wmi
|
||||
# github.com/bombsimon/wsl v1.2.5
|
||||
# github.com/bombsimon/wsl v1.2.7
|
||||
github.com/bombsimon/wsl
|
||||
# github.com/davecgh/go-spew v1.1.1
|
||||
github.com/davecgh/go-spew/spew
|
||||
|
Loading…
x
Reference in New Issue
Block a user