Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to cuddle assignments for a whole block #163

Merged
merged 3 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func defaultConfig() *Configuration {
AllowCuddleWithRHS: []string{"Unlock", "RUnlock"},
ErrorVariableNames: []string{"err"},
ForceCaseTrailingWhitespaceLimit: 0,
AllowCuddleUsedInBlock: false,
}
}

Expand Down Expand Up @@ -68,6 +69,7 @@ func (wa *wslAnalyzer) flags() flag.FlagSet {
flags.BoolVar(&wa.config.ForceExclusiveShortDeclarations, "force-short-decl-cuddling", false, "Force short declarations to cuddle by themselves")
flags.BoolVar(&wa.config.StrictAppend, "strict-append", true, "Strict rules for append")
flags.BoolVar(&wa.config.IncludeGenerated, "include-generated", false, "Include generated files")
flags.BoolVar(&wa.config.AllowCuddleUsedInBlock, "allow-cuddle-used-in-block", false, "Allow cuddling of variables used in block statements")
flags.IntVar(&wa.config.ForceCaseTrailingWhitespaceLimit, "force-case-trailing-whitespace", 0, "Force newlines for case blocks > this number.")

flags.Var(&multiStringValue{slicePtr: &wa.config.AllowCuddleWithCalls}, "allow-cuddle-with-calls", "Comma separated list of idents that can have cuddles after")
Expand Down
103 changes: 103 additions & 0 deletions doc/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,109 @@ var (
)
```

### allow-cuddle-used-in-block

Controls if you may cuddle variables used in block statements. This is false by default as to not change existing behavior.

> Default value: false

Supported when true:

```go
counter := 0
if somethingTrue {
checker := getAChecker()
if !checker {
return
}

counter++
}

var numbers []int
for i := 0; i < 10; i++ {
if 1 == 1 {
numbers = append(numbers, i)
}
}

var numbers2 []int
for {
if 1 == 1 {
numbers2 = append(numbers2, 1)
}
}

var id string
switch {
case int:
if true {
id = strconv.Itoa(i)
}
case uint32:
if true {
id = strconv.Itoa(int(i))
}
case string:
if true {
id = i
}
}
```

Required when false:

```go
counter := 0

if somethingTrue {
checker := getAChecker()
if !checker {
return
}

counter++
}

var numbers []int

for i := 0; i < 10; i++ {
if 1 == 1 {
numbers = append(numbers, i)
}
}

var numbers2 []int

for {
if 1 == 1 {
numbers2 = append(numbers2, 1)
}
}

var id string

switch {
case int:
if true {
id = strconv.Itoa(i)
}
case uint32:
if true {
id = strconv.Itoa(int(i))
}
case string:
if true {
id = i
}
}
```

**Note**: this means the option _overrides_ the following rules:
- [Anonymous switch statements should never be cuddled](rules.md#anonymous-switch-statements-should-never-be-cuddled)
- [For statement without condition should never be cuddled](rules.md#for-statement-without-condition-should-never-be-cuddled)


### [allow-trailing-comment](rules.md#block-should-not-end-with-a-whitespace-or-comment)

Controls if blocks can end with comments. This is not encouraged sine it's
Expand Down
4 changes: 4 additions & 0 deletions doc/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ linter and how they should be resolved or configured to handle.
## Checklist

### Anonymous switch statements should never be cuddled
> Can be configured, see [configuration
documentation](configuration.md#allow-cuddle-used-in-block)

Anonymous `switch` statements (mindless `switch`) should deserve its needed
attention that it does not need any assigned variables. Hence, it should not
Expand Down Expand Up @@ -398,6 +400,8 @@ run()
---

### For statement without condition should never be cuddled
> Can be configured, see [configuration
documentation](configuration.md#allow-cuddle-used-in-block)

`for` loop without conditions (infinity loop) should deserves its own
attention. Hence, it should not be cuddled with anyone.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package testpkg

import (
"fmt"
"strconv"
)

func ForCuddleAssignmentWholeBlock() {
x := 1
y := 2

var numbers []int
for i := 0; i < 10; i++ { // want "for statements should only be cuddled with assignments used in the iteration"
if x == y {
numbers = append(numbers, i)
}
}

var numbers2 []int
for i := range 10 { // want "ranges should only be cuddled with assignments used in the iteration"
if x == y {
numbers2 = append(numbers2, i)
}
}

var numbers3 []int
for { // want "for statement without condition should never be cuddled"
if x == y {
numbers3 = append(numbers3, i)
}
}

environment = make(map[string]string)
for _, env := range req.GetConfig().GetEnvs() { // want "ranges should only be cuddled with assignments used in the iteration"
switch env.GetKey() {
case "user-data":
cloudInitUserData = env.GetValue()
default:
environment[env.GetKey()] = env.GetValue()
}
}
}

func IfCuddleAssignmentWholeBlock() {
x := 1
y := 2

counter := 0
if somethingTrue { // want "if statements should only be cuddled with assignments used in the if statement itself"
checker := getAChecker()
if !checker {
return
}

counter++ // Cuddled variable used in block, but not as first statement
}

var number2 []int
if x == y { // want "if statements should only be cuddled with assignments used in the if statement itself"
fmt.Println("a")
} else {
if x > y {
number2 = append(number2, i)
}
}

var number3 []int
if x == y { // want "if statements should only be cuddled with assignments used in the if statement itself"
fmt.Println("a")
} else if x > y {
if x == y {
number3 = append(number3, i)
}
}

var number4 []int
if x == y { // want "if statements should only be cuddled with assignments used in the if statement itself"
if x == y {
number4 = append(number4, i)
}
} else if x > y {
if x == y {
number4 = append(number4, i)
}
} else {
if x > y {
number4 = append(number4, i)
}
}
}

func SwitchCuddleAssignmentWholeBlock() {
var id string
var b bool // want "declarations should never be cuddled"
switch b { // want "only one cuddle assignment allowed before switch statement"
case true:
id = "a"
case false:
id = "b"
}

var b bool
var id string // want "declarations should never be cuddled"
switch b { // want "only one cuddle assignment allowed before switch statement"
case true:
id = "a"
case false:
id = "b"
}

var id2 string
switch i := objectID.(type) { // want "type switch statements should only be cuddled with variables switched"
case int:
if true {
id2 = strconv.Itoa(i)
}
case uint32:
if true {
id2 = strconv.Itoa(int(i))
}
case string:
if true {
id2 = i
}
}

var id3 string
switch { // want "anonymous switch statements should never be cuddled"
case int:
if true {
id3 = strconv.Itoa(i)
}
case uint32:
if true {
id3 = strconv.Itoa(int(i))
}
case string:
if true {
id3 = i
}
}
}
Loading
Loading