vrana Fri Jun 15 15:49:32 2007 UTC
Modified files:
/phpdoc/scripts check-references.php
Log:
Local refs
Optional single extension
Unicode return types
Constructor return types
http://cvs.php.net/viewvc.cgi/phpdoc/scripts/check-references.php?r1=1.22&r2=1.23&diff_format=u
Index: phpdoc/scripts/check-references.php
diff -u phpdoc/scripts/check-references.php:1.22
phpdoc/scripts/check-references.php:1.23
--- phpdoc/scripts/check-references.php:1.22 Fri Jun 15 11:45:17 2007
+++ phpdoc/scripts/check-references.php Fri Jun 15 15:49:31 2007
@@ -29,7 +29,7 @@
if (!isset($_SERVER["argv"][1]) || !is_dir($phpdoc_dir)) {
echo "Purpose: Check parameters (types, optional, reference, count) and
return types.\n";
- echo "Usage: check-references.php language\n";
+ echo "Usage: check-references.php language [path_to_extension]\n";
echo "Notes:\n";
echo "- Compares documentation with PHP sources (Zend, extensions,
PECL, SAPI).\n";
echo "- Functions not found in sources are checked as without
references.\n";
@@ -37,51 +37,23 @@
exit();
}
+$extension = $_SERVER["argv"][2];
+
// various names for parameters passed by reference
// array() means list of parameters, number is position from which all
parameters are passed by reference
$number_refs = array(
+ "first_arg_force_ref" => array(1),
"second_arg_force_ref" => array(2),
"second_args_force_ref" => array(2),
- "second_argument_force_ref" => array(2),
- "exif_thumbnail_force_ref" => array(2, 3, 4),
- "third_and_rest_force_ref" => 3,
"third_arg_force_ref" => array(3),
- "third_args_force_ref" => array(3),
- "third_argument_force_ref" => array(3),
- "third_arg_force_by_ref_rest" => 3,
- "second_arg_force_by_ref_rest" => 2,
- "arg3to6of6_force_ref" => array(3, 4, 5, 6),
- "second_thru_fourth_args_force_ref" => array(2, 3, 4),
- "secondandthird_args_force_ref" => array(2, 3),
- "first_arg_force_ref" => array(1),
- "first_args_force_ref" => array(1),
- "first_argument_force_ref" => array(1),
- "firstandsecond_args_force_ref" => array(1, 2),
- "arg2and3_force_ref" => array(2, 3),
- "first_through_third_args_force_ref" => array(1, 2, 3),
"fourth_arg_force_ref" => array(4),
- "second_and_third_args_force_ref" => array(2, 3),
- "second_fifth_and_sixth_args_force_ref" => array(2, 5, 6),
- "first_and_second__args_force_ref" => array(1, 2),
- "third_and_fourth_args_force_ref" => array(3, 4),
- "sixth_arg_force_ref" => array(6),
- "msg_receive_args_force_ref" => array(3, 5, 8),
- "all_args_force_by_ref" => 1,
+ "fifth_arg_force_ref" => array(5),
"all_args_by_ref" => 1,
- "http_request_info_ref_3" => array(3),
- "http_request_info_ref_4" => array(4),
- "http_arg_pass_ref_3" => array(3),
- "http_arg_pass_ref_4" => array(4),
- "http_arg_pass_ref_5" => array(5),
- "secondandthird_arg_force_ref" => array(2, 3),
- "fifthandsixth_arg_force_ref" => array(5, 6),
- "seventh_arg_force_ref" => array(7),
- "eighth_arg_force_ref" => array(8),
);
$valid_types = "int|float|string|bool|resource|array|object|mixed|number";
$invalid_types = "integer|long|double|boolean|class"; // objects are written
as appropriate class name so there is no complete list of valid types
-$retval_mapping = array("TRUE" => "bool", "BOOL" => "bool", "LONG" => "int",
"DOUBLE" => "float", "STRING" => "string", "STRINGL" => "string", "ARRAY" =>
"array", "OBJECT" => "object", "RESOURCE" => "resource", "ZVAL" => "mixed"); //
FALSE and NULL omitted because they are used for errors
+$retval_mapping = array("TRUE" => "bool", "BOOL" => "bool", "LONG" => "int",
"DOUBLE" => "float", "STRING" => "string", "STRINGL" => "string", "TEXT" =>
"string", "TEXTL" => "string", "UNICODE" => "unicode", "UNICODEL" => "unicode",
"ASCII_STRING" => "unicode", "ASCII_STRINGL" => "unicode", "ARRAY" => "array",
"OBJECT" => "object", "RESOURCE" => "resource", "ZVAL" => "mixed"); // FALSE
and NULL omitted because they are used for errors
$retval_types = implode('|', array_keys($retval_mapping));
$operators = "!=|<=?|>=?|==";
$max_args = 12; // maximum number of regular function arguments
@@ -190,7 +162,7 @@
$source_types = array(); // array("function_name" => array("type_spec",
filename, lineno), ...)
$return_types = array(); // array("function_name" => array("doc_type",
filename, lineno), ...)
$source_arg_counts = array(); // array("function_name" =>
array(disallowed_count => true, ...), ...)
-foreach (array_merge(array($zend_dir), glob("$phpsrc_dir/ext/*",
GLOB_ONLYDIR), glob("$pecl_dir/*", GLOB_ONLYDIR), glob("$phpsrc_dir/sapi/*",
GLOB_ONLYDIR)) as $dirname) {
+foreach ((isset($extension) ? array($extension) :
array_merge(array($zend_dir), glob("$phpsrc_dir/ext/*", GLOB_ONLYDIR),
glob("$pecl_dir/*", GLOB_ONLYDIR), glob("$phpsrc_dir/sapi/*", GLOB_ONLYDIR)))
as $dirname) {
if (dirname($dirname) == $pecl_dir &&
!file_exists("$phpdoc_dir/reference/" . strtolower(basename($dirname)))) {
continue; // skip undocumented PECL extensions
}
@@ -198,7 +170,8 @@
$aliases = array(); // php_function => sources_function
$macros = array(); // MACRO => array(body, array(params))
$largedir = ($dirname == $zend_dir || $dirname ==
"$phpsrc_dir/ext/standard");
- foreach (array_merge((array) glob("$dirname/*.c*"), (array)
glob("$dirname/*.h")) as $filename) {
+ $local_refs = array();
+ foreach (array_merge((array) glob("$dirname/*.h"), (array)
glob("$dirname/*.c*")) as $filename) {
$file = file_get_contents($filename);
// macros
if (!$largedir) {
@@ -209,6 +182,22 @@
}
}
+
preg_match_all('~ZEND_BEGIN_ARG_INFO(?:_EX)?\\(([^,]*),\\s*([^,)]+)(.*?)ZEND_END_ARG_INFO~s',
$file, $matches, PREG_SET_ORDER);
+ foreach ($matches as $val) {
+ $function_name = trim($val[1]);
+ $local_refs[$function_name] = array();
+
preg_match_all('~ZEND_ARG(?:_PASS)?_INFO\\(\\s*([^,)]+)~', $val[3], $matches2);
+ $i = -1;
+ foreach ($matches2[1] as $i => $val2) {
+ if ($val2 && $val2 != "ZEND_SEND_BY_VAL") {
+ $local_refs[$function_name][] = $i+1;
+ }
+ }
+ if ($val[2] && $val2 != "ZEND_SEND_BY_VAL") {
+ $local_refs[$function_name] =
($local_refs[$function_name] ? min($local_refs[$function_name]) : $i+2);
+ }
+ }
+
if (substr($filename, -2) != ".h") {
$files[$filename] = $file;
@@ -226,14 +215,19 @@
}
// references
- preg_match_all("~^[
\t]*(?:ZEND|PHP)_FE\\((\\w+)\\s*,\\s*(\\w+)\\s*[,)]~m", $file, $matches,
PREG_SET_ORDER);
- preg_match_all("~^[
\t]*(?:ZEND|PHP)_FALIAS\\((\\w+)\\s*,[^,]+,\\s*(\\w+)\\s*[,)]~m", $file,
$matches2, PREG_SET_ORDER);
+ preg_match_all("~^[
\t]*(?:ZEND|PHP)_FE\\((\\w+)\\s*,\\s*(\\w+)\\s*[,)]~m", $file, $matches,
PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
+ preg_match_all("~^[
\t]*(?:ZEND|PHP)_FALIAS\\((\\w+)\\s*,[^,]+,\\s*(\\w+)\\s*[,)]~m", $file,
$matches2, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
foreach (array_merge($matches, $matches2) as $val) {
- if ($val[2] != "NULL") {
- if (empty($number_refs[$val[2]])) {
- echo "! $val[2] from $filename is not
defined.\n";
+ if ($val[2][0] != "NULL") {
+ $lineno = substr_count(substr($file, 0,
$val[0][1]), "\n") + 1;
+ if (isset($local_refs[$val[2][0]])) {
+ $source_refs[strtolower($val[1][0])] =
array($local_refs[$val[2][0]], $filename, $lineno);
+ } elseif (isset($number_refs[$val[2][0]])) {
+ $source_refs[strtolower($val[1][0])] =
array($number_refs[$val[2][0]], $filename, $lineno);
+ } else {
+ $source_refs[strtolower($val[1][0])] =
array(null, $filename, $lineno);
+ echo "! " . $val[2][0] . " from
$filename is not defined.\n";
}
- $source_refs[strtolower($val[1])] =
$number_refs[$val[2]];
}
}
@@ -245,7 +239,9 @@
$lineno = substr_count(substr($file, 0, $val[3][1]),
"\n") + 1;
// return type
- if (!in_array($function_name, $difficult_retvals)) {
+ if (preg_match('~(.+)::__construct$~', $function_name,
$match)) {
+ $return_types[$function_name] =
array($match[1], $filename, $lineno);
+ } elseif (!in_array($function_name,
$difficult_retvals)) {
preg_match_all("~\\b(?:RETURN|RETVAL|(?:return_value->type|Z_TYPE_P\\(return_value\\))\\s*=\\s*IS)_($retval_types)|(?:ZVAL_|convert_to_)((?i)$retval_types)(?:_ex)?\\(return_value~",
$function_body, $types, PREG_SET_ORDER);
if
(preg_match_all('~()(array|object)(?:_and_properties)?_init\\(return_value~',
$function_body, $matches, PREG_SET_ORDER)) {
$types = array_merge($types, $matches);
@@ -361,7 +357,8 @@
// compare with documentation
$counts = array("refs" => 0, "types" => 0, "arg_counts" => 0, "return" => 0);
-foreach (glob("$phpdoc_dir/reference/*/functions/*.xml") as $filename) {
+$reference_path = "$phpdoc_dir/reference/" . (isset($extension) ?
basename($extension) : "*");
+foreach (array_merge(glob("$reference_path/*/*.xml"),
glob("$reference_path/*/*/*.xml")) as $filename) {
if
(preg_match('~^(.*(?:(\\w+)</classname></ooclass>\\s*)?<methodsynopsis>(.*))<methodname>([^<]+)<(.*)</methodsynopsis>~sU',
file_get_contents($filename), $matches)) {
$lineno = substr_count($matches[1], "\n") + 1;
$return_type = $matches[3];
@@ -371,16 +368,17 @@
// return type
if (isset($return_types[$function_name])) {
$counts["return"]++;
- if (!preg_match("~<type>(" .
$return_types[$function_name][0] . ")</type>~", $return_type) &&
($return_types[$function_name][0] != "object" ||
preg_match("~<type>($valid_types|$invalid_types)</type>~", $return_type))) {
- echo "Wrong return type in $filename on line
$lineno.\n";
- echo ": (" . $return_types[$function_name][0] .
") in " . $return_types[$function_name][1] . " on line " .
$return_types[$function_name][2] . ".\n";
+ $modifier = (preg_match('~::__construct$~',
$function_name) ? "i" : "");
+ if (!preg_match("~<type>(" .
$return_types[$function_name][0] . ")</type>~$modifier", $return_type) &&
($return_types[$function_name][0] != "object" ||
preg_match("~<type>($valid_types|$invalid_types)</type>~", $return_type))) {
+ //~ echo "Wrong return type in $filename on
line $lineno.\n";
+ //~ echo ": (" .
$return_types[$function_name][0] . ") in " . $return_types[$function_name][1] .
" on line " . $return_types[$function_name][2] . ".\n";
}
} elseif
(preg_match("~<type>(callback|$invalid_types)</type>~", $return_type)) {
- echo "Wrong return type in $filename on line
$lineno.\n";
+ //~ echo "Wrong return type in $filename on line
$lineno.\n";
}
// references
- $source_ref = (isset($source_refs[$function_name]) ?
$source_refs[$function_name] : null);
+ $source_ref = (isset($source_refs[$function_name]) ?
$source_refs[$function_name] : array(null));
preg_match_all('~<parameter( role="reference")?>~',
$methodsynopsis, $matches);
$byref = array();
foreach ($matches[1] as $key => $val) {
@@ -389,9 +387,9 @@
}
}
if (!in_array($function_name, $wrong_refs)
- && (is_int($source_ref) ? $byref[0] != $source_ref ||
count($byref) != count($matches[1]) - $source_ref + 1 : $byref != $source_ref)
+ && (is_int($source_ref[0]) ? $byref[0] != $source_ref[0] ||
count($byref) != count($matches[1]) - $source_ref[0] + 1 : $byref !=
$source_ref[0])
) {
- echo (isset($source_ref) ? "Parameter(s) " .
(is_int($source_ref) ? "$source_ref and rest" : implode(", ", $source_ref)) :
"Nothing") . " should be passed by reference in $filename on line $lineno.\n";
+ echo (isset($source_ref[0]) ? "Parameter(s) " .
(is_int($source_ref[0]) ? "$source_ref[0] and rest" : implode(", ",
$source_ref[0])) : "Nothing") . " should be passed by reference in $filename on
line $lineno" . (isset($source_ref[1]) ? "\n: source in $source_ref[1] on line
$source_ref[2]" : "") . ".\n";
}
if (isset($source_ref)) {
$counts["refs"]++;
@@ -448,14 +446,14 @@
$count = count($matches[3]);
if (!$matches[3] || substr($matches[3][$count - 1], -3)
!= "...") {
if ($count > $max_args) {
- echo "Warning: Too much parameters in
$function_name.\n";
+ //~ echo "Warning: Too much parameters
in $function_name.\n";
} elseif ($count < $max_args) {
$disallowed += array_fill($count + 1,
$max_args - $count, true);
}
}
if ($source_arg_count[0] != $disallowed) {
- echo "Wrong arguments count in $filename on
line $lineno.\n";
- echo ": source in $source_arg_count[1] on line
$source_arg_count[2].\n";
+ //~ echo "Wrong arguments count in $filename on
line $lineno.\n";
+ //~ echo ": source in $source_arg_count[1] on
line $source_arg_count[2].\n";
}
}
}