Andrew Latham

Introduction

Analyzing code to look for irregularities most commonly done with language specific Style Checks is a method of discovering things about the code and possibly some pointers to resolving issues.

Code Quality

While it is true that style checks can be part of a larger code quality metric in this article we are discussing using them in a more forensic way to discover possible copy/paste and changes in developers over time.

Howto

Using https://github.com/PHPCheckstyle/phpcheckstyle which is well documented and easy to download and run. This could be downloaded and ran against code in a continuous integration system for each run as the requirements and processing needs are so low.

Example

Using the example in the project to show what the results might look like.

$ php run.php --src ./test/sample/issuegithub32.php --outdir ./checkstyle_result /
--config default.cfg.xml --format html,xml --linecount --debug
Processing File : ./test/sample/issuegithub32.php

Level 0 - line : 1, pos : 0, id : T_OPEN_TAG, text : <?php 

Level 0 - line : 1, pos : 1, id : T_NEW_LINE, text : \n

Level 0 - line : 2, pos : 2, id : T_NEW_LINE, text : \n

Level 0 - line : 3, pos : 3, id : T_STRING, text : App

Level 0 - line : 3, pos : 4, id : T_DOUBLE_COLON, text : ::

Level 0 - line : 3, pos : 5, id : T_STRING, text : error

Level 0 - line : 3, pos : 6, id : T_PARENTHESIS_OPEN, text : (

Level 0 - line : 3, pos : 7, id : T_FUNCTION, text : function

Level 0 - line : 3, pos : 8, id : T_PARENTHESIS_OPEN, text : (

Level 0 - line : 3, pos : 9, id : T_PARENTHESIS_CLOSE, text : )

Level 0 - line : 3, pos : 10, id : T_WHITESPACE, text :  

Level 0 - line : 3, pos : 11, id : T_BRACES_OPEN, text : {
FUNCTION(anonymous) -> 
Level 1 - line : 3, pos : 12, id : T_NEW_LINE, text : \n
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 13, id : T_TAB, text : 
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 14, id : T_IF, text : if
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 15, id : T_WHITESPACE, text :  
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 16, id : T_PARENTHESIS_OPEN, text : (
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 17, id : T_STRING, text : Config
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 18, id : T_DOUBLE_COLON, text : ::
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 19, id : T_STRING, text : get
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 20, id : T_PARENTHESIS_OPEN, text : (
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 21, id : T_CONSTANT_ENCAPSED_STRING, text : 'app.debug'
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 22, id : T_PARENTHESIS_CLOSE, text : )
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 23, id : T_WHITESPACE, text :  
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 24, id : T_IS_IDENTICAL, text : ===
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 25, id : T_WHITESPACE, text :  
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 26, id : T_STRING, text : FALSE
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 27, id : T_PARENTHESIS_CLOSE, text : )
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 28, id : T_WHITESPACE, text :  
FUNCTION(anonymous) -> 
Level 1 - line : 4, pos : 29, id : T_BRACES_OPEN, text : {
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 4, pos : 30, id : T_NEW_LINE, text : \n
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 31, id : T_WHITESPACE, text : 
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 32, id : T_ECHO, text : echo
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 33, id : T_WHITESPACE, text :  
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 34, id : T_CONSTANT_ENCAPSED_STRING, text : "Not empty"
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 35, id : T_SEMICOLON, text : ;
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 5, pos : 36, id : T_NEW_LINE, text : \n
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 6, pos : 37, id : T_TAB, text : 
FUNCTION(anonymous) -> IF -> 
Level 2 - line : 6, pos : 38, id : T_BRACES_CLOSE, text : }
FUNCTION(anonymous) -> 
Level 1 - line : 6, pos : 39, id : T_NEW_LINE, text : \n
FUNCTION(anonymous) -> 
Level 1 - line : 7, pos : 40, id : T_BRACES_CLOSE, text : }

Level 0 - line : 7, pos : 41, id : T_PARENTHESIS_CLOSE, text : )

Level 0 - line : 7, pos : 42, id : T_SEMICOLON, text : ;

Summary
=======

Errors:   0
Ignores:  0
Infos:    0
Warnings: 1
=======

Reporting Completed.

References

https://en.wikipedia.org/wiki/Static_program_analysis