2013-07-04 2 views
2

Можно ли получить типы объектов через стандартный токенизатор PHP при выполнении статического анализа?PHP get_token_all object type

Я пытаюсь оценить возможность внедрения детектора шаблонов проектирования, но для достижения своей цели я должен знать фактический тип объектов, когда сообщения отправляются им (т. Е. Когда на них вызывают методы).

Заранее благодарим всех за помощь.

ответ

0

К сожалению :(При попытке написать полный пример я понял, что представляется возможным вывести типы переменных, просмотрев экземпляры объектов (т. Е. «Новые» вызовы) и отслеживая назначения переменных. Однако мне нужно будет реализовать правильный алгоритм для анализа результата token_get_all(). @sectus Позвольте мне еще раз поблагодарить вас за ваше время и терпение.

2

Да ... но это нелегко. Мой пример кода (с использованием состояний) для этого.

$file_path = 'template.php'; 

$contents = file_get_contents($file_path); 
$tokens = token_get_all($contents); 

$classes = array(); 
$namespace_state = false;   // we are not inside namespace name 
$class_or_interface_state = false; // we are not inside class name 

$current_namespace = ''; 
foreach ($tokens as $token) 
    { 
    switch (true) 
     { 
     // namespace? 
     case (is_array($token) && $token[0] == T_NAMESPACE): 
      $namespace_state = true; // we are going inside namespace name 
      break; 

     // semicolon inside namespace name? 
     case ($token === ';' && $namespace_state): 
      $namespace_state = false; // we are leaving namespace name 
      $current_namespace .= '\\'; // add it to namespace name 
      break; 

     // \(namespace separator) inside namespace name? 
     case (is_array($token) && $namespace_state && $token[0] == T_NS_SEPARATOR): 
      $current_namespace .= '\\'; // add it to namespace name 
      break; 

     // string inside namespace name? 
     case (is_array($token) && $namespace_state && $token[0] == T_STRING): 
      $current_namespace .= $token[1]; // add it to namespace name 
      break; 

     // class or interface? 
     case (is_array($token) && ($token[0] == T_CLASS || $token[0] == T_INTERFACE)): 
      $class_or_interface_state = true; // we are going inside class or interface name 
      break; 

     // string inside class or interface name? 
     case (is_array($token) && $token[0] == T_STRING && $class_or_interface_state): 
      $class_or_interface_state = false; // we are leaving class or interface name 
      $classes[strtolower($current_namespace . $token[1])] = $file_path; // we have founded full class name 
      break; 
     } 
    } 

var_dump($classes); 

P.S. этот код не тестировался с несколькими пространствами имен в одном файле.

+0

Это был бы лучший ответ, если бы вы добавили объяснение :) – Jimbo

+0

@ Jimbo, лучше? – sectus

+0

Да, больше усилий обычно = moar +1 – Jimbo

Смежные вопросы