public function advance($parser)
 {
     if ($this->pos >= 0) {
         $type = $this->tokens[$this->pos][0];
         switch ($type) {
             case T_FOR:
             case T_FOREACH:
                 $this->start_loop();
                 break;
             case T_DO:
                 $this->ignoreNextWhile = true;
                 $this->start_loop();
                 break;
             case T_WHILE:
                 if (!$this->ignoreNextWhile) {
                     $this->start_loop();
                 }
                 $this->ignoreNextWhile = false;
                 break;
             case T_SWITCH:
             case T_TRY:
                 $this->start_cond();
                 break;
             case T_IF:
                 if (!$this->lastWasElse) {
                     $this->start_cond();
                 } else {
                     // count the number of "T_ELSE T_IF" because for each of those we get another call
                     // to end_cond()
                     $this->vars->set_elseif();
                 }
                 break;
             case T_ELSEIF:
                 $this->start_cond(true, false);
                 break;
             case T_ELSE:
                 $this->start_cond(true, true);
                 break;
         }
         $this->lastWasElse = $type == T_ELSE;
     }
     $res = parent::advance($parser);
     if ($this->lastComment && $this->lastComment != $this->lastCheckComment) {
         // it was a comment, so lets see if it contains a "@var $<name> <type>" that gives us a
         // hint what type a variable has.
         $matches = array();
         if (preg_match('/\\@var\\s+\\$([a-z0-9_]+)\\s+(\\S+)/i', $this->lastComment, $matches)) {
             // do we know that variable?
             $scopename = $this->scope->get_name();
             if ($this->vars->exists($scopename, $matches[1])) {
                 // ok, determine type and set it
                 $type = PC_Obj_MultiType::get_type_by_name($matches[2]);
                 $var = $this->vars->get($scopename, $matches[1]);
                 $var->set_type($type);
             }
         }
         $this->lastCheckComment = $this->lastComment;
     }
     return $res;
 }
Exemple #2
0
 /**
  * Finds variables that have not been read in the given scope.
  *
  * @param PC_Engine_VarContainer $vars the variables
  * @param string $scope the scope
  */
 public function analyze($vars, $scope)
 {
     if (!$this->env->get_options()->get_report_unused()) {
         return;
     }
     $accesses = $vars->get_accesses();
     if (isset($accesses[$scope])) {
         // determine the parameters to handle them special
         $params = array();
         if ($scope != PC_Obj_Variable::SCOPE_GLOBAL) {
             if (strstr($scope, '::')) {
                 list($cname, $fname) = explode('::', $scope);
                 $func = $this->env->get_types()->get_method($cname, $fname);
             } else {
                 $func = $this->env->get_types()->get_function($scope);
             }
             if ($func) {
                 // don't report anything for abstract methods
                 if ($func->is_abstract()) {
                     return;
                 }
                 $params = $func->get_params();
             }
         }
         foreach ($accesses[$scope] as $vname => $count) {
             if ($count == 0) {
                 if (isset($params[$vname])) {
                     // if it's a method and this method exists in a superclass, too, don't report the error
                     // because it happens quite often that you don't use a parameter in subclasses, but you
                     // are still forced to specify it.
                     if (strstr($scope, '::')) {
                         list($cname, $fname) = explode('::', $scope);
                         $class = $this->env->get_types()->get_class($cname);
                         if ($class) {
                             $super = $class->get_super_class();
                             if ($this->env->get_types()->get_method_of_super($super, $fname) !== null) {
                                 return;
                             }
                             foreach ($class->get_interfaces() as $if) {
                                 if ($this->env->get_types()->get_method_of_super($if, $fname)) {
                                     return;
                                 }
                             }
                         }
                     }
                     // for references, write-only is ok
                     if ($params[$vname]->is_reference()) {
                         return;
                     }
                     $name = 'parameter';
                     $error = PC_Obj_Error::E_S_PARAM_UNUSED;
                 } else {
                     $name = 'variable';
                     $error = PC_Obj_Error::E_S_VAR_UNUSED;
                 }
                 $var = $vars->get($scope, $vname);
                 $this->report($var, 'The ' . $name . ' $' . $vname . ' in #' . $scope . '# is unused', $error);
             }
         }
     }
 }