Skip to content

Commit 056222f

Browse files
committed
Use DocBlock classes, add return type hint and allow override of doc block
1 parent d0a8cc6 commit 056222f

File tree

3 files changed

+152
-53
lines changed

3 files changed

+152
-53
lines changed

src/Code/MethodGenerator.php

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
namespace OpenCodeModeling\CodeAst\Code;
1212

13+
use OpenCodeModeling\CodeAst\Code\DocBlock\DocBlock;
14+
use OpenCodeModeling\CodeAst\Code\DocBlock\Tag\ParamTag;
15+
use OpenCodeModeling\CodeAst\Code\DocBlock\Tag\ReturnTag;
1316
use OpenCodeModeling\CodeAst\Exception;
1417
use PhpParser\Comment\Doc;
1518
use PhpParser\Node\Stmt\ClassMethod;
@@ -49,6 +52,16 @@ final class MethodGenerator extends AbstractMemberGenerator
4952
*/
5053
private $docBlockComment;
5154

55+
/**
56+
* @var string|null
57+
*/
58+
private $returnTypeDocBlockHint;
59+
60+
/**
61+
* @var DocBlock|null
62+
*/
63+
private $docBlock;
64+
5265
/**
5366
* @param string $name
5467
* @param array $parameters
@@ -154,7 +167,7 @@ public function getReturnType(): ?TypeGenerator
154167
return $this->returnType;
155168
}
156169

157-
public function docBlockComment(): ?string
170+
public function getDocBlockComment(): ?string
158171
{
159172
return $this->docBlockComment;
160173
}
@@ -164,10 +177,20 @@ public function setDocBlockComment(?string $docBlockComment): void
164177
$this->docBlockComment = $docBlockComment;
165178
}
166179

180+
public function getReturnTypeDocBlockHint(): ?string
181+
{
182+
return $this->returnTypeDocBlockHint;
183+
}
184+
185+
public function setReturnTypeDocBlockHint(?string $typeDocBlockHint): void
186+
{
187+
$this->returnTypeDocBlockHint = $typeDocBlockHint;
188+
}
189+
167190
/**
168191
* @return bool
169192
*/
170-
public function typed(): bool
193+
public function getTyped(): bool
171194
{
172195
return $this->typed;
173196
}
@@ -180,46 +203,18 @@ public function setTyped(bool $typed): void
180203
$this->typed = $typed;
181204
}
182205

183-
public function generate(): ClassMethod
206+
/**
207+
* Ignores generation of the doc block and uses provided doc block instead.
208+
*
209+
* @param DocBlock $docBlock
210+
*/
211+
public function overrideDocBlock(DocBlock $docBlock): void
184212
{
185-
$docBlockTypes = [];
186-
187-
foreach ($this->getParameters() as $parameter) {
188-
if (null === $parameter->getType()) {
189-
$type = 'mixed';
190-
} else {
191-
$type = $parameter->getType()->isNullable()
192-
? $parameter->getType()->type() . '|null'
193-
: $parameter->getType()->type();
194-
}
195-
196-
if ($typeHint = $parameter->getTypeDocBlockHint()) {
197-
$type = $typeHint;
198-
}
199-
200-
$docBlockTypes[] = '@var ' . $type . ' $' . $parameter->getName();
201-
}
202-
203-
$methodComment = "/**\n";
204-
205-
if ($this->docBlockComment) {
206-
$multiLineDocBlockComment = \trim(\preg_replace("/\n/", "\n * ", $this->docBlockComment));
207-
208-
$methodComment .= " * {$multiLineDocBlockComment}\n *";
209-
}
210-
211-
foreach ($docBlockTypes as $docBlockType) {
212-
$methodComment .= "\n * " . $docBlockType;
213-
}
214-
215-
$methodComment = \preg_replace("/ \* \n/", " *\n", $methodComment) . "\n */";
216-
217-
$attributes = [];
218-
219-
if ($this->typed === false || $this->docBlockComment) {
220-
$attributes = ['comments' => [new Doc($methodComment)]];
221-
}
213+
$this->docBlock = $docBlock;
214+
}
222215

