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