36

I have the following code in swift3 and i am using swift lint for linting the code. The code is given as follows:

    func selectedMenuInLoggedOutState(sender: UIButton) {
    switch sender.tag {
    case 1:
      if let menu = LeftGuestMenu(rawValue: 0) {
        self.changeGuestViewController(menu)
      }
    case 2:
      if let menu = LeftGuestMenu(rawValue: 1) {
        self.changeGuestViewController(menu)
      }
    case 3:
      if let menu = LeftGuestMenu(rawValue: 2) {
        self.changeGuestViewController(menu)
      }
    case 4:
      if let menu = LeftGuestMenu(rawValue: 3) {
        self.changeGuestViewController(menu)
      }
    case 5:
      if let menu = LeftGuestMenu(rawValue: 4) {
        self.changeGuestViewController(menu)
      }
    case 6:
      if let menu = LeftGuestMenu(rawValue: 5) {
        self.changeGuestViewController(menu)
      }
    default:
      break
    }
  }

The swift lint generates a "Cyclomatic Complexity Violation" warning. Why did this warning occur and how does one resolve it?

enter image description here

PJSimon
  • 343
  • 1
  • 18
Chelsea Shawra
  • 1,593
  • 4
  • 22
  • 43

5 Answers5

59

The method is too complex. But instead of rewriting the code, you could exclude switches from the cyclomatic_complexity calculation (since they are perfectly readable) like this:

cyclomatic_complexity:
  ignores_case_statements: true
Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84
23

The warning occurs because your function is too complex as defined by the metric which essentially counts the number of decisions that need to be made.

A simple way to avoid it in this particular case would be with some simple math:

func selectedMenuInLoggedOutState(sender: UIButton) {
    guard let menu = LeftGuestMenu(rawValue: sender.tag - 1) else { return }
    self.changeGuestViewController(menu)
}
Daniel T.
  • 32,821
  • 6
  • 50
  • 72
19

You can disable swiftlint warnings in code like this:

// swiftlint:disable cyclomatic_complexity
func selectedMenuInLoggedOutState(sender: UIButton) {
    ...
}
// swiftlint:enable cyclomatic_complexity

or, if you want to explicitly just disable the next swiftlint warning:

// swiftlint:disable:next cyclomatic_complexity
func selectedMenuInLoggedOutState(sender: UIButton) {
deanWombourne
  • 38,189
  • 13
  • 98
  • 110
2

You can reduce your complexity by eliminating the repeated if let statements:

func selectedMenuInLoggedOutState(sender: UIButton) {

    let menu: MenuType?

    switch sender.tag {
    case 1:
     menu = LeftGuestMenu(rawValue: 0)
    case 2:
     menu = LeftGuestMenu(rawValue: 1) 
    case 3:
     menu = LeftGuestMenu(rawValue: 2) 
    case 4:
      menu = LeftGuestMenu(rawValue: 3) 
    case 5:
      menu = LeftGuestMenu(rawValue: 4)   
    case 6:
      menu = LeftGuestMenu(rawValue: 5) 
    default:
      menu=nil
    }

    if let menu = menu {
       self.changeGuestViewController(menu)
    }
  }
Paulw11
  • 108,386
  • 14
  • 159
  • 186
2

In case if you don't want to change your logic, follow below. Add "cyclomatic_complexity:" property and set warning value in .swiftlint.yml file.

cyclomatic_complexity: warning: 25

Note: Here setting warning value means, increasing the number of linearly independent paths. You can set your own value.

ajaybomma
  • 264
  • 2
  • 10