Nested Callbacks
ID |
swift.nested_callbacks |
Severity |
info |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Complexity |
Language |
Swift |
Tags |
async, complexity |
Description
Reports a callback closure whose nesting depth exceeds a configurable threshold. A "callback" here is a closure passed as an argument to a function call (including Swift’s trailing-closure syntax).
Configuration
-
maxNesting(default5) — callback nesting depths strictly greater than this value are flagged.
Rationale
Deep callback chains — "callback hell" — are hard to read. Each level
shifts the indentation and pulls the next operation away from the
previous one, so the linear order of work disappears under the
brace structure. Error handling becomes scattered, early returns are
impossible, and defer no longer captures the natural lifetime of the
operation. The classic refactor is async/await, which restores the
linear shape; for event-style APIs, extracting named helper functions
usually relieves the nesting too.
Notes
-
Only the inner-most offending closure is flagged so the issue count tracks refactorable spots, not the depth of the chain.
-
Closures that are not in an argument position (e.g. a closure stored in a variable) are not considered callbacks.
Remediation
// Callback pyramid.
fetch(url) { res in
parse(res) { data in
transform(data) { out in
persist(out) { id in
notify(id) { ... }
}
}
}
}
// Linear with async/await.
let res = try await fetch(url)
let data = try await parse(res)
let out = try await transform(data)
let id = try await persist(out)
try await notify(id)