19
19
use PHPStan \Type \Generic \GenericClassStringType ;
20
20
use PHPStan \Type \IntersectionType ;
21
21
use PHPStan \Type \ObjectType ;
22
+ use PHPStan \Type \StaticType ;
22
23
use PHPStan \Type \ThisType ;
23
24
use PHPStan \Type \Type ;
24
25
use PHPStan \Type \UnionType ;
@@ -149,6 +150,12 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
149
150
->tip ('Change record: https://www.drupal.org/node/2966725. ' )
150
151
->build ();
151
152
}
153
+
154
+ if (!$ trustedCallbackType ->isSuperTypeOf ($ type )->yes ()) {
155
+ return RuleErrorBuilder::message (
156
+ sprintf ("%s callback class %s at key '%s' does not implement Drupal\Core\Security\TrustedCallbackInterface. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
157
+ )->line ($ errorLine )->tip ('Change record: https://www.drupal.org/node/2966725. ' )->build ();
158
+ }
152
159
} elseif ($ type instanceof ConstantArrayType) {
153
160
if (!$ type ->isCallable ()->yes ()) {
154
161
return RuleErrorBuilder::message (
@@ -185,25 +192,6 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
185
192
sprintf ("%s callback %s at key '%s' is not callable. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
186
193
)->line ($ errorLine )->build ();
187
194
}
188
- } elseif ($ type instanceof IntersectionType) {
189
- // Try to provide a tip for this weird occurrence.
190
- $ tip = '' ;
191
- if ($ node instanceof Node \Expr \BinaryOp \Concat) {
192
- $ leftStringType = $ scope ->getType ($ node ->left )->toString ();
193
- $ rightStringType = $ scope ->getType ($ node ->right )->toString ();
194
- if ($ leftStringType instanceof GenericClassStringType && $ rightStringType instanceof ConstantStringType) {
195
- $ methodName = str_replace (': ' , '' , $ rightStringType ->getValue ());
196
- $ tip = "Refactor concatenation of `static::class` with method name to an array callback: [static::class, ' $ methodName'] " ;
197
- }
198
- }
199
-
200
- if ($ tip === '' ) {
201
- $ tip = 'If this error is unexpected, open an issue with the error and sample code https://github.com/mglaman/phpstan-drupal/issues/new ' ;
202
- }
203
-
204
- return RuleErrorBuilder::message (
205
- sprintf ("%s value '%s' at key '%s' is invalid. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
206
- )->line ($ errorLine )->tip ($ tip )->build ();
207
195
} else {
208
196
return RuleErrorBuilder::message (
209
197
sprintf ("%s value '%s' at key '%s' is invalid. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
@@ -217,7 +205,22 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
217
205
private function getType (Node \Expr $ node , Scope $ scope ): Type
218
206
{
219
207
$ type = $ scope ->getType ($ node );
220
- if ($ type instanceof ConstantStringType) {
208
+ if ($ type instanceof IntersectionType) {
209
+ // Covers concatenation of static::class . '::methodName'.
210
+ if ($ node instanceof Node \Expr \BinaryOp \Concat) {
211
+ $ leftType = $ scope ->getType ($ node ->left );
212
+ $ rightType = $ scope ->getType ($ node ->right );
213
+ if ($ rightType instanceof ConstantStringType && $ leftType instanceof GenericClassStringType && $ leftType ->getGenericType () instanceof StaticType) {
214
+ return new ConstantArrayType (
215
+ [new ConstantIntegerType (0 ), new ConstantIntegerType (1 )],
216
+ [
217
+ $ leftType ->getGenericType (),
218
+ new ConstantStringType (ltrim ($ rightType ->getValue (), ': ' ))
219
+ ]
220
+ );
221
+ }
222
+ }
223
+ } elseif ($ type instanceof ConstantStringType) {
221
224
if ($ type ->isClassString ()) {
222
225
return $ type ;
223
226
}
@@ -243,7 +246,7 @@ private function getType(Node\Expr $node, Scope $scope): Type
243
246
return new ConstantArrayType (
244
247
[new ConstantIntegerType (0 ), new ConstantIntegerType (1 )],
245
248
[
246
- new ConstantStringType ( $ matches [1 ], true ),
249
+ new StaticType ( $ this -> reflectionProvider -> getClass ( $ matches [1 ]) ),
247
250
new ConstantStringType ($ matches [2 ])
248
251
]
249
252
);
0 commit comments