• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / phpstan-config / 22548915613

01 Mar 2026 05:43PM UTC coverage: 96.654% (-0.6%) from 97.276%
22548915613

push

github

web-flow
Merge pull request #131 from eliashaeussler/renovate/lock-file-maintenance

260 of 269 relevant lines covered (96.65%)

8.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.59
/src/Rule/IgnoreAnnotationWithoutErrorIdentifierRule.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/phpstan-config".
7
 *
8
 * Copyright (C) 2023-2026 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\PHPStanConfig\Rule;
25

26
use PhpParser\Node;
27
use PHPStan\Analyser;
28
use PHPStan\PhpDocParser;
29
use PHPStan\Rules;
30
use PHPStan\Type;
31

32
use function in_array;
33
use function preg_match;
34
use function sprintf;
35

36
/**
37
 * IgnoreAnnotationWithoutErrorIdentifierRule.
38
 *
39
 * @author Elias Häußler <elias@haeussler.dev>
40
 * @license GPL-3.0-or-later
41
 *
42
 * @implements CustomRule<Node\Stmt>
43
 */
44
final readonly class IgnoreAnnotationWithoutErrorIdentifierRule implements CustomRule
45
{
46
    /**
47
     * @param list<non-empty-string> $monitoredAnnotations
48
     */
49
    public function __construct(
3✔
50
        private Type\FileTypeMapper $fileTypeMapper,
51
        private array $monitoredAnnotations,
52
    ) {}
3✔
53

54
    public static function getIdentifier(): string
×
55
    {
56
        return 'ignoreAnnotationWithoutErrorIdentifier';
×
57
    }
58

59
    public function getNodeType(): string
3✔
60
    {
61
        return Node\Stmt::class;
3✔
62
    }
63

64
    public function processNode(Node $node, Analyser\Scope $scope): array
3✔
65
    {
66
        $errors = [];
3✔
67

68
        foreach ($node->getComments() as $comment) {
3✔
69
            $commentText = $comment->getText();
3✔
70

71
            // Convert inline comments to phpdoc to allow usage of phpdoc parser
72
            if (1 !== preg_match('#^/\*{2}#', $commentText)) {
3✔
73
                $commentText = '/** '.preg_replace(['#^(/\*|//)#', '#\*/$#'], '', $commentText).' */';
3✔
74
            }
75

76
            // Parse and resolve phpdoc
77
            $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
3✔
78
                $scope->getFile(),
3✔
79
                $scope->getClassReflection()?->getName(),
3✔
80
                $scope->getTraitReflection()?->getName(),
3✔
81
                $scope->getFunction()?->getName(),
3✔
82
                $commentText,
3✔
83
            );
3✔
84

85
            foreach ($resolvedPhpDoc->getPhpDocNodes() as $phpDocNode) {
3✔
86
                foreach ($phpDocNode->children as $phpDocChildNode) {
3✔
87
                    // We only check phpdoc tag nodes
88
                    if (!$phpDocChildNode instanceof PhpDocParser\Ast\PhpDoc\PhpDocTagNode) {
3✔
89
                        continue;
3✔
90
                    }
91

92
                    $name = ltrim($phpDocChildNode->name, '@');
3✔
93

94
                    // Add error if ignore annotation has no error identifier configured
95
                    if (in_array($name, $this->monitoredAnnotations, true) && '' === trim((string) $phpDocChildNode->value)) {
3✔
96
                        $errors[] = $this->createRuleError($name, $scope, $node);
1✔
97
                    }
98
                }
99
            }
100
        }
101

102
        return $errors;
3✔
103
    }
104

105
    /**
106
     * @return Rules\IdentifierRuleError
107
     */
108
    private function createRuleError(string $annotation, Analyser\Scope $scope, Node $node): Rules\RuleError
1✔
109
    {
110
        $ruleError = Rules\RuleErrorBuilder::message(
1✔
111
            sprintf('Using an @%s annotation without specifying an error identifier is not allowed.', $annotation),
1✔
112
        );
1✔
113

114
        return $ruleError
1✔
115
            ->identifier('ignoreAnnotation.withoutErrorIdentifier')
1✔
116
            ->tip('Read more at https://phpstan.org/user-guide/ignoring-errors and learn how to properly ignore errors.')
1✔
117
            ->nonIgnorable()
1✔
118
            ->build()
1✔
119
        ;
1✔
120
    }
121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc