Пример #1
0
 /**
  * @param XRef_ParsedFile $pf
  * @param bool $is_library_file
  * @return * any data
  */
 public function createFileSlice(XRef_IParsedFile $pf, $is_library_file = false)
 {
     /** array of arrays with info about called functions and methods */
     $called_functions = array();
     /** map: (function call info => true), to report any call once only */
     $uniqs = array();
     /** map of function names, checked for existence by function_exists() */
     $checked_for_functions = array();
     $tokens = $pf->getTokens();
     for ($i = 0; $i < count($tokens); ++$i) {
         $t = $tokens[$i];
         // $this->foo();
         // Foo\Barr::foo();
         if ($t->text == '(') {
             $p = $t->prevNS();
             if ($p->kind != T_STRING) {
                 continue;
             }
             // array with parts of the name (T_NS_SEPARATOR && T_STRING)
             $function_name_parts = array($p->text);
             $class_name = '';
             $pp = $p->prevNS();
             if ($pp->kind == T_NS_SEPARATOR) {
                 // Foo\bar();
                 // \bar();
                 while ($pp->kind == T_NS_SEPARATOR || $pp->kind == T_STRING) {
                     array_unshift($function_name_parts, $pp->text);
                     $pp = $pp->prevNS();
                 }
             } elseif ($pp->kind == T_OBJECT_OPERATOR) {
                 // $var->bar()
                 // $this->bar();
                 $pp = $pp->prevNS();
                 if ($pp->kind == T_VARIABLE && $pp->text == '$this') {
                     $class_name = 'self';
                     // will be resolved later
                 } else {
                     // TODO
                     continue;
                 }
             } elseif ($pp->kind == T_DOUBLE_COLON) {
                 // Foo::bar();
                 // Foo\Bar::bar();
                 // self::foo();
                 // static::bar();
                 $pp = $pp->prevNS();
                 while ($pp->kind == T_NS_SEPARATOR || $pp->kind == T_STRING || $pp->kind == T_STATIC) {
                     $class_name = $pp->text . $class_name;
                     $pp = $pp->prevNS();
                 }
             }
             if ($pp->text == '&') {
                 $pp = $pp->prevNS();
             }
             if ($pp->kind == T_FUNCTION) {
                 // skip function declarations
                 continue;
             }
             $arguments = $pf->extractList($t->nextNS());
             $num_of_arguments = count($arguments);
             $from_class = $pf->getClassAt($t->index);
             $from_class_name = $from_class ? $from_class->name : '';
             if ($pp->kind == T_NEW) {
                 // new Something();
                 // new ns\Another\Something();
                 // new \Foo();
                 $class_name = implode('', $function_name_parts);
                 if ($class_name == 'static' || $class_name == 'self') {
                     $class_name = $from_class_name;
                 } elseif ($class_name == 'parent') {
                     $class_name = $from_class && $from_class->extends ? $from_class->extends[0] : null;
                 } else {
                     $class_name = $pf->qualifyName($class_name, $t->index);
                 }
                 if ($class_name) {
                     $uniq = "new##{$class_name}#{$num_of_arguments}";
                     if (!isset($uniqs[$uniq])) {
                         $uniqs[$uniq] = true;
                         $called_functions[] = array(self::F_CLASS_CONSTRUCTOR, null, $class_name, $t->lineNumber, $num_of_arguments);
                     }
                 }
             } elseif ($class_name) {
                 // method call:
                 //  $this->foo();
                 //  self::foo();
                 //  Foo::bar();
                 //  \bar\Baz::foo();
                 if ($class_name == 'static' || $class_name == 'self') {
                     $class_name = $from_class_name;
                 } elseif ($class_name == 'parent') {
                     $class_name = $from_class && $from_class->extends ? $from_class->extends[0] : null;
                 } else {
                     $class_name = $pf->qualifyName($class_name, $t->index);
                 }
                 if ($class_name) {
                     if (count($function_name_parts) > 1) {
                         throw new Exception("{$class_name}::" . implode('', $function_name_parts));
                     }
                     $function_name = $function_name_parts[0];
                     if ($function_name == '__construct') {
                         $uniq = "new##{$class_name}#{$num_of_arguments}";
                         if (!isset($uniqs[$uniq])) {
                             $uniqs[$uniq] = true;
                             $called_functions[] = array(self::F_CLASS_CONSTRUCTOR, null, $class_name, $t->lineNumber, $num_of_arguments);
                         }
                     } else {
                         $uniq = "{$function_name}##{$class_name}#{$num_of_arguments}";
                         if (!isset($uniqs[$uniq])) {
                             $uniqs[$uniq] = true;
                             $called_functions[] = array(self::F_CLASS_METHOD, $function_name, $class_name, $t->lineNumber, $num_of_arguments);
                         }
                     }
                 }
             } else {
                 // function call: qualified or unqualified
                 // foo();
                 // foo\bar();
                 // \foo\bar\baz();
                 if (count($function_name_parts) > 1) {
                     $function_name = $pf->qualifyName(implode('', $function_name_parts), $t->index);
                     $uniq = "{$function_name}##{$num_of_arguments}";
                     if (!isset($uniqs[$uniq])) {
                         $uniqs[$uniq] = true;
                         $called_functions[] = array(self::F_FULLY_QUALIFIED_FUNC, $function_name, null, $t->lineNumber, $num_of_arguments);
                     }
                 } else {
                     $function_name = $function_name_parts[0];
                     $namespace = $pf->getNamespaceAt($t->index);
                     $namespace_name = $namespace ? $namespace->name : '';
                     $uniq = "{$function_name}##{$namespace_name}#{$num_of_arguments}";
                     if (!isset($uniqs[$uniq])) {
                         $uniqs[$uniq] = true;
                         $called_functions[] = array(self::F_NOT_QUALIFIED_FUNC, $function_name, $namespace_name, $t->lineNumber, $num_of_arguments, $from_class_name);
                     }
                 }
                 if ($function_name == 'function_exists') {
                     $n = $t->nextNS();
                     if ($n->kind == T_CONSTANT_ENCAPSED_STRING) {
                         $checked_for_function_name = trim($n->text, '\'"');
                         $checked_for_functions[$checked_for_function_name] = true;
                     }
                 }
             }
         }
     }
     $file_slice = array("called" => $called_functions, "checked" => $checked_for_functions);
     return $file_slice;
 }