Skip to content

Latest commit

 

History

History
76 lines (53 loc) · 3.48 KB

File metadata and controls

76 lines (53 loc) · 3.48 KB

SonarQube S1144 — False Positive: Private Methods Called Across Trait Boundaries

The Problem

SonarQube S1144 flags private methods it cannot find any callers for:

"Remove this unused private 'methodName' method."

This becomes a false positive when:

  1. A method is declared private inside a class file, and
  2. Its only caller is a $this->method() call inside a trait file that the class composes.

SonarQube's cross-file analysis cannot trace $this->method() calls that cross PHP trait file boundaries. It sees the method as having zero callers and raises S1144 even though the method is genuinely used at runtime.

Concrete Example (June 2026)

Three private methods in two controllers were flagged:

ERROR: php:S1144 - src/Invoice/Inv/InvController.php:388
  Remove this unused private 'displayeditdeletebuttons' method.

ERROR: php:S1144 - src/Invoice/Inv/InvController.php:397
  Remove this unused private 'flashnoenabledgateways' method.

ERROR: php:S1144 - src/Auth/Controller/AuthController.php:814
  Remove this unused private 'redirecttoadminmustmakeactive' method.

In each case the method was used — just from a trait file:

Method (class file) Caller (trait file)
InvController::displayEditDeleteButtons (InvController.php:388) $show_buttons = $this->displayEditDeleteButtons($read_only);View.php:72
InvController::flashNoEnabledGateways (InvController.php:397) $this->flashNoEnabledGateways($enabled_gateways, ...);View.php:49
AuthController::redirectToAdminMustMakeActive (AuthController.php:814) return $this->redirectToAdminMustMakeActive();Callback.php:1295

PHP inlines trait code into the composing class at compile time, so all three calls resolve correctly at runtime. SonarQube's static analysis does not model this.

The Fix

Change the visibility of the falsely-flagged method from private to protected:

// Before — triggers S1144 false positive:
private function displayEditDeleteButtons(bool $read_only): bool { ... }

// After — S1144 only fires on private methods; protected is not flagged:
protected function displayEditDeleteButtons(bool $read_only): bool { ... }

S1144 is defined as "Remove this unused private method." Changing to protected is both semantically appropriate (trait callers are effectively subclass-like consumers) and sufficient to silence the rule without a // NOSONAR suppression.

Why Not // NOSONAR?

// NOSONAR suppresses all rules on a line permanently. Changing to protected is the self-documenting fix: it communicates "this method is part of the protected surface used by composed traits" rather than "we have silenced an unknown warning here."

Related

  • SonarQube S1448 — Too Many Methods (entity classes split into trait groups to pass the 20-method limit — the same trait extraction pattern that introduces S1144 false positives)
  • PHP trait visibility rulesprivate methods in traits are private to the trait; private methods in the class are accessible from inlined trait code at runtime but invisible to static analysis tools that do not model trait inlining.