Skip to content

Commit e9c0aa1

Browse files
committed
Merge branch 'PHP-8.2'
* PHP-8.2: Add support for validation of missing method synopses (#9491)
2 parents cb4e8ff + ce05827 commit e9c0aa1

File tree

7 files changed

+72
-13
lines changed

7 files changed

+72
-13
lines changed

build/gen_stub.php

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,8 @@ class FuncInfo {
12221222
public $numRequiredArgs;
12231223
/** @var string|null */
12241224
public $cond;
1225+
/** @var bool */
1226+
public $isUndocumentable;
12251227

12261228
/**
12271229
* @param ArgInfo[] $args
@@ -1238,7 +1240,8 @@ public function __construct(
12381240
array $args,
12391241
ReturnInfo $return,
12401242
int $numRequiredArgs,
1241-
?string $cond
1243+
?string $cond,
1244+
bool $isUndocumentable
12421245
) {
12431246
$this->name = $name;
12441247
$this->classFlags = $classFlags;
@@ -1252,6 +1255,7 @@ public function __construct(
12521255
$this->return = $return;
12531256
$this->numRequiredArgs = $numRequiredArgs;
12541257
$this->cond = $cond;
1258+
$this->isUndocumentable = $isUndocumentable;
12551259
}
12561260

12571261
public function isMethod(): bool
@@ -3218,7 +3222,8 @@ function parseFunctionLike(
32183222
int $classFlags,
32193223
int $flags,
32203224
Node\FunctionLike $func,
3221-
?string $cond
3225+
?string $cond,
3226+
bool $isUndocumentable
32223227
): FuncInfo {
32233228
try {
32243229
$comment = $func->getDocComment();
@@ -3283,6 +3288,10 @@ function parseFunctionLike(
32833288
}
32843289
$paramMeta[$varName][$tag->name] = true;
32853290
break;
3291+
3292+
case 'undocumentable':
3293+
$isUndocumentable = true;
3294+
break;
32863295
}
32873296
}
32883297
}
@@ -3383,7 +3392,8 @@ function parseFunctionLike(
33833392
$args,
33843393
$return,
33853394
$numRequiredArgs,
3386-
$cond
3395+
$cond,
3396+
$isUndocumentable
33873397
);
33883398
} catch (Exception $e) {
33893399
throw new Exception($name . "(): " .$e->getMessage());
@@ -3570,6 +3580,12 @@ function parseClass(
35703580
throw new Exception("Unknown class kind " . get_class($class));
35713581
}
35723582

3583+
if ($isUndocumentable) {
3584+
foreach ($methods as $method) {
3585+
$method->isUndocumentable = true;
3586+
}
3587+
}
3588+
35733589
return new ClassInfo(
35743590
$name,
35753591
$flags,
@@ -3674,7 +3690,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
36743690
0,
36753691
0,
36763692
$stmt,
3677-
$cond
3693+
$cond,
3694+
$fileInfo->isUndocumentable
36783695
);
36793696
continue;
36803697
}
@@ -3731,7 +3748,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
37313748
$classFlags,
37323749
$classStmt->flags | $abstractFlag,
37333750
$classStmt,
3734-
$cond
3751+
$cond,
3752+
$fileInfo->isUndocumentable
37353753
);
37363754
} else if ($classStmt instanceof Stmt\EnumCase) {
37373755
$enumCaseInfos[] = new EnumCaseInfo(
@@ -4342,7 +4360,7 @@ function replaceClassSynopses(string $targetDirectory, array $classMap, iterable
43424360
foreach ($missingClassSynopses as $className => $info) {
43434361
/** @var ClassInfo $info */
43444362
if (!$info->isUndocumentable) {
4345-
echo "Warning: Missing class synopsis page for $className\n";
4363+
echo "Warning: Missing class synopsis for $className\n";
43464364
}
43474365
}
43484366
}
@@ -4388,7 +4406,8 @@ function generateMethodSynopses(array $funcMap, array $aliasMap): array {
43884406
* @param array<string, FuncInfo> $aliasMap
43894407
* @return array<string, string>
43904408
*/
4391-
function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $aliasMap): array {
4409+
function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $aliasMap, bool $isVerify): array {
4410+
$existingMethodSynopses = [];
43924411
$methodSynopses = [];
43934412

43944413
$it = new RecursiveIteratorIterator(
@@ -4407,6 +4426,27 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
44074426
continue;
44084427
}
44094428

4429+
if ($isVerify) {
4430+
$matches = [];
4431+
preg_match("/<refname>\s*([\w:]+)\s*<\/refname>\s*<refpurpose>\s*&Alias;\s*<(?:function|methodname)>\s*([\w:]+)\s*<\/(?:function|methodname)>\s*<\/refpurpose>/i", $xml, $matches);
4432+
$aliasName = $matches[1] ?? null;
4433+
$alias = $funcMap[$aliasName] ?? null;
4434+
$funcName = $matches[2] ?? null;
4435+
$func = $funcMap[$funcName] ?? null;
4436+
4437+
if ($alias &&
4438+
!$alias->isUndocumentable &&
4439+
($func === null || $func->alias === null || $func->alias->__toString() !== $aliasName) &&
4440+
($alias->alias === null || $alias->alias->__toString() !== $funcName)
4441+
) {
4442+
echo "Warning: $aliasName()" . ($alias->alias ? " is an alias of " . $alias->alias->__toString() . "(), but it" : "") . " is incorrectly documented as an alias for $funcName()\n";
4443+
}
4444+
4445+
if ($aliasName) {
4446+
$existingMethodSynopses[$aliasName] = $aliasName;
4447+
}
4448+
}
4449+
44104450
if (stripos($xml, "<methodsynopsis") === false && stripos($xml, "<constructorsynopsis") === false && stripos($xml, "<destructorsynopsis") === false) {
44114451
continue;
44124452
}
@@ -4448,7 +4488,9 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
44484488
if (!isset($funcMap[$funcName])) {
44494489
continue;
44504490
}
4491+
44514492
$funcInfo = $funcMap[$funcName];
4493+
$existingMethodSynopses[$funcInfo->name->__toString()] = $funcInfo->name->__toString();
44524494

44534495
$newMethodSynopsis = $funcInfo->getMethodSynopsisElement($funcMap, $aliasMap, $doc);
44544496
if ($newMethodSynopsis === null) {
@@ -4534,6 +4576,16 @@ function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $a
45344576
}
45354577
}
45364578