216+
public function generate(): ClassMethod
217+
{
223218
return new ClassMethod(
224219
$this->getName(),
225220
[
@@ -233,10 +228,51 @@ static function (ParameterGenerator $parameter) {
233228
'stmts' => $this->body ? $this->body->generate() : null,
234229
'returnType' => $this->returnType ? $this->returnType->generate() : null,
235230
],
236-
$attributes
231+
$this->generateAttributes()
237232
);
238233
}
239234

235+
private function generateAttributes(): array
236+
{
237+
$attributes = [];
238+
239+
if ($this->docBlock) {
240+
return ['comments' => [new Doc($this->docBlock->generate())]];
241+
}
242+
243+
if ($this->typed === false || $this->docBlockComment || $this->returnTypeDocBlockHint) {
244+
$docBlock = new DocBlock($this->docBlockComment);
245+
246+
foreach ($this->getParameters() as $parameter) {
247+
if (null === $parameter->getType()) {
248+
$types = 'mixed';
249+
} else {
250+
$types = $parameter->getType()->types();
251+
}
252+
if ($typeHint = $parameter->getTypeDocBlockHint()) {
253+
$types = $typeHint;
254+
}
255+
$docBlock->addTag(new ParamTag($parameter->getName(), $types));
256+
}
257+
258+
$returnType = null;
259+
260+
if ($this->returnType) {
261+
$returnType = $this->returnType->type();
262+
}
263+
if ($this->returnTypeDocBlockHint) {
264+
$returnType = $this->returnTypeDocBlockHint;
265+
}
266+
if ($returnType) {
267+
$docBlock->addTag(new ReturnTag($returnType));
268+
}
269+
270+
$attributes = ['comments' => [new Doc($docBlock->generate())]];
271+
}
272+
273+
return $attributes;
274+
}
275+
240276
public function withoutBody(): self
241277
{
242278
$self = clone $this;

src/Code/TypeGenerator.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ public function isNullable(): bool
118118
return $this->nullable;
119119
}
120120

121+
/**
122+
* Normally only one type. Additionally the type null if nullable.
123+
*
124+
* @return string[]
125+
*/
126+
public function types(): array
127+
{
128+
$types = [$this->type];
129+
130+
if ($this->nullable) {
131+
$types[] = 'null';
132+
}
133+
134+
return $types;
135+
}
136+
121137
public function generate(): NodeAbstract
122138
{
123139
$type = $this->isInternalPhpType

tests/Code/MethodGeneratorTest.php

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace OpenCodeModelingTest\CodeAst\Code;
66

7+
use OpenCodeModeling\CodeAst\Code\DocBlock\DocBlock;
78
use OpenCodeModeling\CodeAst\Code\MethodGenerator;
89
use OpenCodeModeling\CodeAst\Code\ParameterGenerator;
910
use PhpParser\Parser;
@@ -52,6 +53,49 @@ public function setType(?string $type) : void;
5253
$this->assertSame($expectedOutput, $this->printer->prettyPrintFile([$method->generate()]));
5354
}
5455

56+
/**
57+
* @test
58+
*/
59+
public function it_generates_method_with_doc_block_if_typed(): void
60+
{
61+
$method = new MethodGenerator('getItems');
62+
$method->setReturnTypeDocBlockHint('Items[]');
63+
$method->setReturnType('array');
64+
65+
$expectedOutput = <<<'EOF'
66+
<?php
67+
68+
/**
69+
* @return Items[]
70+
*/
71+
public function getItems() : array;
72+
EOF;
73+
74+
$this->assertSame($expectedOutput, $this->printer->prettyPrintFile([$method->generate()]));
75+
}
76+
77+
/**
78+
* @test
79+
*/
80+
public function it_generates_method_with_overridden_doc_block(): void
81+
{
82+
$method = new MethodGenerator('getItems');
83+
$method->setReturnTypeDocBlockHint('Items[]');
84+
$method->setReturnType('array');
85+
$method->overrideDocBlock(new DocBlock('Awesome'));
86+
87+
$expectedOutput = <<<'EOF'
88+
<?php
89+
90+
/**
91+
* Awesome
92+
*/
93+
public function getItems() : array;
94+
EOF;
95+
96+
$this->assertSame($expectedOutput, $this->printer->prettyPrintFile([$method->generate()]));
97+
}
98+
5599
/**
56100
* @test
57101
*/
@@ -72,7 +116,7 @@ public function it_generates_method_with_doc_block_comment_if_typed(): void
72116
/**
73117
* Sets an awesome type
74118
*
75-
* @var string|null $type
119+
* @param string|null $type
76120
*/
77121
public function setType(?string $type);
78122
EOF;
@@ -83,14 +127,15 @@ public function setType(?string $type);
83127
/**
84128
* @test
85129
*/
86-
public function it_generates_method_with_doc_block(): void
130+
public function it_generates_method_with_doc_block_comment(): void
87131
{
88132
$method = new MethodGenerator(
89133
'setType',
90134
[
91135
new ParameterGenerator('type', '?string'),
92136
]
93137
);
138+
$method->setReturnType('void');
94139
$method->setDocBlockComment('Sets an awesome type');
95140
$method->setTyped(true);
96141

@@ -100,9 +145,10 @@ public function it_generates_method_with_doc_block(): void
100145
/**
101146
* Sets an awesome type
102147
*
103-
* @var string|null $type
148+
* @param string|null $type
149+
* @return void
104150
*/
105-
public function setType(?string $type);
151+
public function setType(?string $type) : void;
106152
EOF;
107153

108154
$this->assertSame($expectedOutput, $this->printer->prettyPrintFile([$method->generate()]));
@@ -119,15 +165,14 @@ public function it_generates_method_with_mixed_type_doc_block(): void
119165
new ParameterGenerator('type'),
120166
]
121167
);
122-
$method->setDocBlockComment('Sets an awesome type');
168+
$method->setReturnTypeDocBlockHint('mixed');
123169

