home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 August / PCWorld_2001-08_cd.bin / Komunikace / phptriad / phptriadsetup2-11.exe / php / pear / PHPDoc / analyser / PhpdocAnalyser.php next >
PHP Script  |  2001-02-18  |  12KB  |  362 lines

  1. <?php
  2. /**
  3. * Analyses parsing data.
  4. *
  5. * Analyse means:
  6. *   - update brother/sister
  7. *   - update access/return
  8. *   - inherit elements
  9. *   - inherit information
  10. *
  11. * @version $Id: PhpdocAnalyser.php,v 1.6 2001/02/18 15:19:15 uw Exp $
  12. */
  13. class PhpdocAnalyser extends PhpdocObject {
  14.  
  15.     /**
  16.     * Flag indicating that getModule/getClass was called.
  17.     *
  18.     * @var  boolean
  19.     */
  20.     var $flag_get = false;
  21.     
  22.     /**
  23.     * List of all elements of a certain class/module.
  24.     *
  25.     * The array is used to look up see references
  26.     * 
  27.     * @var  array   Format: elementlist[ eltype ][ elname ] = true
  28.     * @see  buildElementlist()
  29.     */
  30.     var $elementlist = array();
  31.     
  32.     /**
  33.     * Adds a suffix to the number like 1st, 2nd and 3th
  34.     *
  35.     * @param    integer     $nr     number to format
  36.     * @return   string
  37.     * @author   Thomas Weinert <subjective@subjective.de>
  38.     */
  39.     function addNumberSuffix($nr) {
  40.     
  41.         $last_nr = substr($nr, -1, 1);
  42.  
  43.         switch ($last_nr) {
  44.             case 1: 
  45.                 return ($nr . "st"); 
  46.                 break;
  47.  
  48.             case 2:
  49.                 return ($nr . "nd"); 
  50.                 break;
  51.  
  52.             default: 
  53.                 return ($nr . "th");
  54.         }
  55.  
  56.     } // end func addNumberSuffix
  57.  
  58.     /**
  59.     * Starts the analysing of the raw parsing data.
  60.     *
  61.     * @access   public
  62.     * @abstract
  63.     */
  64.     function analyse() {
  65.         ;
  66.     } // end func analyse
  67.  
  68.     /**
  69.     * Handles brother and sister.
  70.     *
  71.     * @abstract
  72.     * @see      updateBrotherSisterElements()
  73.     */
  74.     function updateBrothersSisters() {
  75.         ;
  76.     } // end func updateBrothersSisters
  77.  
  78.     /**
  79.     * Updates certain elements that use brother and sister.
  80.     *
  81.     * @return   boolean $ok
  82.     */
  83.     function updateBrotherSisterElements() {
  84.         return false;
  85.     } // end func updateBrotherSisterElements
  86.     
  87.     /**
  88.     * Copies fields from a brother or sister to the current element.
  89.     * 
  90.     * @param    array   Data of the target element that has a brother/sister tag
  91.     * @param    array   Data of the element that is referenced by brother/sister
  92.     */
  93.     function copyBrotherSisterFields($target, $from) {
  94.         
  95.         reset($from);
  96.         while (list($k, $v) = each($from)) 
  97.             if (!isset($target[$k]) || "" == $target[$k]) 
  98.                 $target[$k] = $v;
  99.                 
  100.         return $target;
  101.     } // end func copyBrotherSisterFields
  102.  
  103.     /**
  104.     * Updates the access and return tag values.
  105.     *
  106.     * @see      updateAccessReturnElements(), updateAccessElements()
  107.     * @abstract
  108.     */
  109.     function updateAccessReturn() {
  110.         ;
  111.     } // end func updateAccessReturn
  112.  
  113.     /**
  114.     * Updates access and return for certain elements.
  115.     *
  116.     * This function should only be used to update functions.
  117.     * Functions that have the same name as the class (constructors)
  118.     * get return void and access public. Functions without
  119.     * access get access public and functions without return get return void.
  120.     *
  121.     * @return   boolean    $ok
  122.     * @see      updateAccessReturn()
  123.     * @abstract
  124.     */
  125.     function updateAccessReturnElements() {
  126.         ;
  127.     } // end func updateAccessReturnElements
  128.  
  129.     /**
  130.     * Updates access tags.
  131.     *
  132.     * @see      updateAccessReturnElements()
  133.     * @abstract
  134.     */
  135.     function updateAccessElements() {
  136.         ;
  137.     } // end func updateAccessElements
  138.  
  139.     /**
  140.     * Compares the param tags with the function head found.
  141.     *
  142.     * @abstract
  143.     */
  144.     function checkFunctionArgs() {
  145.         ;
  146.     } // end func checkFunctionArgs
  147.  
  148.     /**
  149.     * Looks for undocumented elements and adds a warning if neccessary.
  150.     *
  151.     * @abstract
  152.     */
  153.     function findUndocumented() {
  154.         ;
  155.     } // end func findUndocumented
  156.     
  157.     /**
  158.     * Checks all see references in the given classes/modulegroup.
  159.     * 
  160.     * @abstract
  161.     */
  162.     function checkSee() {
  163.         ;                
  164.     } // end func checkSee
  165.     
  166.     /**
  167.     * Checks see references in the given elementlist.
  168.     * 
  169.     * @abstract
  170.     */
  171.     function checkSeeElement() {
  172.         ;
  173.     } // end func checkSeeElement
  174.     
  175.     /**
  176.     * Build a list of all elemente (functions, variables,...) of a certain class/module
  177.     * 
  178.     * @abstract
  179.     * @see            $elementlist
  180.     */
  181.     function buildElementlist() {
  182.         ; 
  183.     } // end func buildElementlist
  184.  
  185.     /**
  186.     * Compares the argument list generated from the function head with the param tags found.
  187.     *
  188.     * PHPDoc is able to recognize these documentation mistakes:
  189.     * - too few or too many param tags
  190.     * - name does not match or is missing
  191.     * - type does not match or is missing
  192.     * - trouble with inherited elements
  193.     *
  194.     * @param    array   Function arguments found by the parser
  195.     * @param    array   Paramarray
  196.     * @param    string  Functionname
  197.     * @param    string  Filename
  198.     * @param    boolean Param tags inherited?
  199.     * @return   array   $params    Param array
  200.     */
  201.     function checkArgDocs($args, $params, $elname, $elfile, $inherited = false) {
  202.     
  203.         // "param" contains the information from the @param tags.
  204.         $num_args   = count($args);
  205.         $num_params = count($params);
  206.  
  207.         // no args? return...
  208.         if (0 == $num_args && 0 == $num_params)
  209.             return array();
  210.  
  211.         // no args but @param used
  212.         if (0 == $num_args && $num_params > 0) {
  213.         
  214.             if (!$inherited) {
  215.             
  216.                 $msg = "Function head shows no parameters, remove all @param tags.";
  217.                 $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  218.  
  219.             } else {
  220.  
  221.                 if ("void" != $params[0]["type"]) {
  222.     
  223.                     $msg = "The function inherited some parameter documentation from it's parentclass but PHPDoc could not find
  224.                                     arguments in the function head. Add @param void to the doc comment to avoid confusion.";
  225.                     $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  226.                 
  227.                 }
  228.             
  229.             }
  230.  
  231.             return array();
  232.             
  233.         }
  234.  
  235.         // compare the informations from the parser with the @param tags
  236.         reset($args);
  237.         while (list($k, $arg) = each($args)) {
  238.  
  239.             if (isset($params[$k])) {
  240.  
  241.                 if ($arg["optional"])
  242.                     $params[$k]["default"] = $arg["default"];
  243.  
  244.                 if (!$inherited) {
  245.  
  246.                     if ("" != $arg["type"] && "" != $params[$k]["type"] && "mixed" != $params[$k]["type"] && strtolower($arg["type"]) != strtolower($params[$k]["type"])) {
  247.  
  248.                         $type = $arg["type"];
  249.                         $msg = sprintf("%s parameter type '%s' does match the the documented type '%s', possible error consider an update to '@param %s %s %s' or '@param %s %s', the variable name is optional.",
  250.                                         $this->addNumberSuffix($k + 1),
  251.                                         $arg["name"],
  252.                                         $params[$k]["type"],
  253.                                         $type,
  254.                                         $arg["name"],
  255.                                         (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)",
  256.                                         $type,
  257.                                         (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)"
  258.                                 );
  259.  
  260.                         $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  261.  
  262.                     } else if ("" != $params[$k]["type"]) {
  263.  
  264.                         $type = $params[$k]["type"];
  265.  
  266.                     } else {
  267.  
  268.                         $msg = sprintf('Type missing for the %s parameter, "mixed" assumed.', $this->addNumberSuffix($k));
  269.                         $this->warn->addDocWarning($elfile, "function", $elname, $msg, "missing");
  270.                         $type = "mixed";
  271.  
  272.                     }
  273.  
  274.                     $params[$k]["type"] = $type;
  275.  
  276.                 } else {
  277.  
  278.                     if ("" != $params[$k]["type"] && strtolower($arg["type"]) != strtolower($params[$k]["type"])) {
  279.  
  280.                         $type = (""!=$args["type"]) ? $arg["type"] : $params[$k]["type"];
  281.                         $msg = sprintf("Possible documentation error due to inherited information.
  282.                                         The type of the %s parameter '%s' does not match the documented type '%s'.
  283.                                         Override the inherited documentation if neccessary.",
  284.                                             $this->addNumberSuffix($k),
  285.                                             $arg["type"],
  286.                                             $params[$k]["type"]
  287.                                     );
  288.                         $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  289.                 
  290.                     } else if ("" != $params[$k]["type"]) {
  291.         
  292.                         $type = $params[$k]["type"];
  293.             
  294.                     } else {
  295.             
  296.                         $type = "mixed";
  297.                         $msg = sprintf('Type missing for the %d parameter, "mixed" assumed. Override the inherited documentation if neccessary.', $k);
  298.                         $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  299.  
  300.                     }
  301.  
  302.                     $params[$k]["type"] = $type;
  303.                 
  304.                 }
  305.  
  306.                 if ("" != $params[$k]["name"] && $arg["name"] != $params[$k]["name"]) {
  307.  
  308.                     $msg = sprintf("%s parameter '%s' does not match the documented name '%s', update the tag to '@param %s %s %s' or '@param %s %s', the variable name is optional.",
  309.                                     $this->addNumberSuffix($k+1),
  310.                                     $arg["name"],
  311.                                     $params[$k]["name"],
  312.                                     $type,
  313.                                     $arg["name"],
  314.                                     (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)",
  315.                                     $type,
  316.                                     (isset($params[$k]["desc"])) ? $params[$k]["desc"] : "(description)"
  317.                                 );
  318.  
  319.                     $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  320.                     $params[$k]["name"] = $arg["name"];
  321.  
  322.                 } else if ("" == $params[$k]["name"]) {
  323.  
  324.                     $params[$k]["name"] = $arg["name"];
  325.  
  326.                 }
  327.  
  328.             } else {
  329.  
  330.                 $msg = sprintf("%s parameter '%s' is not documented add '@param %s [description]' to the end of the @param[eter] list.",
  331.                                 $this->addNumberSuffix($k+1),
  332.                                 $arg["name"],
  333.                                 ("" == $arg["type"]) ? "(object objectname|type)" : $arg["type"]
  334.                             );
  335.  
  336.                 $params[$k]["name"]        = $arg["name"];
  337.                 $params[$k]["undoc"]    = true;
  338.  
  339.                 if ("" != $arg["type"])
  340.                     $params[$k]["type"] = $arg["type"];
  341.  
  342.                 $this->warn->addDocWarning($elfile, "function", $elname, $msg, "missing");
  343.             }
  344.  
  345.         }
  346.  
  347.         // more @params specified than variables where found in the function head, delete them
  348.         if ($num_params > $num_args) {
  349.  
  350.             $msg = "The parser found '$num_args' parameter but '$num_params' @param[eter] tags. You should update the @param[eter] list.";
  351.             $this->warn->addDocWarning($elfile, "function", $elname, $msg, "mismatch");
  352.             for ($i = $k + 1;  $i < $num_params; ++$i)
  353.                 unset($params[$i]);
  354.  
  355.         }
  356.  
  357.         return $params;
  358.     } // end func checkArgDocs
  359.  
  360. } // end func PhpdocAnalyser
  361. ?>
  362.