Subversion Repositories fastphp

Rev

Rev 99 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. // TODO: show full signature of each element?
  4.  
  5. error_reporting(0);
  6.  
  7. require_once __DIR__ . '/codeexplorer_api.inc.php';
  8.  
  9. define('ICON_TYPE_FUNCTION',     1);
  10. define('ICON_TYPE_CONSTRUCTOR',  2);
  11. define('ICON_TYPE_DESTRUCTOR',   3);
  12. define('ICON_TYPE_MAGICMETHOD',  4);
  13. define('ICON_TYPE_CLASS',        5);
  14. define('ICON_TYPE_TRAIT',        6);
  15. define('ICON_TYPE_INTERFACE',    7);
  16. define('ICON_TYPE_VAR',          8);
  17. define('ICON_TYPE_CONST',        9);
  18. define('ICON_TYPE_TODO',        10);
  19. define('ICON_TYPE_ERROR',       11);
  20.  
  21. class MyFastPHPIcon extends FastPHPIcon {
  22.  
  23.         public function imageIndex() {
  24.                      if (($this->getType() == ICON_TYPE_CLASS)                               && (!$this->isAbstract())) return  0; // class
  25.                 else if (($this->getType() == ICON_TYPE_CLASS)                               && ( $this->isAbstract())) return  1; // abstract class
  26.                 else if (($this->getType() == ICON_TYPE_INTERFACE)                                                    ) return  2; // interface
  27.                 else if (($this->getType() == ICON_TYPE_TRAIT)                                                        ) return  3; // trait
  28.                 else if (($this->getType() == ICON_TYPE_CONST)     && ($this->isPrivate())                            ) return  4; // private const
  29.                 else if (($this->getType() == ICON_TYPE_VAR)       && ($this->isPrivate())                            ) return  5; // private var
  30.                 else if (($this->isMethod())                       && ($this->isPrivate())   && (!$this->isAbstract())) return  6; // private function
  31.                 else if (($this->isMethod())                       && ($this->isPrivate())   && ( $this->isAbstract())) return  7; // private abstract function
  32.                 else if (($this->getType() == ICON_TYPE_CONST)     && ($this->isProtected())                          ) return  8; // protected const
  33.                 else if (($this->getType() == ICON_TYPE_VAR)       && ($this->isProtected())                          ) return  9; // protected var
  34.                 else if (($this->isMethod())                       && ($this->isProtected()) && (!$this->isAbstract())) return 10; // protected function
  35.                 else if (($this->isMethod())                       && ($this->isProtected()) && ( $this->isAbstract())) return 11; // protected abstract function
  36.                 else if (($this->getType() == ICON_TYPE_CONST)     && ($this->isPublic())                             ) return 12; // public const
  37.                 else if (($this->getType() == ICON_TYPE_VAR)       && ($this->isPublic())                             ) return 13; // public var
  38.                 else if (($this->isMethod())                       && ($this->isPublic())    && (!$this->isAbstract())) return 14; // public function
  39.                 else if (($this->isMethod())                       && ($this->isPublic())    && ( $this->isAbstract())) return 15; // public abstract function
  40.                 else if (($this->getType() == ICON_TYPE_TODO)                                                         ) return 16; // To-Do comment
  41.                 else                                                                                                    return -1;
  42.         }
  43.  
  44.         public function isMethod() {
  45.                 return (($this->getType() == ICON_TYPE_FUNCTION)    ||
  46.                         ($this->getType() == ICON_TYPE_CONSTRUCTOR) ||
  47.                         ($this->getType() == ICON_TYPE_DESTRUCTOR)  ||
  48.                         ($this->getType() == ICON_TYPE_MAGICMETHOD));
  49.         }
  50.  
  51. }
  52.  
  53. class MyFastPHPCodeExplorer {
  54.  
  55.         public function handle($code) {
  56.                 // Quick'n'Dirty fix to correctly parse the line
  57.                 // test(XYZ::class)
  58.                 $code = str_replace('::class', '', $code);
  59.  
  60.                 // Quick'n'Dirty fix to correctly parse the line
  61.                 // $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
  62.                 $code = str_replace('{$', '{', $code);
  63.  
  64.                 // Quick'n'Dirty fix to correctly parse the line
  65.                 // $handler = function(MqttClient $client, string $topic, string $message, int $qualityOfService, bool $retained) use (&$msg_count) {};
  66.                 $code = preg_replace('@function\s*\\(@is', '(', $code);
  67.  
  68.                 $token = token_get_all($code);
  69.                 $wait_function = false;
  70.                 $wait_const = false;
  71.                 $wait_class = false;
  72.                 $wait_trait = false;
  73.                 $icon = new MyFastPHPIcon();
  74.                 $wait_interface = false;
  75.                 $wait_abstract_func_list_end = false;
  76.                 $levelAry = array();
  77.                 $dep = 0;
  78.                 $insideFuncAry = array();
  79.  
  80.                 if (!$token) {
  81.                         $icon->setType(ICON_TYPE_ERROR);
  82.                         FastPHPWriter::outputLeafNode($icon, 0, 'SYNTAX ERROR');
  83.                 }
  84.  
  85.                 foreach ($token as $data) {
  86.                         if ($data == '{') $dep++;
  87.                         if ($data == '}') {
  88.                                 $dep--;
  89.                                 if ((count($levelAry) > 0) && (self::array_peek($levelAry) == $dep)) {
  90.                                         array_pop($levelAry);
  91.                                         FastPHPWriter::outputDecreaseLevel();
  92.                                 }
  93.                                 if ((count($insideFuncAry) > 0) && (self::array_peek($insideFuncAry) == $dep)) {
  94.                                         array_pop($insideFuncAry);
  95.                                 }
  96.                         }
  97.  
  98.                         $token = (!is_array($data)) ? null : $data[0];
  99.                         $value = (!is_array($data)) ? null : $data[1];
  100.                         $line  = (!is_array($data)) ? null : $data[2];
  101.  
  102.                         if ($value == '${') $dep++; // TODO: "${...}" ??? "{$...}" ???
  103.  
  104.                         if ($wait_function && ($data == '{')) {
  105.                                 $wait_function = false; // Anonymous functions do not have a name
  106.                         }
  107.  
  108.                         if ($wait_function && ($token == T_STRING)) {
  109.                                 $wait_function = false;
  110.                                 if ($icon->isAbstract()) {
  111.                                         $desc = "abstract function $value()";
  112.                                         $wait_abstract_func_list_end = true;
  113.                                 } else {
  114.                                         $desc = "function $value()";
  115.                                         $insideFuncAry[] = $dep;
  116.                                 }
  117.  
  118.                                 if ($value == '__construct') { // TODO: auch eine methode mit dem namen der klasse soll eine konstruktor sein
  119.                                         $icon->setType(ICON_TYPE_CONSTRUCTOR);
  120.                                 } else if ($value == '__destruct') {
  121.                                         $icon->setType(ICON_TYPE_DESTRUCTOR);
  122.                                 } else if (substr($value, 0, 2) == '__') {
  123.                                         $icon->setType(ICON_TYPE_MAGICMETHOD);
  124.                                 } else {
  125.                                         $icon->setType(ICON_TYPE_FUNCTION);
  126.                                 }
  127.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  128.                                 $icon->reset();
  129.                         }
  130.  
  131.                         if ($wait_class && ($token == T_STRING)) {
  132.                                 if ($icon->isAbstract()) {
  133.                                         $desc = "Abstract Class $value\n";
  134.                                 } else {
  135.                                         $desc = "Class $value\n";
  136.                                 }
  137.                                 $wait_class = false;
  138.                                 $levelAry[] = $dep;
  139.  
  140.                                 $icon->setType(ICON_TYPE_CLASS);
  141.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  142.                                 $icon->reset();
  143.  
  144.                                 FastPHPWriter::outputIncreaseLevel();
  145.                         }
  146.  
  147.                         if ($wait_trait && ($token == T_STRING)) {
  148.                                 $desc = "Trait $value\n";
  149.                                 $wait_trait = false;
  150.                                 $levelAry[] = $dep;
  151.  
  152.                                 $icon->setType(ICON_TYPE_TRAIT);
  153.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  154.                                 $icon->reset();
  155.  
  156.                                 FastPHPWriter::outputIncreaseLevel();
  157.                         }
  158.  
  159.                         if ($wait_interface && ($token == T_STRING)) {
  160.                                 $desc = "Interface $value\n";
  161.                                 $wait_interface = false;
  162.                                 $levelAry[] = $dep;
  163.  
  164.                                 $icon->setType(ICON_TYPE_INTERFACE);
  165.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  166.                                 $icon->reset();
  167.  
  168.                                 FastPHPWriter::outputIncreaseLevel();
  169.                         }
  170.  
  171.                         if ($wait_const && ($token == T_STRING)) {
  172.                                 $desc = "const $value\n";
  173.                                 $wait_const = false;
  174.  
  175.                                 $icon->setType(ICON_TYPE_CONST);
  176.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  177.                                 $icon->reset();
  178.                         }
  179.  
  180.                         if ((!$wait_abstract_func_list_end) && (count($levelAry) > 0) && (count($insideFuncAry) == 0) && ($token == T_VARIABLE)) {
  181.                                 $desc = "$value\n";
  182.  
  183.                                 $icon->setType(ICON_TYPE_VAR);
  184.                                 FastPHPWriter::outputLeafNode($icon, $line, $desc);
  185.                                 $icon->reset();
  186.                         }
  187.  
  188.                         if ($token == T_PRIVATE)   $icon->setPrivate();
  189.                         if ($token == T_PROTECTED) $icon->setProtected();
  190.                         if ($token == T_PUBLIC)    $icon->setPublic();
  191.                         if ($token == T_ABSTRACT)  $icon->setAbstract();
  192.                         if ($token == T_FINAL)     $icon->setFinal();
  193.                         if ($token == T_STATIC)    $icon->setStatic();
  194.  
  195.                         if (($data == ';') || ($data == '{') || ($data == '}')) {
  196.                                 $wait_abstract_func_list_end = false;
  197.                                 $icon->reset();
  198.                         }
  199.  
  200.                         if ($token == T_FUNCTION) {
  201.                                 $wait_function = true;
  202.                         }
  203.                         if ($token == T_CLASS) {
  204.                                 $wait_class = true;
  205.                                 $dep = 0;
  206.                         }
  207.                         if ($token == T_INTERFACE) {
  208.                                 $wait_interface = true;
  209.                                 $dep = 0;
  210.                         }
  211.                         if ($token == T_TRAIT) {
  212.                                 $wait_trait = true;
  213.                                 $dep = 0;
  214.                         }
  215.  
  216.                         if ($token == T_CONST) {
  217.                                 $wait_const = true;
  218.                         }
  219.  
  220.                         if (($token == T_COMMENT) && self::isToDoDescription($value)) {
  221.                                 $comment_lines = explode("\n", trim($value));
  222.                                 foreach ($comment_lines as $line_no => $comment_line) {
  223.                                         if (self::isToDoDescription($comment_line)) {
  224.                                                 // Because a To-Do-entry can stand everywhere (e.g. between a "private" and a "function" keyword)
  225.                                                 // we shall not alter the $icon instance
  226.                                                 $todoIcon = clone $icon;
  227.                                                 $todoIcon->setType(ICON_TYPE_TODO);
  228.                                                 FastPHPWriter::outputLeafNode($todoIcon, $line+$line_no, self::stripComment($comment_line));
  229.                                                 unset($todoIcon);
  230.                                         }
  231.                                 }
  232.                         }
  233.                 }
  234.         }
  235.  
  236.         private static function isToDoDescription($comment) {
  237.                 return ((stripos($comment, 'TODO')   !== false) ||
  238.                         (stripos($comment, 'BUGBUG') !== false) ||
  239.                         (stripos($comment, 'FIXME')  !== false) ||
  240.                         (stripos($comment, 'XXX')    !== false));
  241.         }
  242.  
  243.         private static function stripComment($x) {
  244.                 $x = trim($x);
  245.                 if (substr($x, 0, 1) == '#') return trim(substr($x, 1));
  246.                 if (substr($x, 0, 2) == '//') return trim(substr($x, 2));
  247.                 if (substr($x, 0, 2) == '/*') return trim(substr($x, 2, strlen($x)-4));
  248.                 return $x;
  249.         }
  250.  
  251.  
  252.         private static /*final*/ function array_peek($array) {
  253.                 if (!isset($array[count($array)-1])) return null;
  254.                 return $array[count($array)-1];
  255.         }
  256. }
  257.  
  258. $parser = new MyFastPHPCodeExplorer();
  259. while (true) {
  260.         try {
  261.                 $code = FastPHPReader::readCodeFromEditor();
  262.         } catch (FastPHPExitSignalReceivedException $e) {
  263.                 die();
  264.         }
  265.         FastPHPWriter::outputHeader();
  266.         $parser->handle($code);
  267.         FastPHPWriter::outputExit();
  268.         FastPHPWriter::signalOutputEnd();
  269.         sleep(1);
  270. }
  271.