Here's some code to detect a few code smells in a PHP file. It can be easily adapted to detect code smells in C, C++, Java, etc. code.
$MAX_INDENTATION_LEVEL = 3;
$MAX_FUNCTION_LINE_COUNT = 20;
$MAX_NUM_PARAMETERS = 4;
function print_warning( $filename, $line, $line_number, $warning )
{
print( "$filename
: $warning
\n" .
" Line $line_number: $line
\n" );
}
function test_line_for_indentation( $line, $max_indentation_level )
{
$char_posit = 0;
while( substr( $line, $char_posit, 1 ) == "\t" )
$char_posit++;
if( $char_posit > $max_indentation_level )
return false;
return true;
}
function test_line_for_function_definition( $line, $max_num_parameters )
{
if( substr( $line, 0, 9 ) == "function " )
{
if( substr_count( $line, ',' ) >= $max_num_parameters )
return false;
}
return true;
}
function test_file_for_smells( $filename )
{
global $MAX_FUNCTION_LINE_COUNT, $MAX_INDENTATION_LEVEL;
$function_line_count = 0;
$found_continued_line = 0;
$line_number = 0;
$fp = fopen( $filename, "r" );
if( ! $fp )
return;
while( ! feof( $fp ) )
{
$line = chop( fgets( $fp, 4096 ) );
$line_number++;
while( substr( $line, 0, 9 ) == "function " &&
substr( $line, strlen($line) - 1, 1 ) != ')' )
{
$line = $line . chop( fgets( $fp, 4096 ) )
$found_continued_line++;
}
if( substr( $line, 0, 9 ) == "function " )
{
$function_line_count = 1;
$function_name = substr( $line, 9, strpos($line, '(') - 9 );
}
if( $function_line_count > 0 )
{
if( $line == "\t}" )
{
$function_line_count = $function_line_count - 3;
if( $function_line_count > $MAX_FUNCTION_LINE_COUNT )
print_warning( $filename, $line, $line_number, "$function_name() too long ($function_line_count lines)" );
$function_line_count = 0;
}
else
$function_line_count++;
$result = test_line_for_indentation( $line, $MAX_INDENTATION_LEVEL );
if( ! $result )
print_warning( $filename, $line, $line_number, "Too much nesting." );
$result = test_line_for_function_definition( $line, $MAX_NUM_PARAMETERS );
if( ! $result )
print_warning( $filename, $line, $line_number, "Too many parameters." );
if( $found_continued_line > 0 )
{
$line_number += $found_continued_line;
$found_continued_line = 0;
}
}
}
}
Please feel free to ReFactor this code. test_file_for_smells() would fail its own tests! -- BrentNewhall
''Doesn't this assume tabs are always used for indentation?''
This code probably needs to be refactored to use the tokenizer extension. I have a "CodeSmeller" object written in PHP5, I will post it soon. -- JonathanArkell
----
CategoryPhp