Static Analysis of PHPCode
How the Heck did I write so many Bugs?PHPCon Poland, September 2016
By Rouven Weßling ( )Ecosystem Developer / Developer Evangelist, Contentful
@RouvenWesslingphoto credit: by Warsaw Kamil Porembiński (license)
class ClientTest extends \PHPUnit_Framework_TestCase{ public function testGetSynchronizationManager() { $client = new Client('b4c0n73n7fu1', 'cfexampleapi');
$this->assertInstanceOf(Manager::class, $client->getSynchronizationManager()); }}
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHP
Reaper PHP vuln hunter RIPS Parse SonarQube SideChannel
Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHPsemver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHP
Reaper PHP vuln hunter RIPS Parse SonarQube SideChannel
Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHPsemver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHP
Reaper PHP vuln hunter RIPS Parse SonarQube SideChannel
Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHPsemver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHP
Reaper PHP vuln hunter RIPS Parse SonarQube SideChannel
Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHPsemver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHP
Reaper PHP vuln hunter RIPS Parse SonarQube SideChannel
Analyzer TaintPHP Deptrac PhpDependencyAnalysis PHPsemver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHPReaper PHP vuln hunter Parse SonarQube Side
ChannelAnalyzer TaintPHP Deptrac PhpDependencyAnalysis PHP
semver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa php7ccCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHPReaper PHP vuln hunter Parse SonarQube Side
ChannelAnalyzer TaintPHP Deptrac PhpDependencyAnalysis PHP
semver checker
phpmd phan phpcs phpunit phploc phpcpd phpsa PHPCoupling Detector Mondrian PHP
Assumption PhpCodeAnalyzer PHPCodeFixer php7mar PHPSemantic Versioning Checker PHP Inspection PHPlint PHP Depend PhpMetrics PHPCheckstyle PHPReaper PHP vuln hunter Parse SonarQube Side
ChannelAnalyzer TaintPHP Deptrac PhpDependencyAnalysis PHP
semver checker
Compiles PHP script with the actual PHP compilerIt's already installed on your computerCan be used to test compatibility with multiple PHPversions
<?phpnamespace Contentful\Log
use Psr\Http\Message\RequestInterface;use Psr\Http\Message\ResponseInterface;
class NullLogger implements LoggerInterface{ public function getTimer() { return new NullTimer; }
public function log($api, RequestInterface $request, StandardTimer $timer, ResponseInterface $response = null, \Exception $exception = null) { }}
PHP 7.0.3 | 10 parallel jobs.................................X...... 40/40 (100 %)
Checked 40 files in 0.5 secondsSyntax error found in 1 file
------------------------------------------------------------Parse error: src/Log/NullLogger.php:9 7| namespace Contentful\Log 8| > 9| use Psr\Http\Message\RequestInterface; 10| use Psr\Http\Message\ResponseInterface; 11|Unexpected 'use' (T_USE), expecting '{'
phploc 3.0.1 by Sebastian Bergmann.
Directories 6Files 40
Size Lines of Code (LOC) 5683 Comment Lines of Code (CLOC) 2562 (45.08%) Non-Comment Lines of Code (NCLOC) 3121 (54.92%) Logical Lines of Code (LLOC) 951 (16.73%) Classes 868 (91.27%) Average Class Length 21 Minimum Class Length 0 Maximum Class Length 190 Average Method Length 2 Minimum Method Length 0 Maximum Method Length 25 Functions 0 (0.00%) Average Function Length 0 Not in classes or functions 83 (8.73%)
Cyclomatic Complexity Average Complexity per LLOC 0.28 Average Complexity per Class 7.65 Minimum Class Complexity 1.00 Maximum Class Complexity 62.00 Average Complexity per Method 1.82 Minimum Method Complexity 1.00 Maximum Method Complexity 11.00
Dependencies Global Accesses 0 Global Constants 0 (0.00%) Global Variables 0 (0.00%) Super-Global Variables 0 (0.00%) Attribute Accesses 536 Non-Static 535 (99.81%) Static 1 (0.19%) Method Calls 319 Non-Static 308 (96.55%) Static 11 (3.45%)
Structure Namespaces 7 Interfaces 3 Traits 0 Classes 37 Abstract Classes 3 (8.11%) Concrete Classes 34 (91.89%) Methods 272 Scope Non-Static Methods 272 (100.00%) Static Methods 0 (0.00%) Visibility Public Methods 221 (81.25%) Non-Public Methods 51 (18.75%) Functions 6 Named Functions 0 (0.00%) Anonymous Functions 6 (100.00%) Constants 2 Global Constants 0 (0.00%) Class Constants 2 (100.00%)
layers: - name: Controller collectors: - type: className regex: .*Controller.* - name: Entity collectors: - type: className regex: AstaRwth\\VorkursticketBundle\\Entity\\.*
ruleset: Controller: - Service - Entity - Form Service: - Repository Command: - Entity Entity: - Validator
How it worksParses all files in your codeStores which classes access which others classesChecks the graph for rule violations
deptrac is alpha, not production ready.please help us and report feedback / bugs.
Start to create an AstMap for 24 Files.........................AstMap created.start emitting dependencies "InheritanceDependencyEmitter"start emitting dependencies "BasicDependencyEmitter"end emitting dependenciesstart flatten dependenciesend flatten dependenciescollecting violations.formatting dependencies.[...]\Services\PdfOrder::5 must not depend on [...]\Entity\Vorkursticket (Service on Entity)[...]\Services\PdfOrder::23 must not depend on [...]\Entity\Vorkursticket (Service on Entity)
Found 2 Violations
How it worksMakes 2 passes over the codebase1. Build a list of all classes, functions, methods, etc.2. Go trough each function and follow the type ofeach variable
/** * @param Locale|string|null $locale * * @return string */public function getDescription($locale = null){ $localeCode = $this->getLocaleFromInput($locale);
// This checks happens after the call to getLocaleFromInput to make sure // the Exception for invalid locales is still thrown. if ($this->description === null) { return null; }
return $this->description->$localeCode;}
src/Delivery/Asset.php:74 PhanTypeMismatchReturn Returning type nullbut getDescription() is declared to return string
class ContentType{ /** * The fields, keyed by ID. * * @var object */ private $fields = [];}
src/Delivery/ContentType.php:34 PhanTypeMismatchProperty Assigning array toproperty but \contentful\delivery\contenttype::fields is object
public function __call($name, $arguments){ // Lots of code here
if ($result instanceof Link) { return $client->resolveLink($result); }
return array_map(function ($value) use ($client) { if ($value instanceof Link) { return $client->resolveLink($value); }
return $value; }, $result);}
src/Delivery/DynamicEntry.php:126PhanTypeMismatchArgumentInternal Argument 2 (input1) is\contentful\delivery\link but \array_map() takes array
Not a bug
phan is using brute force for type checkingRoughly as good as the compiler for a staticallytyped languageWorks, but a Control Flow Graph could give evendeeper insight
Bottom lineThere are dozens of tools - pick what's necessary foryouMake them part of your Continuous Integration setupNever trust. Make sure you understand where theerror is coming from.
Slides available on Slideshare:http://www.slideshare.net/rwessling
Please leave feedback on joind.in( ) or tweet me
( )https://joind.in/talk/8f19b
@RouvenWessling