Skip to content

Commit 652a9d2

Browse files
committed
Handle concatenation of static::class with string as callback
1 parent 8fcebb8 commit 652a9d2

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

src/Rules/Drupal/RenderCallbackRule.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use PHPStan\Type\Constant\ConstantArrayType;
1313
use PHPStan\Type\Constant\ConstantIntegerType;
1414
use PHPStan\Type\Constant\ConstantStringType;
15+
use PHPStan\Type\Generic\GenericClassStringType;
16+
use PHPStan\Type\IntersectionType;
1517
use PHPStan\Type\ObjectType;
1618
use PHPStan\Type\Type;
1719
use PHPStan\Type\UnionType;
@@ -120,10 +122,30 @@ public function processNode(Node $node, Scope $scope): array
120122
)->line($errorLine)->build();
121123
}
122124
}
123-
} else {
125+
} elseif ($type instanceof IntersectionType) {
126+
// Try to provide a tip for this weird occurrence.
127+
$tip = '';
128+
if ($item->value instanceof Node\Expr\BinaryOp\Concat) {
129+
$leftStringType = $scope->getType($item->value->left)->toString();
130+
$rightStringType = $scope->getType($item->value->right)->toString();
131+
if ($leftStringType instanceof GenericClassStringType && $rightStringType instanceof ConstantStringType) {
132+
$methodName = str_replace(':', '', $rightStringType->getValue());
133+
$tip = "Refactor concatenation of `static::class` with method name to an array callback: [static::class, '$methodName']";
134+
}
135+
}
136+
137+
if ($tip === '') {
138+
$tip = 'If this error is unexpected, open an issue with the error and sample code https://github.com/mglaman/phpstan-drupal/issues/new';
139+
}
140+
141+
$errors[] = RuleErrorBuilder::message(
142+
sprintf("%s value '%s' at key '%s' is invalid.", $keyChecked, $type->describe(VerbosityLevel::value()), $pos)
143+
)->line($errorLine)->tip($tip)->build();
144+
}else {
124145
$errors[] = RuleErrorBuilder::message(
125146
sprintf("%s value '%s' at key '%s' is invalid.", $keyChecked, $type->describe(VerbosityLevel::value()), $pos)
126-
)->line($errorLine)->build();
147+
)->line($errorLine)->tip('Open an issue https://github.com/mglaman/phpstan-drupal/issues/new with this error.')
148+
->build();
127149
}
128150
}
129151

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Drupal\pre_render_callback_rule;
4+
5+
use Drupal\Core\Security\TrustedCallbackInterface;
6+
use Drupal\Core\Url;
7+
8+
class LazyBuilderWithConstant implements TrustedCallbackInterface {
9+
10+
public function staticCallback(): array {
11+
return [
12+
'#lazy_builder' => [
13+
[[self::class, 'lazyBuilder'], ['baz', true]],
14+
[[static::class, 'lazyBuilder'], ['mars', false]],
15+
[[$this, 'lazyBuilder'], ['mars', false]],
16+
[self::class . '::lazyBuilder', ['baz', true]],
17+
[static::class . '::lazyBuilder', ['mars', false]],
18+
]
19+
];
20+
}
21+
22+
public static function lazyBuilder(string $foo, bool $bar) {
23+
return [
24+
'#markup' => "$foo $bar",
25+
];
26+
}
27+
28+
public static function trustedCallbacks()
29+
{
30+
return ['lazyBuilder'];
31+
}
32+
}

tests/fixtures/drupal/modules/pre_render_callback_rule/src/RenderArrayWithPreRenderCallback.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use Drupal\Core\Security\TrustedCallbackInterface;
66
use Drupal\Core\Url;
77

8-
final class RenderArrayWithPreRenderCallback implements TrustedCallbackInterface {
8+
class RenderArrayWithPreRenderCallback implements TrustedCallbackInterface {
99

1010
public function staticCallback(): array {
1111
return [
@@ -14,6 +14,9 @@ public function staticCallback(): array {
1414
'#title' => 'FooBar',
1515
'#pre_render' => [
1616
[self::class, 'preRenderCallback'],
17+
[static::class, 'preRenderCallback'],
18+
self::class . '::preRenderCallback',
19+
static::class . '::preRenderCallback',
1720
[$this, 'preRenderCallback'],
1821
static function(array $element): array {
1922
return $element;

tests/src/Rules/PreRenderCallbackRuleTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,13 @@ public function fileData(): \Generator
6565
];
6666
yield [
6767
__DIR__ . '/../../fixtures/drupal/modules/pre_render_callback_rule/src/RenderArrayWithPreRenderCallback.php',
68-
[]
68+
[
69+
[
70+
"#pre_render value 'non-empty-string' at key '3' is invalid.",
71+
19,
72+
"Refactor concatenation of `static::class` with method name to an array callback: [static::class, 'preRenderCallback']"
73+
]
74+
]
6975
];
7076
yield [
7177
__DIR__ . '/../../fixtures/drupal/modules/pre_render_callback_rule/src/RenderCallbackInterfaceObject.php',

0 commit comments

Comments
 (0)