Skip to content

Commit

Permalink
refactor: improve PhpReader
Browse files Browse the repository at this point in the history
  • Loading branch information
Chemaclass committed Jun 9, 2024
1 parent 30765a6 commit fc9472b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/DiagramElement/Package.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function getLogicalName(): string
}

/**
* @param string[] $paths Paths
* @param list<string> $paths
*/
public function addEntry(array $paths, Entry $entry): string
{
Expand Down
4 changes: 3 additions & 1 deletion src/DiagramElement/Relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public function __construct(array $entries, Options $options)
$this->options = $options;
$this->package = new Package([], 'ROOT', $options);
foreach ($entries as $e) {
$this->package->addEntry(preg_split('/[\\\\\/]/', $e->getDirectory()), $e);
/** @var list<string> $paths */
$paths = preg_split('/[\\\\\/]/', $e->getDirectory());
$this->package->addEntry($paths, $e);
}
}

Expand Down
67 changes: 32 additions & 35 deletions src/Php/PhpReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,41 @@
namespace Smeghead\PhpClassDiagram\Php;

use PhpParser\Error;
use PhpParser\ParserFactory;
use PhpParser\Node\Stmt\{
Namespace_,
ClassLike,
};
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\ParserFactory;
use RuntimeException;
use Smeghead\PhpClassDiagram\Config\Options;

final class PhpReader
{
private PhpClass $class;
private function __construct(
private PhpClass $class,
) {
}

private function __construct(PhpClass $class)
public function getInfo(): PhpClass
{
$this->class = $class;
return $this->class;
}

/**
* @return PhpReader[]
* @return list<PhpReader>
*/
public static function parseFile(string $directory, string $filename, Options $options): array
{
$code = file_get_contents($filename);

$targetVesion = ParserFactory::PREFER_PHP7;
switch ($options->phpVersion()) {
case 'php5':
$targetVesion = ParserFactory::PREFER_PHP5;
break;
case 'php7':
$targetVesion = ParserFactory::PREFER_PHP7;
break;
case 'php8':
$targetVesion = ParserFactory::PREFER_PHP7; // php-parser でまだ php8 がサポートされていない。
break;
default:
throw new \Exception("invalid php version. {$targetVesion}\n");
}
$parser = (new ParserFactory)->create($targetVesion);
$targetVersion = match ($options->phpVersion()) {
'php5' => ParserFactory::PREFER_PHP5,
'php7', 'php8' => ParserFactory::PREFER_PHP7, // php-parser でまだ php8 がサポートされていない。
default => throw new RuntimeException(sprintf("invalid php version %s\n", ParserFactory::PREFER_PHP7)),
};

$parser = (new ParserFactory)->create($targetVersion);
try {
$ast = $parser->parse($code);
$nameResolver = new NameResolver();
Expand All @@ -53,43 +48,45 @@ public static function parseFile(string $directory, string $filename, Options $o
// Resolve names
$ast = $nodeTraverser->traverse($ast);
} catch (Error $error) {
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
throw new RuntimeException(sprintf("Parse error: %s file: %s\n", $error->getMessage(), $filename));
}

$relativePath = mb_substr($filename, mb_strlen($directory) + 1);
$classes = [];
foreach (self::getClasses($relativePath, $ast) as $class) {
$classes[] = new self($class);
}

return $classes;
}

/**
* @param \PhpParser\Node[] $ast
* @return PhpClass[]|null
* @param list<Node> $ast
*
* @return list<PhpClass>
*/
private static function getClasses(string $relativePath, array $ast): ?array
private static function getClasses(string $relativePath, array $ast): array
{
if (count($ast) === 0) {
return null;
return [];
}

$classes = [];
foreach ($ast as $element) {
if ($element instanceof ClassLike) {
$classes[] = new PhpClass($relativePath, $element, $ast);
} else if ($element instanceof Namespace_) {
continue;
}

if ($element instanceof Namespace_) {
foreach ($element->stmts as $e) {
if ($e instanceof ClassLike) {
$classes[] = new PhpClass($relativePath, $e, $ast);
}
}
}
}
return $classes;
}

public function getInfo(): PhpClass
{
return $this->class;
return $classes;
}
}

0 comments on commit fc9472b

Please sign in to comment.