Skip to content

Commit

Permalink
Merge pull request #14 from hirokinoue/reduce-inefficient-code
Browse files Browse the repository at this point in the history
冗長なコードを削減する
  • Loading branch information
hirokinoue committed Mar 5, 2024
2 parents fa12e3a + 5a846e7 commit d0ac0f7
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 91 deletions.
3 changes: 1 addition & 2 deletions src/DependencyVisualizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ private function newDiagramUnit(): DiagramUnit
{
$classLike = ClassLikeNodeFinder::find($this->stmts);
$rootClassName = $this->rootClassName($classLike);
$ancestors = ($classLike === null) ? [] : [$rootClassName];
return new DiagramUnit($rootClassName, $ancestors, true, $classLike, 0);
return new DiagramUnit($rootClassName, true, $classLike, 0);
}

private function rootClassName(?ClassLikeWrapper $classLike): string
Expand Down
27 changes: 7 additions & 20 deletions src/DiagramUnit.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,20 @@ final class DiagramUnit
* @var DiagramUnit[] $classesDirectlyDependsOn
*/
private array $classesDirectlyDependsOn = [];
/**
* @var string[] $ancestors Array of fully qualified class name.
*/
private array $ancestors;
private bool $isCirculating = false;
/** @var array<int, string> */
private static array $visitedClasses = [];
private bool $isRoot;
// NOTE: nullになるのはDiagramUnitが定義済みクラスの場合とルートのDiagramUnitがクラスじゃない場合
private ?ClassLikeWrapper $classLikeWrapper;
private int $layer;

/**
* @param string[] $ancestors
*/
public function __construct(
string $fullyQualifiedClassName,
array $ancestors = [],
bool $isRoot = false,
?ClassLikeWrapper $classLikeWrapper = null,
int $layer = 0
) {
$this->fullyQualifiedClassName = $fullyQualifiedClassName;
$this->ancestors = $ancestors;
$this->isRoot = $isRoot;
$this->classLikeWrapper = $classLikeWrapper;
$this->layer = $layer;
Expand All @@ -47,7 +37,6 @@ public function push(DiagramUnit $other): void
if (!$this->hasBeenPushed($other)) {
$this->classesDirectlyDependsOn[] = $other;
}
$other->isCirculating = in_array($other->fullyQualifiedClassName(), $this->ancestors, true);
}

public function fullyQualifiedClassName(): string {
Expand Down Expand Up @@ -80,16 +69,9 @@ public function subClasses(): array {
return $this->classesDirectlyDependsOn;
}

/**
* @return string[]
*/
public function ancestors(): array {
return $this->ancestors;
}

public function shouldStopTraverse(): bool
{
return $this->isCirculating || $this->isEndOfAnalysis() || $this->layer === Config::maxDepth();
return $this->isEndOfAnalysis() || $this->hasReachedMaxDepth() || $this->hasBeenVisited();
}

private function isEndOfAnalysis(): bool
Expand All @@ -103,6 +85,11 @@ private function isEndOfAnalysis(): bool
return false;
}

private function hasReachedMaxDepth(): bool
{
return $this->layer === Config::maxDepth();
}

