9
9
use Pepakriz \PHPStanExceptionRules \CheckedExceptionService ;
10
10
use Pepakriz \PHPStanExceptionRules \DefaultThrowTypeService ;
11
11
use Pepakriz \PHPStanExceptionRules \DynamicThrowTypeService ;
12
- use Pepakriz \PHPStanExceptionRules \Node \FunctionEnd ;
13
12
use Pepakriz \PHPStanExceptionRules \Node \TryCatchTryEnd ;
14
13
use Pepakriz \PHPStanExceptionRules \ThrowsAnnotationReader ;
15
14
use Pepakriz \PHPStanExceptionRules \UnsupportedClassException ;
32
31
use PHPStan \Broker \Broker ;
33
32
use PHPStan \Broker \ClassNotFoundException ;
34
33
use PHPStan \Broker \FunctionNotFoundException ;
34
+ use PHPStan \Node \FunctionReturnStatementsNode ;
35
+ use PHPStan \Node \MethodReturnStatementsNode ;
35
36
use PHPStan \Node \UnreachableStatementNode ;
36
37
use PHPStan \Reflection \MethodReflection ;
37
38
use PHPStan \Reflection \MissingMethodFromReflectionException ;
38
39
use PHPStan \Rules \Rule ;
40
+ use PHPStan \Rules \RuleError ;
41
+ use PHPStan \Rules \RuleErrorBuilder ;
39
42
use PHPStan \ShouldNotHappenException ;
40
43
use PHPStan \Type \NeverType ;
41
44
use PHPStan \Type \ObjectType ;
@@ -157,7 +160,7 @@ public function getNodeType(): string
157
160
}
158
161
159
162
/**
160
- * @return string []
163
+ * @return RuleError []
161
164
*/
162
165
public function processNode (Node $ node , Scope $ scope ): array
163
166
{
@@ -171,12 +174,16 @@ public function processNode(Node $node, Scope $scope): array
171
174
172
175
$ method = $ scope ->getFunction ();
173
176
$ isMethodWhitelisted = $ method instanceof MethodReflection && $ this ->isWhitelistedMethod ($ method );
174
- if ($ node instanceof FunctionEnd ) {
177
+ if ($ node instanceof MethodReturnStatementsNode ) {
175
178
if ($ isMethodWhitelisted && $ method instanceof MethodReflection) {
176
- return $ this ->processWhitelistedMethod ($ method );
179
+ return $ this ->processWhitelistedMethod ($ method, $ node -> getStartLine () );
177
180
}
178
181
179
- return $ this ->processFunctionEnd ($ scope );
182
+ return $ this ->processFunctionEnd ($ scope , $ node ->getStartLine ());
183
+ }
184
+
185
+ if ($ node instanceof FunctionReturnStatementsNode) {
186
+ return $ this ->processFunctionEnd ($ scope , $ node ->getStartLine ());
180
187
}
181
188
182
189
if ($ isMethodWhitelisted ) {
@@ -243,9 +250,9 @@ public function processNode(Node $node, Scope $scope): array
243
250
}
244
251
245
252
/**
246
- * @return string []
253
+ * @return RuleError []
247
254
*/
248
- private function processWhitelistedMethod (MethodReflection $ methodReflection ): array
255
+ private function processWhitelistedMethod (MethodReflection $ methodReflection, int $ startLine ): array
249
256
{
250
257
$ throwType = $ methodReflection ->getThrowType ();
251
258
@@ -254,8 +261,10 @@ private function processWhitelistedMethod(MethodReflection $methodReflection): a
254
261
}
255
262
256
263
return array_map (
257
- static function (string $ throwClass ): string {
258
- return sprintf ('Unused @throws %s annotation ' , $ throwClass );
264
+ static function (string $ throwClass ) use ($ startLine ): RuleError {
265
+ return RuleErrorBuilder::message (sprintf ('Unused @throws %s annotation ' , $ throwClass ))
266
+ ->line ($ startLine )
267
+ ->build ();
259
268
},
260
269
TypeUtils::getDirectClassNames ($ throwType )
261
270
);
@@ -279,7 +288,7 @@ private function isWhitelistedMethod(MethodReflection $methodReflection): bool
279
288
}
280
289
281
290
/**
282
- * @return string []
291
+ * @return RuleError []
283
292
*/
284
293
private function processTryCatch (TryCatch $ node ): array
285
294
{
@@ -294,7 +303,7 @@ private function processTryCatch(TryCatch $node): array
294
303
}
295
304
296
305
/**
297
- * @return string []
306
+ * @return RuleError []
298
307
*/
299
308
private function processTryCatchTryEnd (): array
300
309
{
@@ -304,7 +313,7 @@ private function processTryCatchTryEnd(): array
304
313
}
305
314
306
315
/**
307
- * @return string []
316
+ * @return RuleError []
308
317
*/
309
318
private function processThrow (Throw_ $ node , Scope $ scope ): array
310
319
{
@@ -314,7 +323,7 @@ private function processThrow(Throw_ $node, Scope $scope): array
314
323
}
315
324
316
325
/**
317
- * @return string []
326
+ * @return RuleError []
318
327
*/
319
328
private function processMethodCall (MethodCall $ node , Scope $ scope ): array
320
329
{
@@ -360,7 +369,7 @@ private function processMethodCall(MethodCall $node, Scope $scope): array
360
369
}
361
370
362
371
/**
363
- * @return string []
372
+ * @return RuleError []
364
373
*/
365
374
private function processStaticCall (StaticCall $ node , Scope $ scope ): array
366
375
{
@@ -397,7 +406,7 @@ private function processStaticCall(StaticCall $node, Scope $scope): array
397
406
}
398
407
399
408
/**
400
- * @return string []
409
+ * @return RuleError []
401
410
*/
402
411
private function processNew (New_ $ node , Scope $ scope ): array
403
412
{
@@ -420,7 +429,7 @@ private function processNew(New_ $node, Scope $scope): array
420
429
}
421
430
422
431
/**
423
- * @return string []
432
+ * @return RuleError []
424
433
*/
425
434
private function processExprTraversing (Expr $ expr , Scope $ scope , bool $ useKey ): array
426
435
{
@@ -454,7 +463,7 @@ private function processExprTraversing(Expr $expr, Scope $scope, bool $useKey):
454
463
}
455
464
456
465
/**
457
- * @return string []
466
+ * @return RuleError []
458
467
*/
459
468
private function processFunction (Node \FunctionLike $ node , Scope $ scope ): array
460
469
{
@@ -492,19 +501,15 @@ private function processFunction(Node\FunctionLike $node, Scope $scope): array
492
501
493
502
if (!$ node ->hasAttribute (self ::ATTRIBUTE_HAS_CLASS_METHOD_END )) {
494
503
$ node ->setAttribute (self ::ATTRIBUTE_HAS_CLASS_METHOD_END , true );
495
- if ($ node ->stmts === null ) {
496
- throw new ShouldNotHappenException ();
497
- }
498
- $ node ->stmts [] = new FunctionEnd ($ node );
499
504
}
500
505
501
506
return [];
502
507
}
503
508
504
509
/**
505
- * @return string []
510
+ * @return RuleError []
506
511
*/
507
- private function processFunctionEnd (Scope $ scope ): array
512
+ private function processFunctionEnd (Scope $ scope, int $ startLine ): array
508
513
{
509
514
$ usedThrowsAnnotations = $ this ->throwsScope ->exitFromThrowsAnnotationBlock ();
510
515
@@ -528,7 +533,9 @@ private function processFunctionEnd(Scope $scope): array
528
533
529
534
$ messages = [];
530
535
foreach ($ unusedThrows as $ unusedClass ) {
531
- $ messages [] = sprintf ('Unused @throws %s annotation ' , $ unusedClass );
536
+ $ messages [] = RuleErrorBuilder::message (sprintf ('Unused @throws %s annotation ' , $ unusedClass ))
537
+ ->line ($ startLine )
538
+ ->build ();
532
539
}
533
540
534
541
return $ messages ;
@@ -603,7 +610,7 @@ private function isImplementation(ReflectionMethod $reflection): bool
603
610
}
604
611
605
612
/**
606
- * @return string []
613
+ * @return RuleError []
607
614
*/
608
615
private function processCatch (Catch_ $ node ): array
609
616
{
@@ -623,11 +630,11 @@ private function processCatch(Catch_ $node): array
623
630
624
631
if (!$ this ->checkedExceptionService ->isCheckedException ($ type ->toString ())) {
625
632
foreach ($ caughtChecked as $ caughtCheckedException ) {
626
- $ messages [] = sprintf (
633
+ $ messages [] = RuleErrorBuilder:: message ( sprintf (
627
634
'Catching checked exception %s as unchecked %s is not supported properly in this moment. Eliminate checked exceptions by custom catch statement. ' ,
628
635
$ caughtCheckedException ,
629
636
$ type ->toString ()
630
- );
637
+ ))-> build () ;
631
638
}
632
639
}
633
640
@@ -647,14 +654,14 @@ private function processCatch(Catch_ $node): array
647
654
continue ;
648
655
}
649
656
650
- $ messages [] = sprintf ('%s is never thrown in the corresponding try block ' , $ exceptionClass );
657
+ $ messages [] = RuleErrorBuilder:: message ( sprintf ('%s is never thrown in the corresponding try block ' , $ exceptionClass))-> build ( );
651
658
}
652
659
653
660
return $ messages ;
654
661
}
655
662
656
663
/**
657
- * @return string []
664
+ * @return RuleError []
658
665
*/
659
666
private function processFuncCall (FuncCall $ node , Scope $ scope ): array
660
667
{
@@ -699,7 +706,7 @@ private function processFuncCall(FuncCall $node, Scope $scope): array
699
706
}
700
707
701
708
/**
702
- * @return string []
709
+ * @return RuleError []
703
710
*/
704
711
private function processDiv (Expr $ divisor , Scope $ scope ): array
705
712
{
@@ -725,7 +732,7 @@ private function processDiv(Expr $divisor, Scope $scope): array
725
732
}
726
733
727
734
/**
728
- * @return string []
735
+ * @return RuleError []
729
736
*/
730
737
private function processShift (Expr $ value , Scope $ scope ): array
731
738
{
@@ -774,7 +781,7 @@ private function getThrowTypesOnMethod($class, array $methods, Scope $scope): ar
774
781
/**
775
782
* @param Name|Expr|ClassLike $class
776
783
* @param string[] $methods
777
- * @return string []
784
+ * @return RuleError []
778
785
*/
779
786
private function processThrowTypesOnMethod ($ class , array $ methods , Scope $ scope ): array
780
787
{
@@ -784,7 +791,7 @@ private function processThrowTypesOnMethod($class, array $methods, Scope $scope)
784
791
}
785
792
786
793
/**
787
- * @return string []
794
+ * @return RuleError []
788
795
*/
789
796
private function processThrowsTypes (Type $ targetThrowType ): array
790
797
{
@@ -797,12 +804,12 @@ private function processThrowsTypes(Type $targetThrowType): array
797
804
return [];
798
805
}
799
806
800
- return array_map (static function (string $ exceptionClassName ) use ($ isInGlobalScope ): string {
807
+ return array_map (static function (string $ exceptionClassName ) use ($ isInGlobalScope ): RuleError {
801
808
if ($ isInGlobalScope ) {
802
- return sprintf ('Throwing checked exception %s in global scope is prohibited ' , $ exceptionClassName );
809
+ return RuleErrorBuilder:: message ( sprintf ('Throwing checked exception %s in global scope is prohibited ' , $ exceptionClassName))-> build ( );
803
810
}
804
811
805
- return sprintf ('Missing @throws %s annotation ' , $ exceptionClassName );
812
+ return RuleErrorBuilder:: message ( sprintf ('Missing @throws %s annotation ' , $ exceptionClassName))-> build ( );
806
813
}, $ targetExceptionClasses );
807
814
}
808
815
0 commit comments