Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

PHP_DocBlockGeneratorでinterfaceを扱う


see PHP_DocBlockGenerator使える! - Do You PHP はてな
いつの間にか1.0.2がリリースされているPHP_DocBlockGeneratorですが、1.0.2でfinalクラスやstatic privateなどの対応もされたようです。しかし、interfaceに対しては、まだ対応していないようです。たとえば、

<?php
interface Services_Hatena_Star_Entry {
    public function canComment();
    public function getStars();
    public function getUri();
    public function getRaw();
}

という内容のPHPファイルに対して

$ docblockgen \
--author="Hideyuki Shimooka" \
--category="Services" \
--email=shimooka@doyouphp.jp \
--infile=Entry.php \
--outfile=Entry.commented.php \
--license=php301 \
--package="Services_Hatena_Star" \
--version=0.0.1 --year=2007

と実行すると

<?php

/**
 * Short description for file
 * 

 * @see       References to other sections (if any)...
 */
interface Services_Hatena_Star_Entry {
    public

/**
 * Short description for function
 * 
 * Long description (if any) ...
 * 
 * @return void 
 */
 function canComment();
    public

と、正しくコメントされません(publicの位置がズレる)。
ということで、3分間ハッキング(^^; [PEARインストール先]/PHP/DocBlockGenerator/Tokens.phpをちょっと変えるだけでinterface対応できます。

$ diff -u PHP/DocBlockGenerator/Tokens.php.org PHP/DocBlockGenerator/Tokens.php
--- PHP/DocBlockGenerator/Tokens.php.org        2007-07-22 15:52:50.000000000 +0900
+++ PHP/DocBlockGenerator/Tokens.php    2007-07-22 15:52:57.000000000 +0900
@@ -269,6 +269,7 @@
                         break;

                     case T_CLASS: // class classes and objects
+                    case T_INTERFACE: // interfaces and objects
                         $this->inClass = 0;
                         $this->block->setClass($id);
                         break;
$ 

要は、interfaceもclassと同様に扱うようにするだけです(^^;が、

<?php

/**
 * Short description for file

 * @see       References to other sections (if any)...
 */

/**
 * Short description for class
 * 
 * Long description (if any) ...
 * 
 * @category  Services 
 * @package   Services_Hatena_Star 
 * @author    Hideyuki Shimooka <shimooka@doyouphp.jp>
 * @copyright 2007 Hideyuki Shimooka
 * @license   http://www.php.net/license/3_01.txt The PHP License, version 3.01
 * @version   0.0.1 
 * @link      http://pear.php.net/package/Services_Hatena_Star 
 * @see       References to other sections (if any)...
 */
interface Services_Hatena_Star_Entry {

    /**
     * Short description for function
     * 
     * Long description (if any) ...
     * 
     * @return void   
     * @access public 
     */
    public function canComment();
           :

という具合にinterface定義に対するdocblockも作成されます。ただ、このdocblockもclass用なので、微妙といえば微妙。。。
ということで、Block.phpにinterface用のコードを追加(setClassメソッドをほとんどコピー)して

--- PHP/DocBlockGenerator/Tokens.php.org	2007-07-22 16:21:47.000000000 +0900
+++ PHP/DocBlockGenerator/Tokens.php	2007-07-22 16:13:44.000000000 +0900
@@ -273,6 +273,11 @@
                         $this->block->setClass($id);
                         break;
 
+                    case T_INTERFACE: // interfaces
+                        $this->inClass = 0;
+                        $this->block->setInterface($id);
+                        break;
+
                     case T_CONST: // const
                         // sets the const DocBlock
                         is_null($this->inClass) or $this->block->setConst($id);
--- PHP/DocBlockGenerator/Block.php.org	2007-07-22 16:21:39.000000000 +0900
+++ PHP/DocBlockGenerator/Block.php	2007-07-22 16:18:53.000000000 +0900
@@ -346,6 +346,45 @@
     }
 
     /**
+     * Sets the class DocBlock
+     *
+     * Extracts the class token. Sets the default package name on the
+     * first 2 words of the class. Builds the class DocBlock. Resets the
+     * class variables types cache.
+     *
+     * @param  integer $id the class token identification number
+     * @return void
+     * @access public
+     */
+    public function setInterface($id)
+    {
+        // extracts the interface declaration tokens
+        $tokens = $this->tokens->slice($id, T_INTERFACE, '{');
+
+        if (count($tokens) >= 3) {
+            // a interface is found, extracts the interface tokens
+            $this->interfaceTokens = $this->tokens->slice($id, '{', '}');
+            // if the package name is set to its defaults
+            // extracts the interface name first 2 words, assumed to be the package name
+            // sets the package name to the first 2 words of the interface name
+            $this->packageName == self::packageName and
+            $interfaceName = next($tokens) and
+            $interfaceName = $interfaceName['value'] and
+            $words = explode('_', $interfaceName)and
+            $words = array_slice($words, 0, 2) and
+            $this->packageName = implode('_', $words) or
+            $this->packageName = self::packageName;
+            // adds the default description and the tags to the DocBlock
+            $block = array($this->description['short'], '', $this->description['long']);
+            $block = array_merge($block, $this->setPageTags());
+            $this->build($id, $block, false, 'interface');
+            // resets the variables types cache
+            $this->type->resetCache('var');
+        }
+        // else: ignore, not a syntax compliant interface declaration
+    }
+
+    /**
      * Sets the class constant DocBlock
      *
      * Extracts the constant value. Determines its type.

な感じに変更すると、

<?php

/**
 * Short description for file
 * 

 * @see       References to other sections (if any)...
 */

/**
 * Short description for interface
 * 
 * Long description (if any) ...
 * 
 * @category  Services 
 * @package   Services_Hatena_Star 
 * @author    Hideyuki Shimooka <shimooka@doyouphp.jp>
 * @copyright 2007 Hideyuki Shimooka
 * @license   http://www.php.net/license/3_01.txt The PHP License, version 3.01
 * @version   0.0.1 
 * @link      http://pear.php.net/package/Services_Hatena_Star 
 * @see       References to other sections (if any)...
 */
interface Services_Hatena_Star_Entry {

    /**
     * Short description for function

結構良い感じになります :-)