I was looking around on the web for a good way to detect when code is no longer used in the app and couldn't really find anything good. The best I found was this app that's no longer maintained. Are there any plans to get some sort of static analyzer that could detect unused code?
I don’t know of any static analyzers that can do this with Swift.
I enforce 100% test coverage and write tests without @testable
. Then it is obvious when code goes dead, because it suddenly flags as untested.
I've spoken about strategies for doing this before:
- Video: Swift & Fika 2018 – JP Simard: Bespoke Artisanal Swift Static Analysis - YouTube
- Slides: Bespoke, Artisanal Swift Static Analysis - Speaker Deck
And have some open source solutions in SwiftLint:
We've been using it at Lyft for the last ~8 months, running daily on our codebase and it's found over a thousand lines of dead code in that time. There are also analyzer rules to delete unused imports, about 3,000 have been found, and other rules like enforcing explicit use of self.
when accessing instance members.
The framework supports writing new types of analyzers too if anyone has ideas. Some possible rules that I haven't taken the time to build yet are:
- Over-exposed declarations (i.e.
internal
that could be madeprivate
) - Superfluous type annotations
- Inefficient code patterns
- Converting imperative code to functional equivalents
I'm happy to help anyone who's interested in contributing these kinds of static analysis rules.
That's great JP. Thanks for the super detailed post!
FWIW, the github repo of Periphery is still alive and kicking.
Couldn’t that also yield false positive? If you have tests used for otherwise unused code, it wouldn’t be flagged as unused because the tests are using them right?
Without @testable
, there is no way to call anything not part of the public API. You may have pointless leftover API still being tested, but there is no such thing as dead API. By definition API is reachable.
No static analyzer will ever be able to catch dated or redundant API for you. It will at best be able to check which parts are ever called by tests or known clients.