Skip to content

Commit f3b6446

Browse files
committed
Fixed wrapping bugs
1 parent 727d829 commit f3b6446

File tree

10 files changed

+288
-27
lines changed

10 files changed

+288
-27
lines changed

src/Formatter/Object_/PublicVariableFormatter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ protected function getPropertySequenceAsString(CasterInterface $caster, object $
110110
$segment = $caster->getWrappingIndentationCharacters() . $segment;
111111
});
112112

113-
return implode("\n,", $segments);
113+
return implode(",\n", $segments);
114114
}
115115

116116
return implode(', ', $segments);

src/Formatter/Object_/ReflectionAttributeFormatter.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66

77
use Eboreum\Caster\Abstraction\Formatter\AbstractObjectFormatter;
88
use Eboreum\Caster\Caster;
9+
use Eboreum\Caster\Common\DataType\Integer\PositiveInteger;
910
use Eboreum\Caster\Contract\CasterInterface;
1011
use ReflectionAttribute;
1112
use ReflectionClass;
1213
use ReflectionMethod;
1314
use ReflectionParameter;
1415
use SensitiveParameter;
1516

17+
use function array_map;
1618
use function assert;
1719
use function implode;
1820
use function is_string;
@@ -52,6 +54,10 @@ public function format(CasterInterface $caster, object $object): ?string
5254
/** @var array<string> $argumentsAsStrings */
5355
$argumentsAsStrings = [];
5456

57+
$casterInner = $caster->withDepthCurrent(
58+
new PositiveInteger($caster->getDepthCurrent()->toInteger() + 1)
59+
);
60+
5561
foreach ($object->getArguments() as $key => $value) {
5662
/** @var bool $isSensitive */
5763
$isSensitive = false;
@@ -81,19 +87,30 @@ public function format(CasterInterface $caster, object $object): ?string
8187
$argumentsAsStrings[] = sprintf(
8288
'%s: %s',
8389
$key,
84-
$caster->getSensitiveMessage(),
90+
$casterInner->getSensitiveMessage(),
8591
);
8692
} else {
8793
$argumentsAsStrings[] = sprintf(
8894
'%s: %s',
8995
$key,
90-
$caster->cast($value),
96+
$casterInner->cast($value),
9197
);
9298
}
9399
}
94100

95101
if ($argumentsAsStrings) {
96-
$str .= sprintf(' (%s)', implode(', ', $argumentsAsStrings));
102+
if ($caster->isWrapping()) {
103+
$argumentsAsStrings = array_map(
104+
static function (string $argument) use ($caster): string {
105+
return $caster->getWrappingIndentationCharacters() . $argument;
106+
},
107+
$argumentsAsStrings,
108+
);
109+
110+
$str .= sprintf(" (\n%s\n)", implode(",\n", $argumentsAsStrings));
111+
} else {
112+
$str .= sprintf(' (%s)', implode(', ', $argumentsAsStrings));
113+
}
97114
}
98115

99116
if ($this->isWrappingInClassName()) {

tests/phpunit.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
colors="true"
77
cacheDirectory=".phpunit.cache"
88
requireCoverageMetadata="true"
9+
beStrictAboutCoverageMetadata="false"
10+
beStrictAboutOutputDuringTests="true"
11+
failOnRisky="true"
12+
failOnWarning="true"
13+
displayDetailsOnIncompleteTests="true"
14+
displayDetailsOnSkippedTests="true"
15+
displayDetailsOnTestsThatTriggerDeprecations="true"
16+
displayDetailsOnTestsThatTriggerErrors="true"
17+
displayDetailsOnTestsThatTriggerNotices="true"
18+
displayDetailsOnTestsThatTriggerWarnings="true"
919
>
1020
<testsuites>
1121
<testsuite name="Integration test suite">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TestResource\Unit\Eboreum\Caster\Formatter\Object_\ReflectionAttributeFormatterTest\testFormatWorksWhenWrapping; // phpcs:ignore
6+
7+
use Attribute;
8+
9+
#[Attribute]
10+
class Attribute5d7fcf99144f4ad19f4c0ddbcc504127
11+
{
12+
public readonly string $foo;
13+
14+
/** @var array<int> */
15+
public readonly array $bar;
16+
17+
/**
18+
* @param array<int> $bar
19+
*/
20+
public function __construct(string $foo, array $bar)
21+
{
22+
$this->foo = $foo;
23+
$this->bar = $bar;
24+
}
25+
}

tests/tests/Test/Unit/Formatter/Object_/DateIntervalFormatterTest.php

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
use PHPUnit\Framework\TestCase;
1212
use stdClass;
1313

14+
use function array_map;
1415
use function implode;
16+
use function preg_quote;
17+
use function sprintf;
1518

1619
#[CoversClass(DateIntervalFormatter::class)]
1720
class DateIntervalFormatterTest extends TestCase
@@ -26,7 +29,7 @@ public function testFormatReturnsNullWhenObjectIsNotQualified(): void
2629
$this->assertNull($dateIntervalFormatter->format($caster, $object));
2730
}
2831

