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

keradus / PHP-CS-Fixer / 17252691116

26 Aug 2025 11:09PM UTC coverage: 94.743% (-0.01%) from 94.755%
17252691116

push

github

keradus
chore: apply phpdoc_tag_no_named_arguments

28313 of 29884 relevant lines covered (94.74%)

45.64 hits per line

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

96.49
/src/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of PHP CS Fixer.
7
 *
8
 * (c) Fabien Potencier <fabien@symfony.com>
9
 *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14

15
namespace PhpCsFixer\Fixer\Phpdoc;
16

17
use PhpCsFixer\AbstractFixer;
18
use PhpCsFixer\DocBlock\DocBlock;
19
use PhpCsFixer\DocBlock\Line;
20
use PhpCsFixer\DocBlock\ShortDescription;
21
use PhpCsFixer\FixerDefinition\CodeSample;
22
use PhpCsFixer\FixerDefinition\FixerDefinition;
23
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
24
use PhpCsFixer\Tokenizer\Token;
25
use PhpCsFixer\Tokenizer\Tokens;
26

27
/**
28
 * @author Nobu Funaki <nobu.funaki@gmail.com>
29
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
30
 *
31
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
32
 */
33
final class PhpdocTrimConsecutiveBlankLineSeparationFixer extends AbstractFixer
34
{
35
    public function getDefinition(): FixerDefinitionInterface
36
    {
37
        return new FixerDefinition(
3✔
38
            'Removes extra blank lines after summary and after description in PHPDoc.',
3✔
39
            [
3✔
40
                new CodeSample(
3✔
41
                    '<?php
3✔
42
/**
43
 * Summary.
44
 *
45
 *
46
 * Description that contain 4 lines,
47
 *
48
 *
49
 * while 2 of them are blank!
50
 *
51
 *
52
 * @param string $foo
53
 *
54
 *
55
 * @dataProvider provideFixCases
56
 */
57
function fnc($foo) {}
58
'
3✔
59
                ),
3✔
60
            ]
3✔
61
        );
3✔
62
    }
63

64
    /**
65
     * {@inheritdoc}
66
     *
67
     * Must run before PhpdocAlignFixer.
68
     * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpUnitAttributesFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer.
69
     */
70
    public function getPriority(): int
71
    {
72
        return -41;
1✔
73
    }
74

75
    public function isCandidate(Tokens $tokens): bool
76
    {
77
        return $tokens->isTokenKindFound(\T_DOC_COMMENT);
7✔
78
    }
79

80
    protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
81
    {
82
        foreach ($tokens as $index => $token) {
7✔
83
            if (!$token->isGivenKind(\T_DOC_COMMENT)) {
7✔
84
                continue;
7✔
85
            }
86

87
            $doc = new DocBlock($token->getContent());
7✔
88
            $summaryEnd = (new ShortDescription($doc))->getEnd();
7✔
89

90
            if (null !== $summaryEnd) {
7✔
91
                $this->fixSummary($doc, $summaryEnd);
5✔
92
                $this->fixDescription($doc, $summaryEnd);
5✔
93
            }
94

95
            $this->fixAllTheRest($doc);
7✔
96

97
            $tokens[$index] = new Token([\T_DOC_COMMENT, $doc->getContent()]);
7✔
98
        }
99
    }
100

101
    private function fixSummary(DocBlock $doc, int $summaryEnd): void
102
    {
103
        $nonBlankLineAfterSummary = $this->findNonBlankLine($doc, $summaryEnd);
5✔
104

105
        $this->removeExtraBlankLinesBetween($doc, $summaryEnd, $nonBlankLineAfterSummary);
5✔
106
    }
107

108
    private function fixDescription(DocBlock $doc, int $summaryEnd): void
109
    {
110
        $annotationStart = $this->findFirstAnnotationOrEnd($doc);
5✔
111

112
        // assuming the end of the Description appears before the first Annotation
113
        $descriptionEnd = $this->reverseFindLastUsefulContent($doc, $annotationStart);
5✔
114

115
        if (null === $descriptionEnd || $summaryEnd === $descriptionEnd) {
5✔
116
            return; // no Description
1✔
117
        }
118

119
        if ($annotationStart === \count($doc->getLines()) - 1) {
4✔
120
            return; // no content after Description
1✔
121
        }
122

123
        $this->removeExtraBlankLinesBetween($doc, $descriptionEnd, $annotationStart);
3✔
124
    }
125

126
    private function fixAllTheRest(DocBlock $doc): void
127
    {
128
        $annotationStart = $this->findFirstAnnotationOrEnd($doc);
7✔
129
        $lastLine = $this->reverseFindLastUsefulContent($doc, \count($doc->getLines()) - 1);
7✔
130

131
        if (null !== $lastLine && $annotationStart !== $lastLine) {
7✔
132
            $this->removeExtraBlankLinesBetween($doc, $annotationStart, $lastLine);
5✔
133
        }
134
    }
135

136
    private function removeExtraBlankLinesBetween(DocBlock $doc, int $from, int $to): void
137
    {
138
        for ($index = $from + 1; $index < $to; ++$index) {
6✔
139
            $line = $doc->getLine($index);
6✔
140
            $next = $doc->getLine($index + 1);
6✔
141
            $this->removeExtraBlankLine($line, $next);
6✔
142
        }
143
    }
144

145
    private function removeExtraBlankLine(Line $current, Line $next): void
146
    {
147
        if (!$current->isTheEnd() && !$current->containsUsefulContent()
6✔
148
            && !$next->isTheEnd() && !$next->containsUsefulContent()) {
6✔
149
            $current->remove();
5✔
150
        }
151
    }
152

153
    private function findNonBlankLine(DocBlock $doc, int $after): ?int
154
    {
155
        foreach ($doc->getLines() as $index => $line) {
5✔
156
            if ($index <= $after) {
5✔
157
                continue;
5✔
158
            }
159

160
            if ($line->containsATag() || $line->containsUsefulContent() || $line->isTheEnd()) {
5✔
161
                return $index;
5✔
162
            }
163
        }
164

165
        return null;
×
166
    }
167

168
    private function findFirstAnnotationOrEnd(DocBlock $doc): int
169
    {
170
        foreach ($doc->getLines() as $index => $line) {
7✔
171
            if ($line->containsATag()) {
7✔
172
                return $index;
5✔
173
            }
174
        }
175

176
        if (!isset($index)) {
2✔
177
            throw new \LogicException('PHPDoc has empty lines collection.');
×
178
        }
179

180
        return $index; // no Annotation, return the last line
2✔
181
    }
182

183
    private function reverseFindLastUsefulContent(DocBlock $doc, int $from): ?int
184
    {
185
        for ($index = $from - 1; $index >= 0; --$index) {
7✔
186
            if ($doc->getLine($index)->containsUsefulContent()) {
6✔
187
                return $index;
6✔
188
            }
189
        }
190

191
        return null;
1✔
192
    }
193
}
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