Skip to content

Commit 11ee70e

Browse files
committed
Fix for handling non-stringable types in dynamic property access
1 parent 263be67 commit 11ee70e

File tree

5 files changed

+97
-4
lines changed

5 files changed

+97
-4
lines changed

src/Rules/Properties/AccessPropertiesCheck.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,20 @@ public function __construct(
4141
*/
4242
public function check(PropertyFetch $node, Scope $scope, bool $write): array
4343
{
44+
$errors = [];
4445
if ($node->name instanceof Identifier) {
4546
$names = [$node->name->name];
4647
} else {
47-
$names = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $scope->getType($node->name)->getConstantStrings());
48+
$fetchType = $scope->getType($node->name);
49+
$names = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $fetchType->getConstantStrings());
50+
$fetchStringType = $fetchType->toString();
51+
if (!$fetchStringType->isString()->yes()) {
52+
$errors[] = RuleErrorBuilder::message(sprintf('Cannot access property with a non-stringable type %s.', $fetchType->describe(VerbosityLevel::typeOnly())))
53+
->identifier('property.fetchInvalidExpression')
54+
->build();
55+
}
4856
}
4957

50-
$errors = [];
5158
foreach ($names as $name) {
5259
$errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name, $write));
5360
}

src/Rules/Properties/AccessStaticPropertiesRule.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,20 @@ public function getNodeType(): string
5151

5252
public function processNode(Node $node, Scope $scope): array
5353
{
54+
$errors = [];
5455
if ($node->name instanceof Node\VarLikeIdentifier) {
5556
$names = [$node->name->name];
5657
} else {
57-
$names = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $scope->getType($node->name)->getConstantStrings());
58+
$fetchType = $scope->getType($node->name);
59+
$names = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $fetchType->getConstantStrings());
60+
$fetchStringType = $fetchType->toString();
61+
if (!$fetchStringType->isString()->yes()) {
62+
$errors[] = RuleErrorBuilder::message(sprintf('Cannot access static property with a non-stringable type %s.', $fetchType->describe(VerbosityLevel::typeOnly())))
63+
->identifier('property.fetchInvalidExpression')
64+
->build();
65+
}
5866
}
5967

60-
$errors = [];
6168
foreach ($names as $name) {
6269
$errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name));
6370
}

tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,31 @@ public function testAccessPropertiesOnThisOnly(): void
344344
);
345345
}
346346

347+
public function testBug9475(): void
348+
{
349+
$this->checkThisOnly = false;
350+
$this->checkUnionTypes = false;
351+
$this->checkDynamicProperties = false;
352+
$this->analyse([__DIR__ . '/data/bug-9475.php'], [
353+
[
354+
'Cannot access property with a non-stringable type $this(Bug9475\Properties).',
355+
12,
356+
],
357+
[
358+
'Cannot access property with a non-stringable type $this(Bug9475\Properties).',
359+
13,
360+
],
361+
[
362+
'Cannot access property with a non-stringable type object.',
363+
14,
364+
],
365+
[
366+
'Cannot access property with a non-stringable type array.',
367+
15,
368+
],
369+
]);
370+
}
371+
347372
public function testBug12692(): void
348373
{
349374
$this->checkThisOnly = false;

tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php

+22
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,26 @@ public function testBug8333(): void
309309
]);
310310
}
311311

312+
public function testBug9475(): void
313+
{
314+
$this->analyse([__DIR__ . '/data/bug-9475.php'], [
315+
[
316+
'Cannot access static property with a non-stringable type $this(Bug9475\Properties).',
317+
23,
318+
],
319+
[
320+
'Cannot access static property with a non-stringable type $this(Bug9475\Properties).',
321+
24,
322+
],
323+
[
324+
'Cannot access static property with a non-stringable type object.',
325+
25,
326+
],
327+
[
328+
'Cannot access static property with a non-stringable type array.',
329+
26,
330+
],
331+
]);
332+
}
333+
312334
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug9475;
4+
5+
use Stringable;
6+
7+
final class Properties
8+
{
9+
10+
public function testProperties(string $name, Stringable $stringable, object $object, array $array): void
11+
{
12+
echo 'Hello, ' . $this->{$this}->name;
13+
echo 'Hello, ' . $this->$this->name;
14+
echo 'Hello, ' . $this->$object;
15+
echo 'Hello, ' . $this->$array;
16+
17+
echo 'Hello, ' . $this->$name; // valid
18+
echo 'Hello, ' . $this->$stringable; // valid
19+
}
20+
21+
public function testStaticProperties(string $name, Stringable $stringable, object $object, array $array): void
22+
{
23+
echo 'Hello, ' . self::${$this}->name;
24+
echo 'Hello, ' . self::$$this->name;
25+
echo 'Hello, ' . self::$$object;
26+
echo 'Hello, ' . self::$$array;
27+
28+
echo 'Hello, ' . self::$$name; // valid
29+
echo 'Hello, ' . self::$$stringable; // valid
30+
}
31+
32+
}

0 commit comments

Comments
 (0)