Skip to content

Commit 538407f

Browse files
committed
make property type PhpTypeExcepression.
1 parent df2c56f commit 538407f

File tree

6 files changed

+52
-26
lines changed

6 files changed

+52
-26
lines changed

src/DiagramElement/Entry.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ public function getArrows(): array {
8181
$arrows = [];
8282
//フィールド変数の型に対しての依存をArrowとして追加する。
8383
foreach ($this->class->getProperties() as $p) {
84-
$arrows[] = new ArrowDependency($this->class, $p->getType());
84+
foreach ($p->getType()->getTypes() as $t) {
85+
$arrows[] = new ArrowDependency($this->class, $t);
86+
}
8587
}
8688
foreach ($this->class->getMethods() as $m) {
8789
if ( ! $m->getAccessModifier()->isPublic()) {

src/Php/PhpProperty.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@
77

88
class PhpProperty {
99
protected string $name;
10-
protected PhpType $type;
10+
protected PhpTypeExpression $type;
1111
protected PhpAccessModifier $accessModifier;
1212

1313
public function __construct(Property $p, PhpClass $class) {
1414
$this->name = $p->props[0]->name->toString();
15-
$this->type = $class->findTypeByTypeParts($p, 'type', 'var');
15+
// $this->type = $class->findTypeByTypeParts($p, 'type', 'var');
16+
$this->type = PhpTypeExpression::buildByVar($p, $class->getNamespace(), $class->getUses());
1617
$this->accessModifier = new PhpAccessModifier($p);
1718
}
1819

1920
public function getName(): string {
2021
return $this->name;
2122
}
2223

23-
public function getType(): PhpType {
24+
public function getType(): PhpTypeExpression {
2425
return $this->type;
2526
}
2627

src/Php/PhpTypeExpression.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class PhpTypeExpression {
1515
public const VAR = 'var';
1616
public const PARAM = 'param';
1717
public const RETURN_TYPE = 'return';
18+
public const FOR_TEST = 'for_test';
1819

1920
/** @var string */
2021
private string $docString = '';
@@ -31,9 +32,12 @@ class PhpTypeExpression {
3132
* @param PhpType[] $uses
3233
*/
3334
private function __construct(NodeAbstract $stmt, string $targetType, array $currentNamespace, string $docString, array $uses) {
34-
if ( ! in_array($targetType, [self::VAR, self::PARAM, self::RETURN_TYPE])) {
35+
if ( ! in_array($targetType, [self::VAR, self::PARAM, self::RETURN_TYPE, self::FOR_TEST])) {
3536
throw new \Exception('invalid tag.');
3637
}
38+
if ($targetType === self::FOR_TEST) {
39+
return; // 単体テストのため仕方なく空のインスタンスを生成する方法を用意します。
40+
}
3741
$this->uses = $uses;
3842

3943
$type = $stmt->{$targetType === self::RETURN_TYPE ? 'returnType' : 'type'};
@@ -117,6 +121,15 @@ public static function buildByMethodReturn(
117121
return new self($stmt, self::RETURN_TYPE, $currentNamespace, $typeString, $uses);
118122
}
119123

124+
/**
125+
* 単体テスト用factory
126+
*/
127+
public static function buildByPhpType(PhpType $type): self {
128+
$instance = new self(new Name('dummy'), self::FOR_TEST, [], '', []);
129+
$instance->types[] = $type;
130+
return $instance;
131+
}
132+
120133
/**
121134
* @param Property|Identifier|NullableType|Name $type 型を表すAST
122135
* @param string[] $currentNamespace 名前空間配列
@@ -144,13 +157,13 @@ private function parseType(Property|Identifier|NullableType|Name|null $type, arr
144157
$parts = explode('\\', $docString);
145158
} else {
146159
// usesを検索して適切なnamespaceを探す必要がある。
147-
$targets = array_filter($this->uses, function(PhpType $t) use($typeString) {
160+
$targets = array_values(array_filter($this->uses, function(PhpType $t) use($typeString) {
148161
$xParts = explode('\\', $typeString);
149-
$name = array_pop($xParts);
162+
$name = end($xParts);
150163
return $name === $t->getName();
151-
});
164+
}));
152165
if (count($targets) > 0) {
153-
$parts = array_merge($targets[0]->getNamespace());
166+
$parts = array_merge($targets[0]->getNamespace(), [$targets[0]->getName()]);
154167
} else {
155168
$docString = sprintf('%s\\%s', implode('\\', $currentNamespace), $typeString);
156169
$parts = explode('\\', $docString);
@@ -171,12 +184,12 @@ private function parseType(Property|Identifier|NullableType|Name|null $type, arr
171184
} else if ($type instanceOf Name) {
172185
$typeParts = $type->parts;
173186
// usesを検索して適切なnamespaceを探す必要がある。
174-
$targets = array_filter($this->uses, function(PhpType $t) use($typeParts) {
175-
$name = array_pop($typeParts);
187+
$targets = array_values(array_filter($this->uses, function(PhpType $t) use($typeParts) {
188+
$name = end($typeParts);
176189
return $name === $t->getName();
177-
});
190+
}));
178191
if (count($targets) > 0) {
179-
$parts = array_merge($targets[0]->getNamespace(), [array_pop($typeParts)]);
192+
$parts = array_merge($targets[0]->getNamespace(), [end($typeParts)]);
180193
} else {
181194
$parts = array_merge($currentNamespace, $type->parts);
182195
}
@@ -185,11 +198,19 @@ private function parseType(Property|Identifier|NullableType|Name|null $type, arr
185198
$typeName = array_pop($parts);
186199
return new PhpType($parts, empty($type) ? '' : $type->getType(), $typeName ?? '', null, $nullable);
187200
}
188-
201+
189202
/**
190203
* @return PhpType[] types
191204
*/
192205
public function getTypes(): array {
193206
return $this->types;
194207
}
208+
209+
public function getName(): string {
210+
$types = [];
211+
foreach ($this->types as $type) {
212+
$types[] = sprintf('%s%s', $type->getNullable() ? '?' : '', $type->getName());
213+
}
214+
return implode('|', $types);
215+
}
195216
}

test/PhpReflectionTest.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ public function testDump(): void {
3030
$this->assertSame([], $data->getClassType()->getNamespace(), 'namespace name.');
3131
$this->assertSame('name', $data->getProperties()[0]->getName(), 'property name.');
3232
$this->assertSame('Name', $data->getProperties()[0]->getType()->getName(), 'property name type.');
33-
$this->assertSame([], $data->getProperties()[0]->getType()->getNamespace(), 'namespace.');
33+
$this->assertSame([], $data->getProperties()[0]->getType()->getTypes()[0]->getNamespace(), 'namespace.');
3434
$this->assertSame(true, $data->getProperties()[0]->getAccessModifier()->isPrivate(), 'property name Modifiers.');
3535
$this->assertSame('price', $data->getProperties()[1]->getName(), 'property price.');
3636
$this->assertSame('Price', $data->getProperties()[1]->getType()->getName(), 'property price type.');
37-
$this->assertSame([], $data->getProperties()[1]->getType()->getNamespace(), 'namespace.');
37+
$this->assertSame([], $data->getProperties()[1]->getType()->getTypes()[0]->getNamespace(), 'namespace.');
3838
$this->assertSame(true, $data->getProperties()[1]->getAccessModifier()->isPrivate(), 'property price Modifiers.');
3939
}
4040

@@ -49,7 +49,7 @@ public function testDump_Price(): void {
4949
$this->assertSame([], $data->getClassType()->getNamespace(), 'namespace name.');
5050
$this->assertSame('price', $data->getProperties()[0]->getName(), 'property price.');
5151
$this->assertSame('int', $data->getProperties()[0]->getType()->getName(), 'property price type.');
52-
$this->assertSame([], $data->getProperties()[0]->getType()->getNamespace(), 'namespace.');
52+
$this->assertSame([], $data->getProperties()[0]->getType()->getTypes()[0]->getNamespace(), 'namespace.');
5353
$this->assertSame(true, $data->getProperties()[0]->getAccessModifier()->isPrivate(), 'property price Modifiers.');
5454
}
5555
// public function testDump_php8_Price(): void {
@@ -78,10 +78,10 @@ public function testDump_with_namespace(): void {
7878
$this->assertSame(['hoge', 'fuga', 'product'], $data->getClassType()->getNamespace(), 'namespace name.');
7979
$this->assertSame('name', $data->getProperties()[0]->getName(), 'type.');
8080
$this->assertSame('Name', $data->getProperties()[0]->getType()->getName(), 'type.');
81-
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[0]->getType()->getNamespace(), 'namespace.');
81+
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[0]->getType()->getTypes()[0]->getNamespace(), 'namespace.');
8282
$this->assertSame('price', $data->getProperties()[1]->getName(), 'name.');
8383
$this->assertSame('Price', $data->getProperties()[1]->getType()->getName(), 'type.');
84-
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[1]->getType()->getNamespace(), 'namespace.');
84+
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[1]->getType()->getTypes()[0]->getNamespace(), 'namespace.');
8585
}
8686

8787
public function testDump_with_phpdoc(): void {
@@ -94,16 +94,16 @@ public function testDump_with_phpdoc(): void {
9494
$this->assertSame('Product', $data->getClassType()->getName(), 'class type name.');
9595
$this->assertSame('Stmt_Class', $data->getClassType()->getMeta(), 'class meta name.');
9696
$this->assertSame(['hoge', 'fuga', 'product'], $data->getClassType()->getNamespace(), 'namespace name.');
97-
$this->assertSame('name', $data->getProperties()[0]->getName(), 'type.');
97+
$this->assertSame('name', $data->getProperties()[0]->getName(), 'name.');
9898
$this->assertSame('Name', $data->getProperties()[0]->getType()->getName(), 'type.');
99-
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[0]->getType()->getNamespace(), 'Name namespace.');
99+
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[0]->getType()->getTypes()[0]->getNamespace(), 'Name namespace.');
100100
$this->assertSame('price', $data->getProperties()[1]->getName(), 'name.');
101101
$this->assertSame('Price', $data->getProperties()[1]->getType()->getName(), 'type.');
102-
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[1]->getType()->getNamespace(), 'Price namespace.');
102+
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[1]->getType()->getTypes()[0]->getNamespace(), 'Price namespace.');
103103
$this->assertSame('Tag[]', $data->getProperties()[2]->getType()->getName(), 'type.');
104-
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[2]->getType()->getNamespace(), 'Tag[] namespace.');
104+
$this->assertSame(['hoge', 'fuga', 'product'], $data->getProperties()[2]->getType()->getTypes()[0]->getNamespace(), 'Tag[] namespace.');
105105
$this->assertSame('Ban[]', $data->getProperties()[3]->getType()->getName(), 'full package name, Ban type.');
106-
$this->assertSame(['ban', 'ban', 'ban'], $data->getProperties()[3]->getType()->getNamespace(), 'full package name, ban.ban.ban.Ban[] namespace.');
106+
$this->assertSame(['ban', 'ban', 'ban'], $data->getProperties()[3]->getType()->getTypes()[0]->getNamespace(), 'full package name, ban.ban.ban.Ban[] namespace.');
107107
}
108108

