Add support for validation of missing method synopses (#9491)

This commit is contained in:
Máté Kocsis 2022-09-07 17:40:36 +02:00 committed by GitHub
parent 05aa3b3e0a
commit ce058273ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 13 deletions

View file

@ -1222,6 +1222,8 @@ class FuncInfo {
public $numRequiredArgs;
/** @var string|null */
public $cond;
/** @var bool */
public $isUndocumentable;
/**
* @param ArgInfo[] $args
@ -1238,7 +1240,8 @@ class FuncInfo {
array $args,
ReturnInfo $return,
int $numRequiredArgs,
?string $cond
?string $cond,
bool $isUndocumentable
) {
$this->name = $name;
$this->classFlags = $classFlags;
@ -1252,6 +1255,7 @@ class FuncInfo {
$this->return = $return;
$this->numRequiredArgs = $numRequiredArgs;
$this->cond = $cond;
$this->isUndocumentable = $isUndocumentable;
}
public function isMethod(): bool
@ -3218,7 +3222,8 @@ function parseFunctionLike(
int $classFlags,
int $flags,
Node\FunctionLike $func,
?string $cond
?string $cond,
bool $isUndocumentable
): FuncInfo {
try {
$comment = $func->getDocComment();
@ -3283,6 +3288,10 @@ function parseFunctionLike(
}
$paramMeta[$varName][$tag->name] = true;
break;
case 'undocumentable':
$isUndocumentable = true;
break;
}
}
}
@ -3383,7 +3392,8 @@ function parseFunctionLike(
$args,
$return,
$numRequiredArgs,
$cond
$cond,
$isUndocumentable
);
} catch (Exception $e) {
throw new Exception($name . "(): " .$e->getMessage());
@ -3570,6 +3580,12 @@ function parseClass(
throw new Exception("Unknown class kind " . get_class($class));
}
if ($isUndocumentable) {
foreach ($methods as $method) {
$method->isUndocumentable = true;
}
}
return new ClassInfo(
$name,
$flags,
@ -3674,7 +3690,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
0,
0,
$stmt,
$cond
$cond,
$fileInfo->isUndocumentable
);
continue;
}
@ -3731,7 +3748,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
$classFlags,
$classStmt->flags | $abstractFlag,
$classStmt,
$cond
$cond,
$fileInfo->isUndocumentable
);
} else if ($classStmt instanceof Stmt\EnumCase) {
$enumCaseInfos[] = new EnumCaseInfo(
@ -4342,7 +4360,7 @@ function replaceClassSynopses(string $targetDirectory, array $classMap, iterable
foreach ($missingClassSynopses as $className => $info) {
/** @var ClassInfo $info */
if (!$info->isUndocumentable) {
echo "Warning: Missing class synopsis page for $className\n";
echo "Warning: Missing class synopsis for $className\n";
}
}
}
@ -4388,7 +4406,8 @@ function generateMethodSynopses(array $funcMap, array $aliasMap): array {
* @param array<string, FuncInfo> $aliasMap
* @return array<string, string>
*/
function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $aliasMap): array {
function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $aliasMap, bool $isVerify): array {
$existingMethodSynopses = [];
$methodSynopses = [];
$it = new RecursiveIteratorIterator(
@ -4407,6 +4426,27 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
continue;
}
if ($isVerify) {
$matches = [];
preg_match("/<refname>\s*([\w:]+)\s*<\/refname>\s*<refpurpose>\s*&Alias;\s*<(?:function|methodname)>\s*([\w:]+)\s*<\/(?:function|methodname)>\s*<\/refpurpose>/i", $xml, $matches);
$aliasName = $matches[1] ?? null;
$alias = $funcMap[$aliasName] ?? null;
$funcName = $matches[2] ?? null;
$func = $funcMap[$funcName] ?? null;
if ($alias &&
!$alias->isUndocumentable &&
($func === null || $func->alias === null || $func->alias->__toString() !== $aliasName) &&
($alias->alias === null || $alias->alias->__toString() !== $funcName)
) {
echo "Warning: $aliasName()" . ($alias->alias ? " is an alias of " . $alias->alias->__toString() . "(), but it" : "") . " is incorrectly documented as an alias for $funcName()\n";
}
if ($aliasName) {
$existingMethodSynopses[$aliasName] = $aliasName;
}
}
if (stripos($xml, "<methodsynopsis") === false && stripos($xml, "<constructorsynopsis") === false && stripos($xml, "<destructorsynopsis") === false) {
continue;
}
@ -4448,7 +4488,9 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
if (!isset($funcMap[$funcName])) {
continue;
}
$funcInfo = $funcMap[$funcName];
$existingMethodSynopses[$funcInfo->name->__toString()] = $funcInfo->name->__toString();
$newMethodSynopsis = $funcInfo->getMethodSynopsisElement($funcMap, $aliasMap, $doc);
if ($newMethodSynopsis === null) {
@ -4534,6 +4576,16 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
}
}
if ($isVerify) {
$missingMethodSynopses = array_diff_key($funcMap, $existingMethodSynopses);
foreach ($missingMethodSynopses as $functionName => $info) {
/** @var FuncInfo $info */
if (!$info->isUndocumentable) {
echo "Warning: Missing method synopsis for $functionName()\n";
}
}
}
return $methodSynopses;
}
@ -4845,7 +4897,7 @@ if ($generateMethodSynopses) {
}
if ($replaceMethodSynopses) {
$methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap);
$methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap, $verify);
foreach ($methodSynopses as $filename => $content) {
if (file_put_contents($filename, $content)) {

View file

@ -1,6 +1,9 @@
<?php
/** @generate-class-entries */
/**
* @generate-class-entries
* @undocumentable
*/
function dl_test_test1(): void {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 39ccf8141b0eb785cafd490b420f2e99d6a7a66d */
* Stub hash: 547ddbc21e9aa853b491cb17e902bbbb9cc2df00 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()

View file

@ -1,6 +1,9 @@
<?php
/** @generate-class-entries */
/**
* @generate-class-entries
* @undocumentable
*/
function test1(): void {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: efdd79c2c8ccff694699c86fdd6248a13839c744 */
* Stub hash: 54b0ffc3af871b189435266df516f7575c1b9675 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_test1, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()

View file

@ -212,6 +212,7 @@ function gzwrite($stream, string $data, ?int $length = null): int|false {}
/**
* @param resource $stream
* @alias fwrite
* @undocumentable gzputs is an alias of gzwrite, but transitive aliases are not yet supported
*/
function gzputs($stream, string $data, ?int $length = null): int|false {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 338e64b821dc3f27b6d1d262a90cb7c144ed78b6 */
* Stub hash: 3660ad3239f93c84b6909c36ddfcc92dd0773c70 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ob_gzhandler, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)