Skip to content

Commit 85cdb9d

Browse files
committed
added parse docComment.
1 parent 7c3a613 commit 85cdb9d

File tree

4 files changed

+90
-19
lines changed

4 files changed

+90
-19
lines changed

src/Php/PhpTypeExpression.php

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Smeghead\PhpClassDiagram\Php;
44

5+
use PhpParser\Comment\Doc;
56
use PhpParser\Node\Identifier;
67
use PhpParser\Node\Name;
78
use PhpParser\Node\Name\FullyQualified;
@@ -11,14 +12,29 @@
1112
use PhpParser\NodeAbstract;
1213

1314
class PhpTypeExpression {
14-
public const TYPE = 'type';
15-
public const RETURN_TYPE = 'return_type';
15+
public const VAR = 'var';
16+
public const PARAM = 'param';
17+
public const RETURN_TYPE = 'return';
1618

19+
/** @var string */
20+
private string $docString = '';
1721
/** @var PhpType[] */
1822
private array $types;
1923

2024
public function __construct(NodeAbstract $stmt, string $targetType, array $currentNamespace) {
21-
$type = $stmt->{$targetType};
25+
if ( ! in_array($targetType, [self::VAR, self::PARAM, self::RETURN_TYPE])) {
26+
throw new \Exception('invalid tag.');
27+
}
28+
$doc = $stmt->getDocComment();
29+
if ($doc instanceof Doc) {
30+
$docString = $doc->getText();
31+
if (preg_match(sprintf('/@%s\s+(\S+)(\b|\s).*/', $targetType), $docString, $matches)) {
32+
var_dump($docString);
33+
$this->docString = $matches[1];
34+
}
35+
}
36+
37+
$type = $stmt->{$targetType === self::RETURN_TYPE ? 'returnType' : 'type'};
2238
if ($type instanceOf UnionType) {
2339
foreach ($type->types as $t) {
2440
$this->types[] = $this->parseType($t, $currentNamespace);
@@ -33,18 +49,30 @@ public function __construct(NodeAbstract $stmt, string $targetType, array $curre
3349
* @param string[] $currentNamespace 名前空間配列
3450
*/
3551
private function parseType(Property|Identifier|NullableType|Name $type, array $currentNamespace) {
36-
$nullable = false;
37-
if ($type instanceOf NullableType) {
38-
$type = $type->type;
39-
$nullable = true;
40-
}
4152
$parts = [];
42-
if ($type instanceOf Identifier) {
43-
$parts[] = $type->name;
44-
} else if ($type instanceOf FullyQualified) {
45-
$parts = $type->parts;
46-
} else if ($type instanceOf Name) {
47-
$parts = array_merge($currentNamespace, $type->parts);
53+
if (!empty($this->docString)) {
54+
if (mb_substr($this->docString, 0, 1) === '\\') {
55+
$docString = mb_substr($this->docString, 1);
56+
} else {
57+
var_dump($this->docString);
58+
$docString = sprintf('%s\\%s', implode('\\', $currentNamespace), $this->docString);
59+
var_dump($docString);
60+
}
61+
$parts = explode('\\', $docString);
62+
}
63+
$nullable = false;
64+
if (count($parts) === 0) { // docCommentから取得できない時には、$typeを解析する。
65+
if ($type instanceOf NullableType) {
66+
$type = $type->type;
67+
$nullable = true;
68+
}
69+
if ($type instanceOf Identifier) {
70+
$parts[] = $type->name;
71+
} else if ($type instanceOf FullyQualified) {
72+
$parts = $type->parts;
73+
} else if ($type instanceOf Name) {
74+
$parts = array_merge($currentNamespace, $type->parts);
75+
}
4876
}
4977
$typeName = array_pop($parts);
5078
return new PhpType($parts, $type->getType(), $typeName ?? '', null, $nullable);

test/PhpTypeExpressionTest.php

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function setUp(): void {
1212
}
1313

1414
public function testNullableString(): void {
15+
// private ?string $nullableString;
1516
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
1617
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
1718
try {
@@ -20,22 +21,23 @@ public function testNullableString(): void {
2021
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
2122
}
2223

23-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[0], PhpTypeExpression::TYPE, ['hoge', 'fuga', 'product']);
24+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[0], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
2425
$types = $expression->getTypes();
2526

2627
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
2728
$this->assertSame('string', $types[0]->getName(), 'name');
2829
$this->assertSame(true, $types[0]->getNullable(), 'nullable');
2930
}
3031
public function testIntOrString(): void {
32+
// private int|string $intOrString;
3133
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
3234
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
3335
try {
3436
$ast = $parser->parse(file_get_contents($filename));
3537
} catch (Error $error) {
3638
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
3739
}
38-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[1], PhpTypeExpression::TYPE, ['hoge', 'fuga', 'product']);
40+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[1], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
3941
$types = $expression->getTypes();
4042

4143
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
@@ -46,48 +48,84 @@ public function testIntOrString(): void {
4648
$this->assertSame(false, $types[1]->getNullable(), 'nullable');
4749
}
4850
public function testPrice(): void {
51+
// private Price $price;
4952
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
5053
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
5154
try {
5255
$ast = $parser->parse(file_get_contents($filename));
5356
} catch (Error $error) {
5457
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
5558
}
56-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[2], PhpTypeExpression::TYPE, ['hoge', 'fuga', 'product']);
59+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[2], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
5760
$types = $expression->getTypes();
5861

5962
$this->assertSame(['hoge', 'fuga', 'product'], $types[0]->getNamespace(), 'namespace');
6063
$this->assertSame('Name', $types[0]->getName(), 'name');
6164
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
6265
}
6366
public function testException(): void {
67+
// private \Exception $error;
6468
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
6569
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
6670
try {
6771
$ast = $parser->parse(file_get_contents($filename));
6872
} catch (Error $error) {
6973
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
7074
}
71-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[4], PhpTypeExpression::TYPE, ['hoge', 'fuga', 'product']);
75+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[4], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
7276
$types = $expression->getTypes();
7377

7478
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
7579
$this->assertSame('Exception', $types[0]->getName(), 'name');
7680
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
7781
}
7882
public function testRelated(): void {
83+
// private bar\Boo $boo;
7984
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
8085
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
8186
try {
8287
$ast = $parser->parse(file_get_contents($filename));
8388
} catch (Error $error) {
8489
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
8590
}
86-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[5], PhpTypeExpression::TYPE, ['hoge', 'fuga', 'product']);
91+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[5], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
8792
$types = $expression->getTypes();
8893

8994
$this->assertSame(['hoge', 'fuga', 'product', 'bar'], $types[0]->getNamespace(), 'namespace');
9095
$this->assertSame('Boo', $types[0]->getName(), 'name');
9196
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
9297
}
98+
public function testAbsolute(): void {
99+
// private \hoge\fuga\product\bar\Boo $boo2;
100+
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
101+
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
102+
try {
103+
$ast = $parser->parse(file_get_contents($filename));
104+
} catch (Error $error) {
105+
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
106+
}
107+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[6], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
108+
$types = $expression->getTypes();
109+
110+
$this->assertSame(['hoge', 'fuga', 'product', 'bar'], $types[0]->getNamespace(), 'namespace');
111+
$this->assertSame('Boo', $types[0]->getName(), 'name');
112+
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
113+
}
114+
public function testDocString(): void {
115+
// /** @var bur\Bon $docString */
116+
// private bar\Boo $docString;
117+
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
118+
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
119+
try {
120+
$ast = $parser->parse(file_get_contents($filename));
121+
} catch (Error $error) {
122+
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
123+
}
124+
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[7], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
125+
$types = $expression->getTypes();
126+
127+
$this->assertSame(['hoge', 'fuga', 'product', 'bur'], $types[0]->getNamespace(), 'namespace');
128+
$this->assertSame('Bon', $types[0]->getName(), 'name');
129+
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
130+
}
93131
}

test/fixtures/php8/product/Product.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ class Product {
1313
private Price $price;
1414
private \Exception $error;
1515
private bar\Boo $boo;
16+
private \hoge\fuga\product\bar\Boo $boo2;
17+
/** @var bur\Bon $docString */
18+
private bar\Boo $docString;
1619

1720
/** @return Product product */
1821
public function method1(string $param1) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?php
2+
namespace hoge\fuga\product\bar;
3+
24
class Boo {
35

46
}

0 commit comments

Comments
 (0)