Unused setter value is likely a mistakeSW-W1004Duplicate key in dictionary is likely a mistakeSW-E1000Default parameters should always be positioned at the endSW-W1001Duplicate conditions in branch instruction is likely a mistakeSW-W1005Enum should always have unique casesSW-W1007Use of an insecure version of TLS protocolSW-S1002Use of an insecure block cipher modeSW-S1003Use of an insecure cipher algorithmSW-S1004Prefer using `min()` or `max()` over `sorted().first` or `sorted().last`SW-P1011Prefer using `.first(where:)` over `.filter { }.first` in collectionsSW-P1007Prefer `contains` over `range(of:) != nil` and `range(of:) == nil`SW-P1012Force unwrapping should be avoidedSW-W1023An object should only remove itself as an observer in `deinit`SW-W1028Prefer `contains` over comparing `filter(where:).count` to zeroSW-P1001Prefer `reduce(into:_:)` over `reduce(_:_:)` for copy-on-write typesSW-P1010Prefer using `.allSatisfy()` or `.contains()` over `reduce(true)` or `reduce(false)`SW-P1000Prefer `contains` over using `filter(where:).isEmpty`SW-P1002Prefer `contains` over `first(where:) != nil` and `firstIndex(where:) != nil`SW-P1003Prefer checking `isEmpty` over comparing collection to an empty array or dictionary literalSW-P1004`@IBInspectable` should be applied to variables only, have its type explicit and be of a supported typeSW-W1006`try!` statements should be avoidedSW-W1008When the index or the item is not used, `.enumerated()` can be removedSW-W1002The initializers declared in compiler protocols such as `ExpressibleByArrayLiteral` shouldn’t be called directlySW-W1027Avoid using `dynamic` and `@inline(__always)` togetherSW-W1026Subclasses of `NSObject` should implement `isEqual` instead of `==`SW-W1029Passing `NSNumber.init` or `NSDecimalNumber.init` as a function reference is dangerous as it can cause the wrong initializer to be used, causing crashes; use `.init(value:)` insteadSW-W1030Delegate protocols should be class-only so they can be weakly referencedSW-R1029Prefer using `.last(where:)` over `.filter { }.last` in collectionsSW-P1009TODOs and FIXMEs should be resolvedSW-D1000Extensions shouldn't override declarationsSW-R1020Duplicate import statements are redundant and can be removedSW-W1000Unused parameters in a closure can be replaced with the underscore identifierSW-W1009Audit: Use of legacy functions to generate random values can be insecureSW-A1000Comparing two identical operands is likely a mistakeSW-W1015Unit tests marked `private` are silently skippedSW-W1016Void functions should not be used with ternary operatorsSW-W1018Use of unrestricted base URL in web viewSW-S1000Use of insufficient number of iterations during hash computationSW-S1001Audit: Use of potentially insecure options during XML parsingSW-A1001Prefer using `Array(seq)` over `seq.map { $0 }` to convert a sequence into an ArraySW-R1000Always specify message when invoking `fatalError()`SW-R1021Do not name an enum member as `none`SW-R1025An `XCTFail` call should include a description of the assertionSW-R1032`@IBOutlet`s shouldn’t be declared as weakSW-W1020`fileprivate` should be avoidedSW-R1027Delegates should be weak to avoid reference cyclesSW-W1025Prefer using the `hash(into:)` function instead of overriding `hashValue`SW-R1001Use named arguments in multiline Swift closuresSW-R1004Swift constructors are preferred over legacy convenience functionsSW-R1008Prefer `.zero` over explicit init with zero parametersSW-R1009Returning values from a function returning `Void` should be avoidedSW-R1014Extensions shouldn’t be used to group code within the same source fileSW-R1028Force casts should be avoidedSW-W1013self refers to the unapplied `NSObject.self()` method, which is likely not expectedSW-W1017Implicitly unwrapped optionals should be avoided when possibleSW-W1022Prefer using `Set.isDisjoint(with:)` over `Set.intersection(_:).isEmpty`SW-R1007Shorthand syntactic sugar should be used, i.e. `[Type]` instead of `Array<Type>`SW-C1003`@objc` is redundant when used with implicit Objective-C attributeSW-R1011Setter access control should be different from the variable's access levelSW-R1013Avoid using unneeded break statementsSW-R1018Fallthrough should be avoidedSW-W1012Types used for hosting only static members should be implemented as a caseless enum to avoid instantiationSW-R1030String enum values can be omitted when they are equal to the enum case nameSW-R1031Follow conventions while naming typesSW-C1000Missing documentation commentSW-D1001Use shorthand syntax for optional bindingSW-C1001Prefer `flatMap` over `map` followed by `reduce([], +)`SW-P1008`where` clauses are preferred over a single `if` inside a `for` loopSW-R1005`nil` coalescing operator is never evaluated as it's in RHSSW-R1010Redundant `Optional` initializationSW-R1012Declare operators as static functions instead of free functionsSW-R1015Use `#unavailable`/`#available` instead of `#available`/`#unavailable` with an empty bodySW-R1017Do not explicitly call `.init` methodSW-R1022Unused control flow label should be removedSW-W1010Unimplemented functions should be marked as `unavailable`SW-W1014Use `assertionFailure()` and `preconditionFailure()` over `assert(false)`SW-W1021Generic type name should only contain alphanumeric characters, start with an uppercase character and span between 1 and 20 characters in lengthSW-C1002Prefer checking `isEmpty` over comparing `count` to zeroSW-P1005The constant literal should be placed on the right-hand side of the comparison operatorSW-R1003Catch statements should not declare error variables without type castingSW-R1019Empty `XCTest` method should be avoidedSW-W1031Prefer checking `isEmpty` over comparing `string` to an empty string literalSW-P1006Function with cyclomatic complexity higher than thresholdSW-R1002
Swift logoSwift/
SW-R1002

