diff --git a/.psalm/baseline.xml b/.psalm/baseline.xml index b8ce67f..facfcc4 100644 --- a/.psalm/baseline.xml +++ b/.psalm/baseline.xml @@ -11,5 +11,9 @@ $hash $key + + $value->name + $value->value + diff --git a/composer.json b/composer.json index 58cbb24..0c328ff 100644 --- a/composer.json +++ b/composer.json @@ -48,6 +48,11 @@ "src/" ] }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, "extra": { "branch-alias": { "dev-master": "5.0-dev" diff --git a/src/Exporter.php b/src/Exporter.php index 664d2ff..8c1a4de 100644 --- a/src/Exporter.php +++ b/src/Exporter.php @@ -15,6 +15,7 @@ use function get_class; use function get_resource_type; use function gettype; use function implode; +use function interface_exists; use function is_array; use function is_float; use function is_object; @@ -28,8 +29,10 @@ use function sprintf; use function str_repeat; use function str_replace; use function var_export; +use BackedEnum; use SebastianBergmann\RecursionContext\Context; use SplObjectStorage; +use UnitEnum; /** * A nifty utility for visualizing PHP variables. @@ -115,6 +118,26 @@ final class Exporter return $string; } + // FIXME: Remove 'interface_exists' check once we drop support for PHP 8.0 + if (interface_exists('\UnitEnum')) { + if ($value instanceof BackedEnum) { + return sprintf( + '%s Enum (%s, %s)', + get_class($value), + $value->name, + $this->export($value->value) + ); + } + + if ($value instanceof UnitEnum) { + return sprintf( + '%s Enum (%s)', + get_class($value), + $value->name + ); + } + } + if (is_object($value)) { return sprintf( '%s Object (%s)', @@ -217,6 +240,28 @@ final class Exporter ); } + // FIXME: Remove 'interface_exists' check once we drop support for PHP 8.0 + if (interface_exists('\UnitEnum')) { + if ($value instanceof BackedEnum) { + return sprintf( + '%s Enum #%d (%s, %s)', + get_class($value), + spl_object_id($value), + $value->name, + $this->export($value->value, $indentation) + ); + } + + if ($value instanceof UnitEnum) { + return sprintf( + '%s Enum #%d (%s)', + get_class($value), + spl_object_id($value), + $value->name + ); + } + } + if (is_string($value)) { // Match for most non printable chars somewhat taking multibyte chars into account if (preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) { diff --git a/tests/ExampleEnum.php b/tests/ExampleEnum.php new file mode 100644 index 0000000..b55e1ae --- /dev/null +++ b/tests/ExampleEnum.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Exporter; + +/* + * Helper to test export of enums. + */ +enum ExampleEnum +{ + case Value; +} diff --git a/tests/ExampleIntegerBackedEnum.php b/tests/ExampleIntegerBackedEnum.php new file mode 100644 index 0000000..fbd85c9 --- /dev/null +++ b/tests/ExampleIntegerBackedEnum.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Exporter; + +/* + * Helper to test export of backed enums. + */ +enum ExampleIntegerBackedEnum: int +{ + case Value = 0; +} diff --git a/tests/ExampleStringBackedEnum.php b/tests/ExampleStringBackedEnum.php new file mode 100644 index 0000000..2583a52 --- /dev/null +++ b/tests/ExampleStringBackedEnum.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Exporter; + +/* + * Helper to test export of backed enums. + */ +enum ExampleStringBackedEnum: string +{ + case Value = 'value'; +} diff --git a/tests/ExporterTest.php b/tests/ExporterTest.php index 52ac23f..0ff3520 100644 --- a/tests/ExporterTest.php +++ b/tests/ExporterTest.php @@ -365,6 +365,50 @@ EOF; mb_language($oldMbLanguage); } + public function enumProvider() + { + return [ + 'export enum' => [ExampleEnum::Value, 'SebastianBergmann\Exporter\ExampleEnum Enum #%d (Value)'], + 'export backed enum' => [ExampleStringBackedEnum::Value, 'SebastianBergmann\Exporter\ExampleStringBackedEnum Enum #%d (Value, \'value\')'], + 'shortened export integer backed enum' => [ExampleIntegerBackedEnum::Value, 'SebastianBergmann\Exporter\ExampleIntegerBackedEnum Enum #%d (Value, 0)'], + ]; + } + + /** + * @requires PHP 8.1 + * @dataProvider enumProvider + */ + public function testEnumExport($value, $expected): void + { + // FIXME: Merge test into testExport once we drop support for PHP 8.0 + $this->assertStringMatchesFormat( + $expected, + $this->trimNewline($this->exporter->export($value)) + ); + } + + public function enumShortenedProvider() + { + return [ + 'shortened export enum' => [ExampleEnum::Value, 'SebastianBergmann\Exporter\ExampleEnum Enum (Value)'], + 'shortened export string backed enum' => [ExampleStringBackedEnum::Value, 'SebastianBergmann\Exporter\ExampleStringBackedEnum Enum (Value, \'value\')'], + 'shortened export integer backed enum' => [ExampleIntegerBackedEnum::Value, 'SebastianBergmann\Exporter\ExampleIntegerBackedEnum Enum (Value, 0)'], + ]; + } + + /** + * @requires PHP 8.1 + * @dataProvider enumShortenedProvider + */ + public function testEnumShortenedExport($value, $expected): void + { + // FIXME: Merge test into testShortenedExport once we drop support for PHP 8.0 + $this->assertStringMatchesFormat( + $expected, + $this->trimNewline($this->exporter->shortenedExport($value)) + ); + } + public function provideNonBinaryMultibyteStrings(): array { return [