29-
public function testFormatWorks(): void
32+
public function testFormatWorksWithoutWrapping(): void
3033
{
3134
$caster = Caster::create();
3235
$dateIntervalFormatter = new DateIntervalFormatter();
@@ -52,33 +55,56 @@ public function testFormatWorks(): void
5255
', \$i = 34',
5356
', \$s = 56',
5457
', \$f = 0',
55-
// The following group exists only up until in PHP 8.1, but was removed in PHP 8.2.
56-
'(',
57-
', \$weekday = 0',
58-
', \$weekday_behavior = 0',
59-
', \$first_last_day_of = 0',
60-
')?',
6158
', \$invert = 0',
6259
', \$days = 33',
63-
'(',
64-
// This first group matches PHP 8.1.
65-
'(',
66-
', \$special_type = 0',
67-
', \$special_amount = 0',
68-
', \$have_weekday_relative = 0',
69-
', \$have_special_relative = 0',
70-
')',
71-
'|',
72-
// This second group matches PHP 8.2+.
73-
'(',
74-
', \$from_string = false',
75-
')',
76-
')',
60+
', \$from_string = false',
7761
'\}',
7862
'$',
7963
'/',
8064
]),
8165
$formatted,
8266
);
8367
}
68+
69+
public function testFormatWorksWithWrapping(): void
70+
{
71+
$caster = Caster::create()->withIsWrapping(true);
72+
$dateIntervalFormatter = new DateIntervalFormatter();
73+
74+
$object = (new DateTimeImmutable('2021-01-01T00:00:00+00:00'))->diff(
75+
new DateTimeImmutable('2021-02-03T12:34:56+00:00')
76+
);
77+
78+
$this->assertTrue($dateIntervalFormatter->isHandling($object));
79+
80+
$formatted = $dateIntervalFormatter->format($caster, $object);
81+
82+
$this->assertIsString($formatted);
83+
$this->assertMatchesRegularExpression(
84+
sprintf(
85+
'/^\\\\DateInterval \{\n%s\n\}$/',
86+
implode(
87+
"\n",
88+
array_map(
89+
static function (string $str) use ($caster): string {
90+
return preg_quote($caster->getWrappingIndentationCharacters() . $str, '/');
91+
},
92+
[
93+
'$y = 0,',
94+
'$m = 1,',
95+
'$d = 2,',
96+
'$h = 12,',
97+
'$i = 34,',
98+
'$s = 56,',
99+
'$f = 0,',
100+
'$invert = 0,',
101+
'$days = 33,',
102+
'$from_string = false',
103+
],
104+
),
105+
),
106+
),
107+
$formatted,
108+
);
109+
}
84110
}

tests/tests/Test/Unit/Formatter/Object_/DebugInfoFormatterTest.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function testFormatReturnsNullWhenObjectIsNotQualified(): void
3030
$this->assertNull($debugInfoFormatter->format($caster, $object));
3131
}
3232

33-
public function testFormatWorks(): void
33+
public function testFormatWorksWithoutWrapping(): void
3434
{
3535
$caster = Caster::create();
3636
$debugInfoFormatter = new DebugInfoFormatter();
@@ -65,4 +65,40 @@ public function __debugInfo(): array
6565
$formatted,
6666
);
6767
}
68+
69+
public function testFormatWorksWithWrapping(): void
70+
{
71+
$caster = Caster::create()->withIsWrapping(true);
72+
$debugInfoFormatter = new DebugInfoFormatter();
73+
74+
$object = new class
75+
{
76+
/**
77+
* @return array<string, string>
78+
*/
79+
public function __debugInfo(): array
80+
{
81+
return ['foo' => 'bar'];
82+
}
83+
};
84+
85+
$this->assertTrue($debugInfoFormatter->isHandling($object));
86+
$formatted = $debugInfoFormatter->format($caster, $object);
87+
$this->assertIsString($formatted);
88+
$this->assertMatchesRegularExpression(
89+
sprintf(
90+
implode('', [
91+
'/',
92+
'^',
93+
'class@anonymous\/in\/.+\/%s\:\d+ \(\[\n',
94+
' "foo" \=\> "bar"\n',
95+
'\]\)',
96+
'$',
97+
'/',
98+
]),
99+
preg_quote(basename(__FILE__), '/'),
100+
),
101+
$formatted,
102+
);
103+
}
68104
}

