Skip to content

Commit a33fc5c

Browse files
committed
changed how to create instance by factory methods.
1 parent 85cdb9d commit a33fc5c

File tree

3 files changed

+95
-27
lines changed

3 files changed

+95
-27
lines changed

src/Php/PhpTypeExpression.php

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,17 @@ class PhpTypeExpression {
2121
/** @var PhpType[] */
2222
private array $types;
2323

24-
public function __construct(NodeAbstract $stmt, string $targetType, array $currentNamespace) {
24+
private function __construct(NodeAbstract $stmt, string $targetType, array $currentNamespace, string $docString) {
2525
if ( ! in_array($targetType, [self::VAR, self::PARAM, self::RETURN_TYPE])) {
2626
throw new \Exception('invalid tag.');
2727
}
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-
}
3628

3729
$type = $stmt->{$targetType === self::RETURN_TYPE ? 'returnType' : 'type'};
38-
if ($type instanceOf UnionType) {
30+
if ( ! empty($docString)) {
31+
foreach (explode('|', $docString) as $typeString) {
32+
$this->types[] = $this->parseType($type, $currentNamespace, $typeString);
33+
}
34+
} else if ($type instanceof UnionType) {
3935
foreach ($type->types as $t) {
4036
$this->types[] = $this->parseType($t, $currentNamespace);
4137
}
@@ -44,21 +40,47 @@ public function __construct(NodeAbstract $stmt, string $targetType, array $curre
4440
}
4541
}
4642

43+
public static function buildByVar(NodeAbstract $stmt, array $currentNamespace): self {
44+
$doc = $stmt->getDocComment();
45+
$typeString = '';
46+
if ($doc instanceof Doc) {
47+
$docString = $doc->getText();
48+
if (preg_match(sprintf('/@%s\s+(\S+)(\b|\s).*/', 'var'), $docString, $matches)) {
49+
$typeString = $matches[1];
50+
}
51+
}
52+
return new self($stmt, self::VAR, $currentNamespace, $typeString);
53+
}
54+
4755
/**
4856
* @param Property|Identifier|NullableType|Name $type 型を表すAST
4957
* @param string[] $currentNamespace 名前空間配列
58+
* @param ?string $typeString コメントの型表記
5059
*/
51-
private function parseType(Property|Identifier|NullableType|Name $type, array $currentNamespace) {
60+
private function parseType(Property|Identifier|NullableType|Name|null $type, array $currentNamespace, ?string $typeString = '') {
5261
$parts = [];
53-
if (!empty($this->docString)) {
54-
if (mb_substr($this->docString, 0, 1) === '\\') {
55-
$docString = mb_substr($this->docString, 1);
62+
if (!empty($typeString)) {
63+
$primitiveTypes = [
64+
'null',
65+
'bool',
66+
'int',
67+
'float',
68+
'string',
69+
'array',
70+
'object',
71+
'callable',
72+
'resource',
73+
];
74+
if (in_array($typeString, $primitiveTypes)) {
75+
$parts = [$typeString]; // primitive typeは、namespaceを付与しない。
5676
} else {
57-
var_dump($this->docString);
58-
$docString = sprintf('%s\\%s', implode('\\', $currentNamespace), $this->docString);
59-
var_dump($docString);
77+
if (mb_substr($typeString, 0, 1) === '\\') {
78+
$docString = mb_substr($typeString, 1);
79+
} else {
80+
$docString = sprintf('%s\\%s', implode('\\', $currentNamespace), $typeString);
81+
}
82+
$parts = explode('\\', $docString);
6083
}
61-
$parts = explode('\\', $docString);
6284
}
6385
$nullable = false;
6486
if (count($parts) === 0) { // docCommentから取得できない時には、$typeを解析する。
@@ -75,7 +97,7 @@ private function parseType(Property|Identifier|NullableType|Name $type, array $c
7597
}
7698
}
7799
$typeName = array_pop($parts);
78-
return new PhpType($parts, $type->getType(), $typeName ?? '', null, $nullable);
100+
return new PhpType($parts, empty($type) ? '' : $type->getType(), $typeName ?? '', null, $nullable);
79101
}
80102

81103
/**

test/PhpTypeExpressionTest.php

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function testNullableString(): void {
2121
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
2222
}
2323

24-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[0], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
24+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[0], ['hoge', 'fuga', 'product']);
2525
$types = $expression->getTypes();
2626

2727
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
@@ -37,7 +37,7 @@ public function testIntOrString(): void {
3737
} catch (Error $error) {
3838
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
3939
}
40-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[1], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
40+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[1], ['hoge', 'fuga', 'product']);
4141
$types = $expression->getTypes();
4242

4343
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
@@ -56,7 +56,7 @@ public function testPrice(): void {
5656
} catch (Error $error) {
5757
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
5858
}
59-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[2], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
59+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[2], ['hoge', 'fuga', 'product']);
6060
$types = $expression->getTypes();
6161

6262
$this->assertSame(['hoge', 'fuga', 'product'], $types[0]->getNamespace(), 'namespace');
@@ -72,7 +72,7 @@ public function testException(): void {
7272
} catch (Error $error) {
7373
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
7474
}
75-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[4], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
75+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[4], ['hoge', 'fuga', 'product']);
7676
$types = $expression->getTypes();
7777

7878
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
@@ -88,7 +88,7 @@ public function testRelated(): void {
8888
} catch (Error $error) {
8989
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
9090
}
91-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[5], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
91+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[5], ['hoge', 'fuga', 'product']);
9292
$types = $expression->getTypes();
9393

9494
$this->assertSame(['hoge', 'fuga', 'product', 'bar'], $types[0]->getNamespace(), 'namespace');
@@ -104,7 +104,7 @@ public function testAbsolute(): void {
104104
} catch (Error $error) {
105105
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
106106
}
107-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[6], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
107+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[6], ['hoge', 'fuga', 'product']);
108108
$types = $expression->getTypes();
109109

110110
$this->assertSame(['hoge', 'fuga', 'product', 'bar'], $types[0]->getNamespace(), 'namespace');
@@ -121,11 +121,52 @@ public function testDocString(): void {
121121
} catch (Error $error) {
122122
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
123123
}
124-
$expression = new PhpTypeExpression($ast[0]->stmts[1]->stmts[7], PhpTypeExpression::VAR, ['hoge', 'fuga', 'product']);
124+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[7], ['hoge', 'fuga', 'product']);
125125
$types = $expression->getTypes();
126126

127127
$this->assertSame(['hoge', 'fuga', 'product', 'bur'], $types[0]->getNamespace(), 'namespace');
128128
$this->assertSame('Bon', $types[0]->getName(), 'name');
129129
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
130130
}
131+
public function testDocStringUnion(): void {
132+
// /** @var bur\Bon $docString */
133+
// private bar\Boo $docString;
134+
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
135+
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
136+
try {
137+
$ast = $parser->parse(file_get_contents($filename));
138+
} catch (Error $error) {
139+
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
140+
}
141+
$expression = PhpTypeExpression::buildByVar($ast[0]->stmts[1]->stmts[8], ['hoge', 'fuga', 'product']);
142+
$types = $expression->getTypes();
143+
144+
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
145+
$this->assertSame('string', $types[0]->getName(), 'name');
146+
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
147+
$this->assertSame([], $types[1]->getNamespace(), 'namespace');
148+
$this->assertSame('int', $types[1]->getName(), 'name');
149+
$this->assertSame(false, $types[1]->getNullable(), 'nullable');
150+
}
151+
public function testMethodParameterDocString(): void {
152+
// /** @params string|int $param1 */
153+
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
154+
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
155+
try {
156+
$ast = $parser->parse(file_get_contents($filename));
157+
} catch (Error $error) {
158+
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
159+
}
160+
// var_dump($ast[0]->stmts[1]->stmts[8]);die();
161+
$expression = PhpTypeExpression::buildByMethodParam($ast[0]->stmts[1]->stmts[9], ['hoge', 'fuga', 'product']);
162+
$types = $expression->getTypes();
163+
164+
$this->assertSame([], $types[0]->getNamespace(), 'namespace');
165+
$this->assertSame('string', $types[0]->getName(), 'name');
166+
$this->assertSame(false, $types[0]->getNullable(), 'nullable');
167+
$this->assertSame([], $types[1]->getNamespace(), 'namespace');
168+
$this->assertSame('int', $types[1]->getName(), 'name');
169+
$this->assertSame(false, $types[1]->getNullable(), 'nullable');
170+
}
171+
131172
}

test/fixtures/php8/product/Product.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ class Product {
1616
private \hoge\fuga\product\bar\Boo $boo2;
1717
/** @var bur\Bon $docString */
1818
private bar\Boo $docString;
19+
/** @var string|int $docString */
20+
private $docStringUnion;
1921

20-
/** @return Product product */
22+
/**
23+
* @param string|int $param1
24+
* @return Product product
25+
*/
2126
public function method1(string $param1) {
2227
}
2328
}

0 commit comments

Comments
 (0)