NuSphere Forums Forum Index
NuSphere Forums
Reply to topic
ZendCodeAnalyzer
Guru master

Joined: 05 Jul 2004
Posts: 659
Location: Belgium
Reply with quote
Zend Studio has a nice little addition called the code analyzer. It checks your php code and points out possible flaws and other stuff.
Fortunately for us the code analyzer is a separate executable so it's pretty easy to use in PhpED.
You can get the executable itself by downloading a trial version of Zend Studio.
The file you need is called ZendCodeAnalyzer.exe

For ease of use I've modified a PHP5 script written by Knut Urdalen.
It's a quick 'n dirty hack job, so obviously not the best code, but I thought it might be useful to others.
The original class also includes support for scanning entire folders, but I only implemented a single file. I left the rest of the code in there though.

I set it up so that the php5 exectable included with phped is used, this give the least clutter and the fastest results.
just call php.exe with the script as parameter and add "@FName@" to the end.

The script assumes the executable is in a bin\ subdirectory relative to the script, but that can be changed.

Why a script and not call ZendCodeAnalyzer directly?
This script allows me to modify the way the messages are outputted. I don't like the default ZCA output as it's too much.
And I'm still secretly hoping PhpED will add support for specifying files and line numbers, so that the messages get clickable. With this script I would be able to accommodate for the line-format they will support (fingers crossed).

The script:
Code:

<?php
/**
 * ZendCodeAnalyzerTask analyze PHP source code using the ZendCodeAnalyzer included in Zend Studio 5.1
 *
 * Available warnings:
 * <b>zend-error</b> - %s(line %d): %s
 * <b>oneline-comment</b> - One-line comment ends with ?> tag.
  * <b>bool-assign</b> - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='?
  * <b>bool-print</b> - Print statement used when boolean expression is expected.
  * <b>bool-array</b> - Array used when boolean expression is expected.
  * <b>bool-object</b> - Object used when boolean expression is expected.
  * <b>call-time-ref</b> - Call-time reference is deprecated. Define function as accepting parameter by reference instead.
  * <b>if-if-else</b> - In if-if-else construction else relates to the closest if. Use braces to make the code clearer.
  * <b>define-params</b> - define() requires two or three parameters.
  * <b>define-const</b> - First parameter for define() should be string. Maybe you forgot quotes?
  * <b>break-var</b> - Break/continue with variable is dangerous - break level can be out of scope.
  * <b>break-depth</b> - Break/continue with depth more than current nesting level.
  * <b>var-once</b> - Variable '%s' encountered only once. May be a typo?
  * <b>var-arg-unused</b> - Function argument '%s' is never used.
  * <b>var-global-unused</b> - Global variable '%s' is defined but never used.
  * <b>var-use-before-def</b> - Variable '%s' is used before it was assigned.
  * <b>var-use-before-def-global</b> - Global variable '%s' is used without being assigned. You are probably relying on register_globals feature of PHP. Note that this feature is off by default.
  * <b>var-no-global</b> - PHP global variable '%s' is used as local. Maybe you wanted to define '%s' as global?
  * <b>var-value-unused</b> - Value assigned to variable '%s' is never used
  * <b>var-ref-notmodified</b> - Function parameter '%s' is passed by reference but never modified. Consider passing by value.
  * <b>return-empty-val</b> - Function '%s' has both empty return and return with value.
  * <b>return-empty-used</b> - Function '%s' has empty return but return value is used.
  * <b>return-noref</b> - Function '%s' returns reference but the value is not assigned by reference. Maybe you meant '=&' instead of '='?
  * <b>return-end-used</b> - Control reaches the end of function '%s'(file %s, line %d) but return value is used.
  * <b>sprintf-miss-args</b> - Missing arguments for sprintf: format reqires %d arguments but %d are supplied.
  * <b>sprintf-extra-args</b> - Extra arguments for sprintf: format reqires %d arguments but %d are supplied.
  * <b>unreach-code</b> - Unreachable code in function '%s'.
  * <b>include-var</b> - include/require with user-accessible variable can be dangerous. Consider using constant instead.
  * <b>non-object</b> - Variable '%s' used as object, but has different type.
  * <b>bad-escape</b> - Bad escape sequence: \%c, did you mean \\%c?
  * <b>empty-cond</b> - Condition without a body
  * <b>expr-unused</b> - Expression result is never used
  *
  * @author   Knut Urdalen <knut.urdalen@telio.no>
  * @package  phing.tasks.ext
  */
