Partly. SonarQube reports unused code that's local or private: a variable, parameter, import, private method or private class that nothing in the same scope uses. Searching its rules, we found none for a public function, class or export that nothing in the project calls, and none for unused files.

What SonarQube's rules cover

These are the rules about unused or unreachable code that SonarSource's own SonarQube instance returned for each language when searched for "unused", "dead", "unreachable" and "reachable" (rule search, 13 October 2026). "None found" means no rule came back for that kind of dead code:

Kind of dead codePythonTypeScriptJava
Unused local variablesS1481none foundS1481
Unused parametersS1172S1172S1172
Unused assignments (dead stores)S1854S1854S1854
Unused importsS1128S1128S1128
Unused private methodsS1144 (class-private)S1068 (private class members)S1144
Unused private classes or fieldsS3985, S4487S1068S3985, S1068
Unused nested definitionsS5603none foundnone found
Unreachable codeS1763S1763S2583
Unused React props and component methodsn/aS6767, S6441n/a
Unused public function, class or exportnone foundnone foundnone found
Unused filenone foundnone foundnone found

Every rule above works inside one function, class or file. That's why SonarQube is reliable for them: the answer is local.

What it misses, in practice

A public function that nothing calls is invisible to those rules. In this small repository, legacy_slugify, Formatter.render_upper and formatPriceLegacy are all defined and never used:

# app/text.py
def slugify(title: str) -> str: ...          # used by Formatter.render
def legacy_slugify(title: str) -> str: ...   # never called

class Formatter:
    def render(self, title: str) -> str: ...        # used by main.py
    def render_upper(self, title: str) -> str: ...  # never called
// web/format.ts
export function formatPrice(cents: number): string { /* used by index.ts */ }
export function formatPriceLegacy(cents: number): string { /* never imported */ }

None of them is local or private, so no rule in the table applies. Skylos 4.47.2 reports all three, and nothing that is used:

$ skylos . --format concise
app/text.py:8  SKY-U001  unused function: legacy_slugify
app/text.py:16  SKY-U001  unused function: Formatter.render_upper
web/format.ts:5  SKY-U001  unused function: formatPriceLegacy

Why public dead code needs a different tool

Proving that a public function is unused means checking every possible caller:

  • Every module that might import it, including re-exports and __all__.
  • Framework entry points that are never called directly: routes, views, CLI commands, signal handlers and test fixtures.
  • Dynamic use: names passed as strings, getattr, plugin registries.

A rule that looks at one file can't answer that, so it reports nothing rather than guess. Dedicated dead-code tools build a reference graph of the whole repository instead. Skylos also models framework entry points, such as FastAPI routes and pytest fixtures, so they aren't reported as unused. Python has its deepest coverage. TypeScript/JavaScript, Java, PHP, Rust and Dart are also covered (language support).

Use both

SonarQube's unused-code rules and a whole-project dead-code check don't overlap much, so they work well together:

pip install skylos
skylos .                      # dead code across the whole project
skylos . --diff-base origin/main --diff origin/main   # only what a pull request changed

Skylos's dead-code findings have been the basis of cleanup pull requests that maintainers merged in several open-source projects (the list).