124170
$expectedOutput = <<<'EOF'
125171
<?php
126172
127173
/**
128-
* Sets an awesome type
129-
*
130-
* @var mixed $type
174+
* @param mixed $type
175+
* @return mixed
131176
*/
132177
public function setType($type);
133178
EOF;
@@ -149,6 +194,7 @@ public function it_generates_method_with_array_type_doc_block(): void
149194
$parameter,
150195
]
151196
);
197+
$method->setReturnType('void');
152198
$method->setDocBlockComment('Sets awesome items');
153199

154200
$expectedOutput = <<<'EOF'
@@ -157,9 +203,10 @@ public function it_generates_method_with_array_type_doc_block(): void
157203
/**
158204
* Sets awesome items
159205
*
160-
* @var array<string, \stdClass> $items
206+
* @param array<string, \stdClass> $items
207+
* @return void
161208
*/
162-
public function setItems(array $items);
209+
public function setItems(array $items) : void;
163210
EOF;
164211

165212
$this->assertSame($expectedOutput, $this->printer->prettyPrintFile([$method->generate()]));
@@ -202,8 +249,8 @@ public function it_generates_method_with_long_doc_block(): void
202249
* It is a long established fact that a reader will be distracted by the readable content of a page when looking at
203250
* its layout.
204251
*
205-
* @var string $type
206-
* @var int|null $value
252+
* @param string $type
253+
* @param int|null $value
207254
*/
208255
public function setType(string $type, ?int $value);
209256
EOF;

0 commit comments

Comments
 (0)