123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- <?php
- namespace Knuckles\Scribe\Extracting;
- use Exception;
- use PhpParser\Node;
- use PhpParser\NodeFinder;
- use PhpParser\ParserFactory;
- use ReflectionFunctionAbstract;
- use Throwable;
- /**
- * MethodAstParser
- * Utility class to help with retrieving (and caching) ASTs of route methods.
- */
- class MethodAstParser
- {
- protected static array $methodAsts = [];
- protected static array $classAsts = [];
- public static function getMethodAst(ReflectionFunctionAbstract $method)
- {
- $methodName = $method->name;
- $fileName = $method->getFileName();
- $methodAst = self::getCachedMethodAst($fileName, $methodName);
- if ($methodAst) {
- return $methodAst;
- }
- $classAst = self::getClassAst($fileName);
- $methodAst = self::findMethodInClassAst($classAst, $methodName);
- self::cacheMethodAst($fileName, $methodName, $methodAst);
- return $methodAst;
- }
- /**
- * @param string $sourceCode
- *
- * @return \PhpParser\Node\Stmt[]|null
- */
- protected static function parseClassSourceCode(string $sourceCode): ?array
- {
- $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
- try {
- $ast = $parser->parse($sourceCode);
- } catch (Throwable $error) {
- throw new Exception("Parse error: {$error->getMessage()}");
- }
- return $ast;
- }
- /**
- * @param \PhpParser\Node\Stmt[] $ast
- * @param string $methodName
- *
- * @return Node|null
- */
- protected static function findMethodInClassAst(array $ast, string $methodName)
- {
- $nodeFinder = new NodeFinder;
- return $nodeFinder->findFirst($ast, function(Node $node) use ($methodName) {
- // Todo handle closures
- return $node instanceof Node\Stmt\ClassMethod
- && $node->name->toString() === $methodName;
- });
- }
- protected static function getCachedMethodAst(string $fileName, string $methodName)
- {
- $key = self::getAstCacheId($fileName, $methodName);
- return self::$methodAsts[$key] ?? null;
- }
- protected static function cacheMethodAst(string $fileName, string $methodName, Node $methodAst)
- {
- $key = self::getAstCacheId($fileName, $methodName);
- self::$methodAsts[$key] = $methodAst;
- }
- private static function getAstCacheId(string $fileName, string $methodName): string
- {
- return $fileName . "///". $methodName;
- }
- private static function getClassAst(string $fileName)
- {
- $classAst = self::$classAsts[$fileName]
- ?? self::parseClassSourceCode(file_get_contents($fileName));
- return self::$classAsts[$fileName] = $classAst;
- }
- }
|