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 ;
@@ -185,25 +186,6 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
185
186
sprintf ("%s callback %s at key '%s' is not callable. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
186
187
)->line ($ errorLine )->build ();
187
188
}
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
189
} else {
208
190
return RuleErrorBuilder::message (
209
191
sprintf ("%s value '%s' at key '%s' is invalid. " , $ keyChecked , $ type ->describe (VerbosityLevel::value ()), $ pos )
@@ -217,7 +199,16 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
217
199
private function getType (Node \Expr $ node , Scope $ scope ): Type
218
200
{
219
201
$ type = $ scope ->getType ($ node );
220
- if ($ type instanceof ConstantStringType) {
202
+ if ($ type instanceof IntersectionType) {
203
+ // Covers concatenation of static::class . '::methodName'.
204
+ if ($ node instanceof Node \Expr \BinaryOp \Concat) {
205
+ $ leftType = $ scope ->getType ($ node ->left );
206
+ $ rightType = $ scope ->getType ($ node ->right );
207
+ if ($ leftType instanceof GenericClassStringType && $ leftType ->getGenericType () instanceof StaticType && $ rightType instanceof ConstantStringType) {
208
+ return new ConstantStringType ($ leftType ->getGenericType ()->getClassName () . $ rightType ->getValue ());
209
+ }
210
+ }
211
+ } elseif ($ type instanceof ConstantStringType) {
221
212
if ($ type ->isClassString ()) {
222
213
return $ type ;
223
214
}
0 commit comments