4579+
if ($isVerify) {
4580+
$missingMethodSynopses = array_diff_key($funcMap, $existingMethodSynopses);
4581+
foreach ($missingMethodSynopses as $functionName => $info) {
4582+
/** @var FuncInfo $info */
4583+
if (!$info->isUndocumentable) {
4584+
echo "Warning: Missing method synopsis for $functionName()\n";
4585+
}
4586+
}
4587+
}
4588+
45374589
return $methodSynopses;
45384590
}
45394591

@@ -4845,7 +4897,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc
48454897
}
48464898

48474899
if ($replaceMethodSynopses) {
4848-
$methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap);
4900+
$methodSynopses = replaceMethodSynopses($targetSynopses, $funcMap, $aliasMap, $verify);
48494901

48504902
foreach ($methodSynopses as $filename => $content) {
48514903
if (file_put_contents($filename, $content)) {

ext/dl_test/dl_test.stub.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
22

3-
/** @generate-class-entries */
3+
/**
4+
* @generate-class-entries
5+
* @undocumentable
6+
*/
47

58
function dl_test_test1(): void {}
69

ext/dl_test/dl_test_arginfo.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/skeleton/skeleton.stub.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
22

3-
/** @generate-class-entries */
3+
/**
4+
* @generate-class-entries
5+
* @undocumentable
6+
*/
47

58
function test1(): void {}
69

ext/skeleton/skeleton_arginfo.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/zlib/zlib.stub.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ function gzwrite($stream, string $data, ?int $length = null): int|false {}
212212
/**
213213
* @param resource $stream
214214
* @alias fwrite
215+
* @undocumentable gzputs is an alias of gzwrite, but transitive aliases are not yet supported
215216
*/
216217
function gzputs($stream, string $data, ?int $length = null): int|false {}
217218

ext/zlib/zlib_arginfo.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)