A linter scans source a file at a time, matching it against a rule set of suspicious patterns and reporting likely bugs. It is the cheap, high-volume end of static analysis, fast enough to run on every save and every diff and tuned to keep false positives low. Only the logical rules do verification work; a linter's stylistic and formatting rules are hygiene, better delegated to a formatter.
What it catches¶
- Common defect patterns. Off-by-one, missing
await, inconsistent equality, suspicious type cast. - API misuse. Calling a deprecated function, passing the wrong type, ignoring a required return value, misusing a standard-library contract.
Several defect classes have their own static-analysis page even where a lint rule is what ships the check. Taint, secrets, and regular-expression denial of service (ReDoS) are on deep static analysis. Every kind of dead code is on dead-code detection. Memory-safety and concurrency depth is on memory safety and concurrency.
Tools¶
JavaScript / TypeScript¶
- ESLint with the typescript-eslint logical subset enabled; the stylistic and formatting subsets go to Prettier.
- Biome as a faster ESLint+Prettier alternative.
Python¶
- Ruff — fast, covers a broad rule set, replacing flake8 + many plugins.
- pylint — slower, more checks, harder to configure.
- Bandit — security-focused rules.
Rust¶
- Clippy — built into the Rust toolchain. The Clippy adoption study found ~21 warnings per thousand lines of code on average across crates.io (Li et al. 2024)1.
- cargo-audit for dependencies with known vulnerabilities.
Java / Kotlin¶
- SpotBugs (successor to FindBugs).
- Error Prone (Google) — runs as a compiler plugin.
C / C++¶
- Coverity (commercial) — a widely deployed commercial tool; a large-scale retrospective covers it (Bessey et al. 2010)2.
- clang-tidy — free, ships with LLVM.
- Infer — Facebook's tool, free; especially strong on null-deref and concurrency.
- Cppcheck, scan-build.
Go¶
go vetin the standard toolchain.- staticcheck — broad, high-quality checks.
- golangci-lint runs many linters in one pass.
When to use, when not¶
Use:
- At diff time, with a small high-confidence ruleset expanded over time.
- With logical rules only; hand formatting and style to a formatter so the signal is bugs, not whitespace.
Don't:
- Gate the build on a complexity metric. Cyclomatic and cognitive complexity are advisory refactoring signals, not verification. A duplicate-branch or identical-condition rule flags an actual likely bug; a complexity threshold flags only "this is large."
Evidence¶
- Clippy in the wild. Across real-world Rust projects, false positives and missing auto-fix are the dominant non-adoption reasons (Li et al. 2024)1.
- Complexity metrics are weak gates. Cyclomatic complexity (McCabe 1976)3 rests on contested theoretical foundations and in practice largely tracks lines of code, adding little independent predictive value (Shepperd 1988)4. SonarSource's Cognitive Complexity (Campbell 2018)5 reformulates it to target human understandability; the one controlled validation found it correlates with comprehension time and subjective ratings, but with mixed results for task correctness — capturing "at least some aspects" of understandability (Muñoz Barón et al. 2020)6.
Classification¶
- Quality dimensions: Functionality, Maintainability.
- Area: General code quality and common defect patterns; per-language tooling run at diff time; API-misuse and suspicious-construct rules.
- Guarantee: Empirical — depends on rule precision and recall; a high-confidence signal, not a proof.
Referenced by¶
- Abstract interpretation · Methods
- Checklists · Methods
- Database migration safety · Methods
- Dead-code detection · Methods
- Static analysis · Methods
- Verifying concurrency · Methods
- Verifying memory safety · Methods
- Verifying time and date handling · Methods
References¶
-
Li, Chunmiao, Yijun Yu, Haitao Wu, Yuanliang Zhang, Zhi Jin, and Zhenjiang Hu. 2024. "Unleashing the Power of Clippy in Real-World Rust Projects." Proceedings of the 2024 IEEE/ACM 46th International Conference on Software Engineering: Companion Proceedings, 318–19. https://doi.org/10.1145/3639478.3643096. ↩↩
-
Bessey, Al, Ken Block, Ben Chelf, et al. 2010. "A Few Billion Lines of Code Later: Using Static Analysis to Find Bugs in the Real World." Communications of the ACM 53 (2): 66–75. https://doi.org/10.1145/1646353.1646374. ↩
-
McCabe, Thomas J. 1976. "A Complexity Measure." IEEE Transactions on Software Engineering SE-2 (4): 308–20. https://doi.org/10.1109/TSE.1976.233837. ↩
-
Shepperd, Martin. 1988. "A Critique of Cyclomatic Complexity as a Software Metric." Software Engineering Journal 3 (2): 30–36. https://doi.org/10.1049/sej.1988.0003. ↩
-
Campbell, G. Ann. 2018. "Cognitive Complexity: An Overview and Evaluation." Proceedings of the 2018 International Conference on Technical Debt (TechDebt '18), 57–58. https://doi.org/10.1145/3194164.3194186. ↩
-
Muñoz Barón, Marvin, Marvin Wyrich, and Stefan Wagner. 2020. "An Empirical Validation of Cognitive Complexity as a Measure of Source Code Understandability." Proceedings of the 14th ACM/IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM '20), 1–12. https://doi.org/10.1145/3382494.3410636. ↩