$members */ function generateMethodAnnotations(string $namespaceName, array $members) : string{ $selfName = basename(__FILE__); $lines = ["/**"]; $lines[] = " * This doc-block is generated automatically, do not modify it manually."; $lines[] = " * This must be regenerated whenever registry members are added, removed or changed."; $lines[] = " * @see build/$selfName"; $lines[] = " * @generate-registry-docblock"; $lines[] = " *"; static $lineTmpl = " * @method static %2\$s %s()"; $memberLines = []; foreach(Utils::stringifyKeys($members) as $name => $member){ $reflect = new \ReflectionClass($member); while($reflect !== false && $reflect->isAnonymous()){ $reflect = $reflect->getParentClass(); } if($reflect === false){ $typehint = "object"; }elseif($reflect->getNamespaceName() === $namespaceName){ $typehint = $reflect->getShortName(); }else{ $typehint = '\\' . $reflect->getName(); } $accessor = mb_strtoupper($name); $memberLines[$accessor] = sprintf($lineTmpl, $accessor, $typehint); } ksort($memberLines, SORT_STRING); foreach($memberLines as $line){ $lines[] = $line; } $lines[] = " */"; return implode("\n", $lines); } function processFile(string $file) : void{ $contents = file_get_contents($file); if($contents === false){ throw new \RuntimeException("Failed to get contents of $file"); } if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){ return; } $shortClassName = basename($file, ".php"); $className = $matches[1] . "\\" . $shortClassName; if(!class_exists($className)){ return; } $reflect = new \ReflectionClass($className); $docComment = $reflect->getDocComment(); if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){ return; } echo "Found registry in $file\n"; $replacement = generateMethodAnnotations($matches[1], $className::getAll()); $newContents = str_replace($docComment, $replacement, $contents); if($newContents !== $contents){ echo "Writing changed file $file\n"; file_put_contents($file, $newContents); }else{ echo "No changes made to file $file\n"; } } require dirname(__DIR__) . '/vendor/autoload.php'; if(is_dir($argv[1])){ /** @var string $file */ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){ if(!str_ends_with($file, ".php")){ continue; } processFile($file); } }else{ processFile($argv[1]); }