109109
public function testDump_with_interface(): void {

test/dummy/PhpClassDummy.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
PhpClass,
55
PhpType,
66
PhpProperty,
7+
PhpTypeExpression,
78
};
89
require_once(__DIR__ . '/PhpMethodDummy.php');
910
require_once(__DIR__ . '/PhpPropertyDummy.php');
@@ -47,7 +48,7 @@ public function getUses(): array {
4748
public function getProperties(): array {
4849
$props = [];
4950
foreach ($this->data->properties as $p) {
50-
$props[] = new PhpPropertyDummy($p->name, new PhpType($p->type->namespace, '', $p->type->name), $p->modifier);
51+
$props[] = new PhpPropertyDummy($p->name, PhpTypeExpression::buildByPhpType(new PhpType($p->type->namespace, '', $p->type->name)), $p->modifier);
5152
}
5253
return $props;
5354
}

test/dummy/PhpPropertyDummy.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
PhpType,
99
PhpProperty,
1010
PhpAccessModifier,
11+
PhpTypeExpression,
1112
};
1213

1314
class PhpPropertyDummy extends PhpProperty {
1415
// public string $name;
1516
// public PhpType $type;
1617
// public PhpAccessModifier $accessModifier;
1718

18-
public function __construct(string $name, PhpType $type, \stdClass $modifier) {
19+
public function __construct(string $name, PhpTypeExpression $type, \stdClass $modifier) {
1920
$this->name = $name;
2021
$this->type = $type;
2122
$this->accessModifier = new PhpAccessModifierDummy($modifier);

0 commit comments

Comments
 (0)