class ZendCodeAnalyzer
{
   protected $msAnalyzerPath;  // Path to ZendCodeAnalyzer binary
   protected $msFile = "";                                  // the source file (from xml attribute)
   protected $maFileSet = Array ( );
   protected $maWarningsEnabled = Array ( );
   protected $maWarningsDisabled = Array ( );

   public function Execute ( )
   {
      if ( ! isset ( $this -> msAnalyzerPath ) )
         die (  "Missing attribute 'analyzerPath'" );

      if ( ! isset ( $this -> msFile ) && count ( $this -> maFileSet ) == 0 )
         die ("Missing either a nested fileset or attribute 'file' set");

      if ( ! empty ( $this -> msFile ) )
      {
         return $this -> Analyze ( $this -> msFile );
      }
      /*else { // process filesets
       $project = $this->getProject();
       foreach($this->filesets as $fs) {
           $ds = $fs->getDirectoryScanner($project);
           $files = $ds->getIncludedFiles();
           $dir = $fs->getDir($this->project)->getPath();
           foreach($files as $file) {
       $this->analyze($dir.DIRECTORY_SEPARATOR.$file);
           }
       }
     }
     $this->log("Number of findings: ".$this->counter, PROJECT_MSG_INFO);*/
   }

   public function SetAnalyzer ( $sFile )
   {
      $this -> msAnalyzerPath = $sFile;
   }

   public function SetFile ( $sFile )
   {
      $this -> msFile = $sFile;
   }

   /**
    * Analyze file
    *
    * @param string $file
    * @return void
    */
   protected function Analyze ( $sFile )
   {
      if ( ! file_exists ( $sFile ) || ! is_readable ( $sFile ) )
         return FALSE;

      // Construct shell command
      $sCMD = '"' . $this -> msAnalyzerPath . '" ';
      foreach ( $this -> maWarningsEnabled as $sEnable )    // Enable warning levels
         $sCMD .= ' --enable ' . $sEnable;

      foreach ( $this -> maWarningsDisabled as $sDisable )  // Disable warning levels
         $sCMD .= ' --disable ' . $sDisable;
      $sCMD .= $sFile . ' 2>&1';

      // Execute command
      $sResult = shell_exec ( $sCMD );
      $aResult = explode ( "\n", $sResult );
      $nLines = count ( $aResult );
      $aMessages = Array ( );
      for ( $n= 2; $n <= $nLines; $n ++ )
         if ( preg_match ( '/(.+)\(line (\d+)\): (.+)/', $aResult [ $n ], $aMatches ) )
         {
            $aMessages [ ] = Array
            (
               'directory'    => dirname ( $aMatches [ 1 ] ),
               'file'         => basename ( $aMatches [ 1 ] ),
               'line'         => intval ( $aMatches [ 2 ] ),
               'message'      => trim ( $aMatches [ 3 ] ),
            );
         }
      return $aMessages;
   }
}

   $oAnalyzer = new ZendCodeAnalyzer;

   $oAnalyzer -> SetAnalyzer ( dirname ( $_SERVER [ 'PHP_SELF' ] ) . "\\bin\\ZendCodeAnalyzer.exe" );
   if ( ! empty ( $argv [ 1 ] ) )
   {
      $oAnalyzer -> SetFile ( $argv [ 1 ] );
      echo 'Analyzing "' . $argv [ 1 ] . '"...' . "\r\n";
   }
   $aMessages = $oAnalyzer -> Execute ( );
   if ( $aMessages === FALSE )
      echo 'Something went wrong!';
   else
   {
      if ( count ( $aMessages ) )
         foreach ( $aMessages as $aMessage )
            echo $aMessage [ 'file' ] . '(' . $aMessage [ 'line' ] . ') ' . $aMessage [ 'message' ] . "\r\n";
      else
         echo "All OK!\r\n";
   }

?>
View user's profileFind all posts by BlizzSend private messageVisit poster's website
ZendCodeAnalyzer
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
All times are GMT - 5 Hours  
Page 1 of 1  

  
  
 Reply to topic