private function hasBeenPushed(DiagramUnit $other): bool
{
foreach ($this->classesDirectlyDependsOn as $diagramUnit) {
Expand All @@ -113,7 +100,7 @@ private function hasBeenPushed(DiagramUnit $other): bool
return false;
}

public function hasBeenVisited(): bool
private function hasBeenVisited(): bool
{
if (in_array($this->fullyQualifiedClassName, self::$visitedClasses)) {
return true;
Expand Down
9 changes: 1 addition & 8 deletions src/Visitor/ClassVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ public function __construct(DiagramUnit $diagramUnit) {
}

public function enterNode(Node $node) {
if ($this->diagramUnit->shouldStopTraverse()) {
return $node;
}

if (!$node instanceof FullyQualified) {
return $node;
}
Expand All @@ -39,22 +35,19 @@ public function enterNode(Node $node) {
$classFile = ClassLoader::create($node);
if ($classFile->isClass()) {
Logger::info('load class', ['name' => $classFile->className()]);
$ancestors = $this->diagramUnit->ancestors();
$ancestors[] = $node->toCodeString();

$stmts = $classFile->stmts();
$classLike = ClassLikeNodeFinder::find($stmts);

$subClass = new DiagramUnit(
$classFile->className(),
$ancestors,
false,
$classLike,
$this->diagramUnit->nextLayer()
);
$this->diagramUnit->push($subClass);

if ($stmts === [] || $classFile->notLoaded() || $subClass->hasBeenVisited()) {
if ($stmts === [] || $classFile->notLoaded() || $subClass->shouldStopTraverse()) {
return $node;
}

Expand Down
58 changes: 2 additions & 56 deletions tests/DiagramUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public function testクラス名と名前空間が取得できること(): void
// given
$sut = new DiagramUnit(
'\Foo\Bar',
['\Foo\Bar'],
false,
null
);
Expand All @@ -48,40 +47,6 @@ public function testクラス名と名前空間が取得できること(): void
$this->assertSame('Foo', $namespace);
}

/**
* @noinspection NonAsciiCharacters
*/
public function test循環依存している時トラバースしないこと(): void
{
// given
$sut = new DiagramUnit(
'\Foo\Bar',
['\Foo\Bar'],
false,
null
);
$diagramUnit = new DiagramUnit(
'\Foo\Baz',
['\Foo\Bar', '\Foo\Baz'],
false,
null
);

// when1
$shouldStop = $sut->shouldStopTraverse();

// then1
$this->assertFalse($shouldStop);

// when2
$sut->push($diagramUnit);
$diagramUnit->push($sut);
$shouldStop = $sut->shouldStopTraverse();

// then2
$this->assertTrue($shouldStop);
}

/**
* @dataProvider data指定された名前空間のクラスをトラバースしないこと
* @noinspection NonAsciiCharacters
Expand All @@ -92,7 +57,6 @@ public function test指定された名前空間のクラスをトラバースし
Config::initialize($path);
$sut = new DiagramUnit(
'\Bar\Foo',
['\Bar\Foo'],
false,
null
);
Expand Down Expand Up @@ -125,20 +89,19 @@ public function test解析したことのあるクラスを再び解析しない
// given
$sut = new DiagramUnit(
'\Foo\Bar',
['\Foo\Bar'],
false,
null
);

// when1
$shouldStop = $sut->hasBeenVisited();
$shouldStop = $sut->shouldStopTraverse();

// then1
$this->assertFalse($shouldStop);

// when2
$sut->registerVisitedClass();
$shouldStop = $sut->hasBeenVisited();
$shouldStop = $sut->shouldStopTraverse();

// then2
$this->assertTrue($shouldStop);
Expand Down Expand Up @@ -167,7 +130,6 @@ public function data解析結果のルートを見分けられること(): \Gene
yield '解析結果がルートではない_クラスのファイルがない' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
null
),
Expand All @@ -177,7 +139,6 @@ public function data解析結果のルートを見分けられること(): \Gene
yield '解析結果がルートではない_クラスのファイルがある' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Class_('Bar'))
),
Expand All @@ -187,7 +148,6 @@ public function data解析結果のルートを見分けられること(): \Gene
yield '解析結果がルート_クラスのファイルがない' => [
new DiagramUnit(
'\Foo',
['\Foo'],
true,
null
),
Expand All @@ -197,7 +157,6 @@ public function data解析結果のルートを見分けられること(): \Gene
yield '解析結果がルート_クラスのファイルがある' => [
new DiagramUnit(
'\Foo',
['\Foo'],
true,
new ClassLikeWrapper(new Class_('Bar'))
),
Expand Down Expand Up @@ -231,7 +190,6 @@ public function data宣言要素が取得できること(): array
'具象クラス' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Class_('Bar'))
),
Expand All @@ -240,7 +198,6 @@ public function data宣言要素が取得できること(): array
'抽象クラス' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper($abstract)
),
Expand All @@ -249,7 +206,6 @@ public function data宣言要素が取得できること(): array
'インタフェース' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Interface_('Bar'))
),
Expand All @@ -258,7 +214,6 @@ public function data宣言要素が取得できること(): array
'トレイト' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Trait_('Bar'))
),
Expand All @@ -267,7 +222,6 @@ public function data宣言要素が取得できること(): array
'Enum' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Enum_('Bar'))
),
Expand All @@ -276,7 +230,6 @@ public function data宣言要素が取得できること(): array
'以上のどれでもない場合デフォルトの宣言要素を返す' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
null
),
Expand Down Expand Up @@ -306,7 +259,6 @@ public function dataトレイトを判定できること(): \Generator
yield '具象クラス' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Class_('Bar'))
),
Expand All @@ -315,7 +267,6 @@ public function dataトレイトを判定できること(): \Generator
yield 'トレイト' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Trait_('Bar'))
),
Expand All @@ -324,7 +275,6 @@ public function dataトレイトを判定できること(): \Generator
yield 'クラス類ではない' => [
new DiagramUnit(
'\Foo',
['\Foo'],
false,
null
),
Expand All @@ -340,7 +290,6 @@ public function testクラス類ではない時メソッドが1つも得られ
// given
$sut = new DiagramUnit(
'\Foo',
['\Foo'],
true,
null
);
Expand All @@ -363,7 +312,6 @@ public function testクラス類である時メソッドが得られること():
$classLikeWrapper = new ClassLikeWrapper($classLike);
$sut = new DiagramUnit(
'\Foo',
['\Foo'],
true,
$classLikeWrapper
);
Expand All @@ -383,7 +331,6 @@ public function test次の階層が得られること(): void
// given
$sut = new DiagramUnit(
'\Foo',
['\Foo'],
true,
null,
0
Expand All @@ -404,7 +351,6 @@ public function test階層が上限を超えると例外を送出すること():
// given
$sut = new DiagramUnit(
'\Foo',
['\Foo'],
true,
null,
PHP_INT_MAX
Expand Down
6 changes: 1 addition & 5 deletions tests/Visitor/ClassVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public function testユーザ定義クラスの名前と内容_定義済みク
$stmts = $this->parse(__DIR__ . '/../data/root.php');
$diagramUnit = new DiagramUnit(
'root',
['root'],
true,
null
);
Expand Down Expand Up @@ -69,7 +68,6 @@ public function testClassVisitorに登録されたことがあるクラスは再
$classLike = ClassLikeNodeFinder::find($stmts);
$diagramUnit = new DiagramUnit(
'\Hirokinoue\DependencyVisualizer\Tests\data\Visitor\VisitedClass\A',
['\Hirokinoue\DependencyVisualizer\Tests\data\Visitor\VisitedClass\A'],
false,
$classLike
);
Expand Down Expand Up @@ -105,7 +103,6 @@ public function test指定された名前空間を解析しないこと(string $
Config::initialize($path);
$sut = new ClassVisitor(new DiagramUnit(
'\Hirokinoue\DependencyVisualizer\Tests\data\Foo',
['\Hirokinoue\DependencyVisualizer\Tests\data\Foo'],
false,
new ClassLikeWrapper(new Class_(new Identifier('Foo')))
));
Expand Down Expand Up @@ -140,7 +137,6 @@ public function test指定された深さ以上解析しないこと(): void
Config::initialize(__DIR__ . '/../data/Visitor/Config/maxDepth');
$sut = new ClassVisitor(new DiagramUnit(
'\Foo',
['\Foo'],
false,
new ClassLikeWrapper(new Class_(new Identifier('Foo'))),
1
Expand All @@ -150,7 +146,7 @@ public function test指定された深さ以上解析しないこと(): void
$sut->enterNode(new FullyQualified('Hirokinoue\DependencyVisualizer\Tests\data\Baz'));

// then
$this->assertSame(2, DiagramUnit::countVisitedClasses());
$this->assertSame(1, DiagramUnit::countVisitedClasses());
}

/**
Expand Down

0 comments on commit d0ac0f7

Please sign in to comment.