github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/testdata/cognitive-complexity.go (about) 1 // Test of cognitive complexity. 2 3 // Package pkg ... 4 package pkg 5 6 import ( 7 "fmt" 8 ast "go/ast" 9 "log" 10 "testing" 11 12 "k8s.io/klog" 13 ) 14 15 // Test IF and Boolean expr 16 func f(x int) bool { // MATCH /function f has cognitive complexity 3 (> max enabled 0)/ 17 if x > 0 && true || false { // +3 18 return true 19 } else { 20 log.Printf("non-positive x: %d", x) 21 } 22 return false 23 } 24 25 // Test IF 26 func g(f func() bool) string { // MATCH /function g has cognitive complexity 1 (> max enabled 0)/ 27 if ok := f(); ok { // +1 28 return "it's okay" 29 } else { 30 return "it's NOT okay!" 31 } 32 } 33 34 // Test Boolean expr 35 func h(a, b, c, d, e, f bool) bool { // MATCH /function h has cognitive complexity 3 (> max enabled 0)/ 36 return a && b && c || d || e && f // +3 37 } 38 39 func i(a, b, c, d, e, f bool) bool { // MATCH /function i has cognitive complexity 2 (> max enabled 0)/ 40 result := a && b && c || d || e // +2 41 return result 42 } 43 44 func j(a, b, c, d, e, f bool) bool { // MATCH /function j has cognitive complexity 2 (> max enabled 0)/ 45 result := z(a && !(b && c)) // +2 46 return result 47 } 48 49 func j1(a, b, c, d, e, f bool) bool { // MATCH /function j1 has cognitive complexity 2 (> max enabled 0)/ 50 return (a && !(b < 2) || c) 51 } 52 53 // Test Switch expr 54 func k(a, b, c, d, e, f bool) bool { // MATCH /function k has cognitive complexity 1 (> max enabled 0)/ 55 switch expr { // +1 56 case cond1: 57 case cond2: 58 default: 59 } 60 61 return result 62 } 63 64 // Test nesting FOR expr + nested IF 65 func l() { // MATCH /function l has cognitive complexity 6 (> max enabled 0)/ 66 for i := 1; i <= max; i++ { // +1 67 for j := 2; j < i; j++ { // +1 +1(nesting) 68 if i%j == 0 { // +1 +2(nesting) 69 continue 70 } 71 } 72 73 total += i 74 } 75 return total 76 } 77 78 // Test nesting IF 79 func m() { // MATCH /function m has cognitive complexity 6 (> max enabled 0)/ 80 if i <= max { // +1 81 if j < i { // +1 +1(nesting) 82 if i%j == 0 { // +1 +2(nesting) 83 return 0 84 } 85 } 86 87 total += i 88 } 89 return total 90 } 91 92 // Test nesting IF + nested FOR 93 func n() { // MATCH /function n has cognitive complexity 6 (> max enabled 0)/ 94 if i > max { // +1 95 for j := 2; j < i; j++ { // +1 +1(nesting) 96 if i%j == 0 { // +1 +2(nesting) 97 continue 98 } 99 } 100 101 total += i 102 } 103 return total 104 } 105 106 // Test nesting 107 func o() { // MATCH /function o has cognitive complexity 12 (> max enabled 0)/ 108 if i > max { // +1 109 if j < i { // +1 +1(nesting) 110 if i%j == 0 { // +1 +2(nesting) 111 return 112 } 113 } 114 115 total += i 116 } 117 118 if i > max { // +1 119 if j < i { // +1 +1(nesting) 120 if i%j == 0 { // +1 +2(nesting) 121 return 122 } 123 } 124 125 total += i 126 } 127 } 128 129 // Tests TYPE SWITCH 130 func p() { // MATCH /function p has cognitive complexity 1 (> max enabled 0)/ 131 switch n := n.(type) { // +1 132 case *ast.IfStmt: 133 targets := []ast.Node{n.Cond, n.Body, n.Else} 134 v.walk(targets...) 135 return nil 136 case *ast.ForStmt: 137 v.walk(n.Body) 138 return nil 139 case *ast.TypeSwitchStmt: 140 v.walk(n.Body) 141 return nil 142 case *ast.BinaryExpr: 143 v.complexity += v.binExpComplexity(n) 144 return nil 145 } 146 } 147 148 // Test RANGE 149 func q() { // MATCH /function q has cognitive complexity 1 (> max enabled 0)/ 150 for _, t := range targets { // +1 151 ast.Walk(v, t) 152 } 153 } 154 155 // Tests SELECT 156 func r() { // MATCH /function r has cognitive complexity 1 (> max enabled 0)/ 157 select { // +1 158 case c <- x: 159 x, y = y, x+y 160 case <-quit: 161 fmt.Println("quit") 162 return 163 } 164 } 165 166 // Test jump to label 167 func s() { // MATCH /function s has cognitive complexity 3 (> max enabled 0)/ 168 FirstLoop: 169 for i := 0; i < 10; i++ { // +1 170 break 171 } 172 for i := 0; i < 10; i++ { // +1 173 break FirstLoop // +1 174 } 175 } 176 177 func t() { // MATCH /function t has cognitive complexity 2 (> max enabled 0)/ 178 FirstLoop: 179 for i := 0; i < 10; i++ { // +1 180 goto FirstLoop // +1 181 } 182 } 183 184 func u() { // MATCH /function u has cognitive complexity 3 (> max enabled 0)/ 185 FirstLoop: 186 for i := 0; i < 10; i++ { // +1 187 continue 188 } 189 for i := 0; i < 10; i++ { // +1 190 continue FirstLoop // +1 191 } 192 } 193 194 // Tests FUNC LITERAL 195 func v() { // MATCH /function v has cognitive complexity 2 (> max enabled 0)/ 196 myFunc := func(b bool) { 197 if b { // +1 +1(nesting) 198 199 } 200 } 201 } 202 203 func v() { 204 t.Run(tc.desc, func(t *testing.T) {}) 205 } 206 207 func w() { // MATCH /function w has cognitive complexity 3 (> max enabled 0)/ 208 defer func(b bool) { 209 if b { // +1 +1(nesting) 210 211 } 212 }(false || true) // +1 213 } 214 215 // Test from Cognitive Complexity white paper 216 func sumOfPrimes(max int) int { // MATCH /function sumOfPrimes has cognitive complexity 7 (> max enabled 0)/ 217 total := 0 218 OUT: 219 for i := 1; i <= max; i++ { // +1 220 for j := 2; j < i; j++ { // +1 +1(nesting) 221 if i%j == 0 { // +1 +2(nesting) 222 continue OUT // +1 223 } 224 } 225 226 total += i 227 } 228 return total 229 } 230 231 // Test from K8S 232 func (m *Migrator) MigrateIfNeeded(target *EtcdVersionPair) error { // MATCH /function (*Migrator).MigrateIfNeeded has cognitive complexity 18 (> max enabled 0)/ 233 klog.Infof("Starting migration to %s", target) 234 err := m.dataDirectory.Initialize(target) 235 if err != nil { // +1 236 return fmt.Errorf("failed to initialize data directory %s: %v", m.dataDirectory.path, err) 237 } 238 239 var current *EtcdVersionPair 240 vfExists, err := m.dataDirectory.versionFile.Exists() 241 if err != nil { // +1 242 return err 243 } 244 if vfExists { // +1 245 current, err = m.dataDirectory.versionFile.Read() 246 if err != nil { // +1 +1 247 return err 248 } 249 } else { 250 return fmt.Errorf("existing data directory '%s' is missing version.txt file, unable to migrate", m.dataDirectory.path) 251 } 252 253 for { // +1 254 klog.Infof("Converging current version '%s' to target version '%s'", current, target) 255 currentNextMinorVersion := &EtcdVersion{} 256 switch { // +1 +1 257 case current.version.MajorMinorEquals(target.version) || currentNextMinorVersion.MajorMinorEquals(target.version): // +1 258 klog.Infof("current version '%s' equals or is one minor version previous of target version '%s' - migration complete", current, target) 259 err = m.dataDirectory.versionFile.Write(target) 260 if err != nil { // +1 +2 261 return fmt.Errorf("failed to write version.txt to '%s': %v", m.dataDirectory.path, err) 262 } 263 return nil 264 case current.storageVersion == storageEtcd2 && target.storageVersion == storageEtcd3: // +1 265 return fmt.Errorf("upgrading from etcd2 storage to etcd3 storage is not supported") 266 case current.version.Major == 3 && target.version.Major == 2: // +1 267 return fmt.Errorf("downgrading from etcd 3.x to 2.x is not supported") 268 case current.version.Major == target.version.Major && current.version.Minor < target.version.Minor: // +1 269 stepVersion := m.cfg.supportedVersions.NextVersionPair(current) 270 klog.Infof("upgrading etcd from %s to %s", current, stepVersion) 271 current, err = m.minorVersionUpgrade(current, stepVersion) 272 case current.version.Major == 3 && target.version.Major == 3 && current.version.Minor > target.version.Minor: // +1 273 klog.Infof("rolling etcd back from %s to %s", current, target) 274 current, err = m.rollbackEtcd3MinorVersion(current, target) 275 } 276 if err != nil { // +1 +1 277 return err 278 } 279 } 280 } 281 282 // no regression test for issue #451 283 func myFunc()