Dead Code Detection in PHP

How can I find unused functions in a PHP project

Thanks Greg and Dave for the feedback. Wasn't quite what I was looking for, but I decided to put a bit of time into researching it and came up with this quick and dirty solution:

<?php
$functions = array();
$path = "/path/to/my/php/project";
define_dir($path, $functions);
reference_dir($path, $functions);
echo
"<table>" .
"<tr>" .
"<th>Name</th>" .
"<th>Defined</th>" .
"<th>Referenced</th>" .
"</tr>";
foreach ($functions as $name => $value) {
echo
"<tr>" .
"<td>" . htmlentities($name) . "</td>" .
"<td>" . (isset($value[0]) ? count($value[0]) : "-") . "</td>" .
"<td>" . (isset($value[1]) ? count($value[1]) : "-") . "</td>" .
"</tr>";
}
echo "</table>";
function define_dir($path, &$functions) {
if ($dir = opendir($path)) {
while (($file = readdir($dir)) !== false) {
if (substr($file, 0, 1) == ".") continue;
if (is_dir($path . "/" . $file)) {
define_dir($path . "/" . $file, $functions);
} else {
if (substr($file, - 4, 4) != ".php") continue;
define_file($path . "/" . $file, $functions);
}
}
}
}
function define_file($path, &$functions) {
$tokens = token_get_all(file_get_contents($path));
for ($i = 0; $i < count($tokens); $i++) {
$token = $tokens[$i];
if (is_array($token)) {
if ($token[0] != T_FUNCTION) continue;
$i++;
$token = $tokens[$i];
if ($token[0] != T_WHITESPACE) die("T_WHITESPACE");
$i++;
$token = $tokens[$i];
if ($token[0] != T_STRING) die("T_STRING");
$functions[$token[1]][0][] = array($path, $token[2]);
}
}
}
function reference_dir($path, &$functions) {
if ($dir = opendir($path)) {
while (($file = readdir($dir)) !== false) {
if (substr($file, 0, 1) == ".") continue;
if (is_dir($path . "/" . $file)) {
reference_dir($path . "/" . $file, $functions);
} else {
if (substr($file, - 4, 4) != ".php") continue;
reference_file($path . "/" . $file, $functions);
}
}
}
}
function reference_file($path, &$functions) {
$tokens = token_get_all(file_get_contents($path));
for ($i = 0; $i < count($tokens); $i++) {
$token = $tokens[$i];
if (is_array($token)) {
if ($token[0] != T_STRING) continue;
if ($tokens[$i + 1] != "(") continue;
$functions[$token[1]][1][] = array($path, $token[2]);
}
}
}
?>

I'll probably spend some more time on it so I can quickly find the files and line numbers of the function definitions and references; this information is being gathered, just not displayed.

Dead code detection in PHP

xdebug's code coverage tools allow you to test which lines of code are actually being executed, without needing to put trace statements in all of the functions/methods.

Example:

<?php
xdebug_start_code_coverage();

function a($a) {
echo $a * 2.5;
}

function b($count) {
for ($i = 0; $i < $count; $i++) {
a($i + 0.17);
}
}

b(6);
b(10);

var_dump(xdebug_get_code_coverage()); // array '/path/file.php' => array line_number => int 1 or 0.
?>

Tools to detect useless file or useless code PHP

PHP Mess Detector (PHPMD):

  • Possible bugs;
  • Suboptimal code;
  • Overcomplicated expressions;
  • Unused parameters, methods, properties.

PHPMD will show to you all mess created in your code. It's also show the cyclomatic complexity of your codem which will let you do a few code optimizations.

PHP Depend

PHPMD is a spin-off of PHP Depend. PHP Depend will show to you better metrics and graphics of your software than PHPMD. A really powerfull tool, better than PHPMD for optimization, but with a different purpose.

Mark Baker also talked about PHP Dead Code Detector (PHPDCD). IDK the project, but seems very similar to PHPMD.

Can I detect dead php code with SonarQube? If yes, how?

Yes, and no.

There are currently 8 PHP rules related to unused code. However, the current state of PHP analyzer limits rules to running within a file, so there's not yet any ability to find classes in a project that are never used, for instance.

How do I use Psalm's UnusedMethod Feature?

Psalm creator here - dead code detection only detects unused classes and methods when the entire project is analysed - e.g. ./vendor/bin/psalm --find-dead-code, omitting src/test.php.

While private methods and properties are a special case (their non-use can be inferred without checking the entire project), for public/protected methods and properties everything must be consumed.

Best way to debug my way through a newly acquainted large PHP app and detect dead code?

As per the discussion in the comments, I'd wondered if the execution coverage tools in XDebug would help here. This is a low-level code monitor that watches what lines of PHP code have been executed when you start a program. As you'd expect, this adds a certain level of overhead, so it is generally not added to live environments.

Hosted build systems like Travis and Scrutinizer do code coverage reporting, though they probably rely on tools like PHPUnit and XDebug to actually make them work.



Related Topics



Leave a reply



Submit