diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 1b770d6889..799fd3d145 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1476,7 +1476,7 @@ public function describe(VerbosityLevel $level): string if (is_string($keyDescription)) { if (str_contains($keyDescription, '"')) { $keyDescription = sprintf('\'%s\'', $keyDescription); - } elseif (str_contains($keyDescription, '\'')) { + } else { $keyDescription = sprintf('"%s"', $keyDescription); } } diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php index 2d1aaa237c..5e3ef24b35 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeBuilderTest.php @@ -5,6 +5,7 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\NullType; use PHPStan\Type\StringType; +use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\VerbosityLevel; use PHPUnit\Framework\TestCase; @@ -162,4 +163,38 @@ public function testIsListWithUnion(): void $this->assertFalse($builder->isList()); } + public function dataQuotedOffsetNames(): iterable + { + yield [ + 'array{"count(*)": 1}', + new ConstantStringType('count(*)'), + new ConstantIntegerType(1), + ]; + + yield [ + "array{'cou\"nt(*)': 1}", + new ConstantStringType('cou"nt(*)'), + new ConstantIntegerType(1), + ]; + + yield [ + 'array{"count\'ed": 1}', + new ConstantStringType("count'ed"), + new ConstantIntegerType(1), + ]; + } + + /** + * @dataProvider dataQuotedOffsetNames + */ + public function testQuotedOffsetNames(string $expectedDescription, Type $key, Type $value): void + { + $builder = ConstantArrayTypeBuilder::createEmpty(); + $builder->setOffsetValueType($key, $value); + + $array1 = $builder->getArray(); + $this->assertInstanceOf(ConstantArrayType::class, $array1); + $this->assertSame($expectedDescription, $array1->describe(VerbosityLevel::precise())); + } + }