Function with cyclomatic complexity higher than thresholdSW-R1002

Minor severityMinor
Anti-pattern categoryAnti-pattern

A function with high cyclomatic complexity can be hard to understand and maintain. Cyclomatic complexity is a software metric that measures the number of independent paths through a function. A higher cyclomatic complexity indicates that the function has more decision points and is more complex.

Functions with high cyclomatic complexity are more likely to have bugs and be harder to test. They may lead to reduced code maintainability and increased development time.

To reduce the cyclomatic complexity of a function, you can:

  • Break the function into smaller, more manageable functions.
  • Refactor complex logic into separate functions or classes.
  • Avoid multiple return paths and deeply nested control expressions.

Bad practice

// following code has a complexity of 6
func getColorName(code: Int) -> String {
    if code == 0xFF0000 {
        return "red"
    else if code == 0x00FF00 {
        return "green"
    else if code == 0x0000FF {
        return "blue"
    else if code == 0xFFFF00 {
        return "yellow"
    else if code == 0xFFFFFF {
        return "white"
    } else {
        return "unknown"
    }
}
// following code has a complexity of 2
func getColorName(code: Int) -> String {
    let codeMap = [
        0xFF0000: "red",
        0x00FF00: "green",
        0x0000FF: "blue",
        0xFFFF00: "yellow",
        0xFFFFFF: "white"
    ]
    if let name = codeMap[code] {
        return name
    } else {
        return "unknown"
    }
}

Issue configuration

Cyclomatic complexity threshold can be configured using the cyclomatic_complexity_threshold meta field in the .deepsource.toml config file.

Configuring this is optional. If you don't provide a value, the Analyzer will raise issues for functions with complexity higher than the default threshold, which is 25 (category "high", please refer the table below) for the Swift Analyzer.

Here's the mapping of the risk category to the cyclomatic complexity score to help you configure this better:

Risk categoryCyclomatic complexity rangeRecommended action
low1-5No action needed.
medium6-15Review and monitor.
high16-25Review and refactor. Recommended to add comments if the function is absolutely needed to be kept as it is.
very-high26-50Refactor to reduce the complexity.
critical>50Must refactor this. This can make the code untestable and very difficult to understand.