This parser may be used as the basis for a variety of secondary tools, including a reflection-based API generator, a code metrics analyzer, and various other possible use cases.
Inheritance: extends lithium\core\StaticObject
 public function testParamTag()
 {
     $comment = "/**\n * Lithium is cool\n * @param string \$str Some string\n */";
     $expected = array('description' => 'Lithium is cool', 'text' => '', 'tags' => array('params' => array('$str' => array('type' => 'string', 'text' => 'Some string'))));
     $result = Docblock::comment($comment);
     $this->assertEqual($expected, $result);
 }
Example #2
0
 public function testDocblockNewlineHandling()
 {
     $doc = " * This line as well as the line below it,\r\n";
     $doc .= " * are part of the description.\r\n *\r\n * This line isn't.";
     $result = Docblock::comment($doc);
     $description = "This line as well as the line below it,\nare part of the description.";
     $this->assertEqual($description, $result['description']);
     $this->assertEqual('This line isn\'t.', $result['text']);
 }
Example #3
0
 /**
  * Detailed source code identifier analysis
  *
  * Analyzes a passed $identifier for more detailed information such
  * as method/property modifiers (e.g. `public`, `private`, `abstract`)
  *
  * @param string $identifier The identifier to be analyzed
  * @param array $info Optionally restrict or expand the default information
  *        returned from the `info` method. By default, the information returned
  *        is the same as the array keys contained in the `$_methodMap` property of
  *        Inspector.
  * @return array An array of the parsed meta-data information of the given identifier.
  */
 public static function info($identifier, $info = array())
 {
     $info = $info ?: array_keys(static::$_methodMap);
     $type = static::type($identifier);
     $result = array();
     $class = null;
     if ($type == 'method' || $type == 'property') {
         list($class, $identifier) = explode('::', $identifier);
         try {
             $classInspector = new ReflectionClass($class);
         } catch (Exception $e) {
             return null;
         }
         if ($type == 'property') {
             $identifier = substr($identifier, 1);
             $accessor = 'getProperty';
         } else {
             $identifier = str_replace('()', '', $identifier);
             $accessor = 'getMethod';
         }
         try {
             $inspector = $classInspector->{$accessor}($identifier);
         } catch (Exception $e) {
             return null;
         }
         $result['modifiers'] = static::_modifiers($inspector);
     } elseif ($type == 'class') {
         $inspector = new ReflectionClass($identifier);
     } else {
         return null;
     }
     foreach ($info as $key) {
         if (!isset(static::$_methodMap[$key])) {
             continue;
         }
         if (method_exists($inspector, static::$_methodMap[$key])) {
             $setAccess = ($type == 'method' || $type == 'property') && array_intersect($result['modifiers'], array('private', 'protected')) != array() && method_exists($inspector, 'setAccessible');
             if ($setAccess) {
                 $inspector->setAccessible(true);
             }
             $result[$key] = $inspector->{static::$_methodMap[$key]}();
             if ($setAccess) {
                 $inspector->setAccessible(false);
                 $setAccess = false;
             }
         }
     }
     if ($type == 'property' && !$classInspector->isAbstract()) {
         $inspector->setAccessible(true);
         try {
             $result['value'] = $inspector->getValue(static::_class($class));
         } catch (Exception $e) {
             return null;
         }
     }
     if (isset($result['start']) && isset($result['end'])) {
         $result['length'] = $result['end'] - $result['start'];
     }
     if (isset($result['comment'])) {
         $result += Docblock::comment($result['comment']);
     }
     return $result;
 }
Example #4
0
 protected static function _codeToDoc($code)
 {
     $tokens = token_get_all($code);
     $display = array();
     $current = '';
     foreach ($tokens as $i => $token) {
         if ($i == 0 || $token[0] == T_CLOSE_TAG && $i + 1 == count($tokens)) {
             continue;
         }
         if ($token[0] == T_DOC_COMMENT) {
             if (preg_match('/@copyright/', $token[1])) {
                 continue;
             }
             if (!trim($current)) {
                 $current = '';
             }
             if ($current) {
                 $display[] = "{{{\n{$current}}}}";
                 $current = '';
             }
             $doc = Docblock::comment($token[1]);
             foreach (array('text', 'description') as $key) {
                 $doc[$key] = Code::embed($doc[$key]);
             }
             $display[] = $doc;
             continue;
         }
         $current .= is_array($token) ? $token[1] : $token;
     }
     if ($current) {
         $display[] = "{{{\n{$current}}}}";
     }
     return $display;
 }
Example #5
0
 /**
  * Get the properties for the class
  *
  * @param string $class
  * @param array $options
  * @return array
  */
 protected function _properties($class, $options = array())
 {
     $defaults = array('name' => null);
     $options += $defaults;
     $properties = Inspector::properties($class);
     $results = array();
     foreach ($properties as &$property) {
         $comment = Docblock::comment($property['docComment']);
         $description = trim($comment['description']);
         $type = isset($comment['tags']['var']) ? strtok($comment['tags']['var'], ' ') : null;
         $name = str_replace('_', '-', Inflector::underscore($property['name']));
         $usage = $type == 'boolean' ? "-{$name}" : "--{$name}=" . strtoupper($name);
         $results[$name] = compact('name', 'description', 'type', 'usage');
         if ($name == $options['name']) {
             return array($name => $results[$name]);
         }
     }
     return $results;
 }
Example #6
0
 public function _parseClass($class)
 {
     $data = array();
     // $methods = Inspector::methods($class, null, array('public' => false));
     $methods = get_class_methods($class);
     $properties = array_keys(get_class_vars($class));
     $ident = $class;
     $info = Inspector::info($ident);
     $info = Docblock::comment($info['comment']);
     $data = $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
     $this->_merge($data, array('id' => $info['text'], 'comments' => array($class)));
     foreach ($methods as $method) {
         $ident = "{$class}::{$method}()";
         $info = Inspector::info($ident);
         $info = Docblock::comment($info['comment']);
         $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
         $this->_merge($data, array('id' => $info['text'], 'comments' => array($ident)));
         if (isset($info['tags']['return'])) {
             $this->_merge($data, array('id' => $info['tags']['return'], 'comments' => array($ident)));
         }
         foreach (Set::extract($info, '/tags/params/text') as $text) {
             $this->_merge($data, array('id' => $text, 'comments' => array($ident)));
         }
     }
     foreach ($properties as $property) {
         $ident = "{$class}::\${$property}";
         $info = Inspector::info($ident);
         $info = Docblock::comment($info['comment']);
         $data = $this->_merge($data, array('id' => $info['description'], 'comments' => array($ident)));
         $data = $this->_merge($data, array('id' => $info['text'], 'comments' => array($ident)));
     }
     return $data;
 }