tests/tests/Test/Unit/Formatter/Object_/PublicVariableFormatterTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ public function testFormatWorksWhenWrapping(): void
227227
{
228228
public readonly object $foo;
229229

230+
public int $bar = 42;
231+
230232
public function __construct()
231233
{
232234
$this->foo = new class
@@ -242,7 +244,8 @@ public function __construct()
242244
sprintf(
243245
implode("\n", [
244246
'%s {',
245-
' $foo = %s',
247+
' $foo = %s,',
248+
' $bar = 42',
246249
'}',
247250
]),
248251
Caster::makeNormalizedClassName(new ReflectionObject($object)),

tests/tests/Test/Unit/Formatter/Object_/ReflectionAttributeFormatterTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use ReflectionProperty;
1515
use stdClass;
1616
// phpcs:disable
17+
use TestResource\Unit\Eboreum\Caster\Formatter\Object_\ReflectionAttributeFormatterTest\testFormatWorksWhenWrapping\Attribute5d7fcf99144f4ad19f4c0ddbcc504127;
1718
use TestResource\Unit\Eboreum\Caster\Formatter\Object_\ReflectionAttributeFormatterTest\testFormatWorksWithAReflectionAttributeWithIntegerIndexedArguments\Attributeda304392c18711edafa10242ac120002;
1819
use TestResource\Unit\Eboreum\Caster\Formatter\Object_\ReflectionAttributeFormatterTest\testFormatWorksWithAReflectionAttributeWithIntegerIndexedArguments\Classda304392c18711edafa10242ac120002;
1920
use TestResource\Unit\Eboreum\Caster\Formatter\Object_\ReflectionAttributeFormatterTest\testFormatWorksWithAReflectionAttributeWithoutArguments\Attributeda304090c18711edafa10242ac120002;
@@ -196,6 +197,47 @@ public function testFormatWorksWithASensitiveNamedArgument(): void
196197
);
197198
}
198199

200+
public function testFormatWorksWhenWrapping(): void
201+
{
202+
$caster = Caster::create()->withIsWrapping(true);
203+
$reflectionAttributeFormatter = new ReflectionAttributeFormatter();
204+
205+
$object = new class
206+
{
207+
#[Attribute5d7fcf99144f4ad19f4c0ddbcc504127(foo: 'lorem', bar: [42])]
208+
// @phpstan-ignore-next-line
209+
private int $lorem = 42;
210+
};
211+
212+
$reflectionProperty = new ReflectionProperty($object, 'lorem');
213+
214+
/** @var ReflectionAttribute<Attribute5d7fcf99144f4ad19f4c0ddbcc504127>|null $reflectionAttribute */
215+
$reflectionAttribute = (
216+
$reflectionProperty->getAttributes(Attribute5d7fcf99144f4ad19f4c0ddbcc504127::class)[0] ?? null
217+
);
218+
219+
$this->assertIsObject($reflectionAttribute);
220+
221+
$this->assertTrue($reflectionAttributeFormatter->isHandling($reflectionAttribute));
222+
$this->assertSame(
223+
sprintf(
224+
implode(
225+
"\n",
226+
[
227+
'\\ReflectionAttribute (\\%s (',
228+
' foo: "lorem",',
229+
' bar: [',
230+
' 0 => 42',
231+
' ]',
232+
'))',
233+
],
234+
),
235+
Attribute5d7fcf99144f4ad19f4c0ddbcc504127::class,
236+
),
237+
$reflectionAttributeFormatter->format($caster, $reflectionAttribute),
238+
);
239+
}
240+
199241
public function testWithIsWrappingInClassNameWorks(): void
200242
{
201243
$reflectionAttributeFormatterA = new ReflectionAttributeFormatter();

tests/tests/Test/Unit/Formatter/Object_/ReflectionParameterFormatterTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,56 @@ public function testFormatWorksForMethodParameters(
270270
$this->assertMatchesRegularExpression($expectedRegex, $formatted, $message);
271271
}
272272

273+
public function testFormatWorksWhenWrapping(): void
274+
{
275+
$caster = Caster::create()->withIsWrapping(true);
276+
$reflectionParameterFormatter = new ReflectionParameterFormatter();
277+
$reflectionParameter = $this->createMock(ReflectionParameter::class);
278+
279+
$reflectionParameter
280+
->expects($this->exactly(2))
281+
->method('isDefaultValueAvailable')
282+
->with()
283+
->willReturn(true);
284+
285+
$reflectionParameter
286+
->expects($this->once())
287+
->method('isDefaultValueConstant')
288+
->with()
289+
->willReturn(false);
290+
291+
$reflectionParameter
292+
->expects($this->once())
293+
->method('getDefaultValue')
294+
->with()
295+
->willReturn(['bar' => [42]]);
296+
297+
$reflectionParameter
298+
->expects($this->any())
299+
->method('getName')
300+
->with()
301+
->willReturn('foo');
302+
303+
$formatted = $reflectionParameterFormatter->format($caster, $reflectionParameter);
304+
305+
$this->assertSame(
306+
sprintf(
307+
implode(
308+
"\n",
309+
[
310+
'%s ($foo = [',
311+
' "bar" => [',
312+
' 0 => 42',
313+
' ]',
314+
'])',
315+
],
316+
),
317+
Caster::makeNormalizedClassName(new ReflectionObject($reflectionParameter)),
318+
),
319+
$formatted,
320+
);
321+
}
322+
273323
public function testFormatDefaultValueThrowsExceptionWhenNoDefaultValueIsAvailableOnFunction(): void
274324
{
275325
$caster = Caster::create();

0 commit comments

Comments
 (0)