Skip to content

Commit

Permalink
Add support to cuddle assignments for a whole block (#163)
Browse files Browse the repository at this point in the history
* Support to cuddle assignments for a whole block

* Implement PR suggestions

* Update doc/configuration.md

Co-authored-by: Simon Sawert <simon@sawert.se>

---------

Co-authored-by: Simon Sawert <simon@sawert.se>
  • Loading branch information
jacobdrury and bombsimon authored Feb 24, 2025
1 parent 66344d2 commit 5eae4e3
Show file tree
Hide file tree
Showing 9 changed files with 768 additions and 12 deletions.
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 anywhere in the following block.

> 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

0 comments on commit 5eae4e3

Please sign in to comment.