• 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

98.11
/src/Fixer/ControlStructure/NoUnneededBracesFixer.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\ControlStructure;
16

17
use PhpCsFixer\AbstractFixer;
18
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
19
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
20
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
21
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
22
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
23
use PhpCsFixer\FixerDefinition\CodeSample;
24
use PhpCsFixer\FixerDefinition\FixerDefinition;
25
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
26
use PhpCsFixer\Tokenizer\Token;
27
use PhpCsFixer\Tokenizer\Tokens;
28

29
/**
30
 * @phpstan-type _AutogeneratedInputConfiguration array{
31
 *  namespaces?: bool,
32
 * }
33
 * @phpstan-type _AutogeneratedComputedConfiguration array{
34
 *  namespaces: bool,
35
 * }
36
 *
37
 * @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
38
 *
39
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
40
 */
41
final class NoUnneededBracesFixer extends AbstractFixer implements ConfigurableFixerInterface
42
{
43
    /** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
44
    use ConfigurableFixerTrait;
45

46
    public function getDefinition(): FixerDefinitionInterface
47
    {
48
        return new FixerDefinition(
3✔
49
            'Removes unneeded braces that are superfluous and aren\'t part of a control structure\'s body.',
3✔
50
            [
3✔
51
                new CodeSample(
3✔
52
                    '<?php {
3✔
53
    echo 1;
54
}
55

56
switch ($b) {
57
    case 1: {
58
        break;
59
    }
60
}
61
'
3✔
62
                ),
3✔
63
                new CodeSample(
3✔
64
                    '<?php
3✔
65
namespace Foo {
66
    function Bar(){}
67
}
68
',
3✔
69
                    ['namespaces' => true]
3✔
70
                ),
3✔
71
            ]
3✔
72
        );
3✔
73
    }
74

75
    /**
76
     * {@inheritdoc}
77
     *
78
     * Must run before NoUselessElseFixer, NoUselessReturnFixer, ReturnAssignmentFixer, SimplifiedIfReturnFixer.
79
     */
80
    public function getPriority(): int
81
    {
82
        return 40;
1✔
83
    }
84

85
    public function isCandidate(Tokens $tokens): bool
86
    {
87
        return $tokens->isTokenKindFound('}');
15✔
88
    }
89

90
    protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
91
    {
92
        foreach ($this->findBraceOpen($tokens) as $index) {
15✔
93
            if ($this->isOverComplete($tokens, $index)) {
15✔
94
                $this->clearOverCompleteBraces($tokens, $index, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index));
4✔
95
            }
96
        }
97

98
        if (true === $this->configuration['namespaces']) {
15✔
99
            $this->clearIfIsOverCompleteNamespaceBlock($tokens);
7✔
100
        }
101
    }
102

103
    protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
104
    {
105
        return new FixerConfigurationResolver([
24✔
106
            (new FixerOptionBuilder('namespaces', 'Remove unneeded braces from bracketed namespaces.'))
24✔
107
                ->setAllowedTypes(['bool'])
24✔
108
                ->setDefault(false)
24✔
109
                ->getOption(),
24✔
110
        ]);
24✔
111
    }
112

113
    /**
114
     * @param int $openIndex  index of `{` token
115
     * @param int $closeIndex index of `}` token
116
     */
117
    private function clearOverCompleteBraces(Tokens $tokens, int $openIndex, int $closeIndex): void
118
    {
119
        $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex);
4✔
120
        $tokens->clearTokenAndMergeSurroundingWhitespace($openIndex);
4✔
121
    }
122

123
    /**
124
     * @return iterable<int>
125
     */
126
    private function findBraceOpen(Tokens $tokens): iterable
127
    {
128
        for ($i = \count($tokens) - 1; $i > 0; --$i) {
15✔
129
            if ($tokens[$i]->equals('{')) {
15✔
130
                yield $i;
15✔
131
            }
132
        }
133
    }
134

135
    /**
136
     * @param int $index index of `{` token
137
     */
138
    private function isOverComplete(Tokens $tokens, int $index): bool
139
    {
140
        return $tokens[$tokens->getPrevMeaningfulToken($index)]->equalsAny(['{', '}', [\T_OPEN_TAG], ':', ';']);
15✔
141
    }
142

143
    private function clearIfIsOverCompleteNamespaceBlock(Tokens $tokens): void
144
    {
145
        if (1 !== $tokens->countTokenKind(\T_NAMESPACE)) {
7✔
146
            return; // fast check, we never fix if multiple namespaces are defined
1✔
147
        }
148

149
        $index = $tokens->getNextTokenOfKind(0, [[\T_NAMESPACE]]);
6✔
150

151
        $namespaceIsNamed = false;
6✔
152

153
        $index = $tokens->getNextMeaningfulToken($index);
6✔
154
        while ($tokens[$index]->isGivenKind([\T_STRING, \T_NS_SEPARATOR])) {
6✔
155
            $index = $tokens->getNextMeaningfulToken($index);
5✔
156
            $namespaceIsNamed = true;
5✔
157
        }
158

159
        if (!$namespaceIsNamed) {
6✔
160
            return;
1✔
161
        }
162

163
        if (!$tokens[$index]->equals('{')) {
5✔
164
            return; // `;`
4✔
165
        }
166

167
        $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index);
5✔
168
        $afterCloseIndex = $tokens->getNextMeaningfulToken($closeIndex);
5✔
169

170
        if (null !== $afterCloseIndex && (!$tokens[$afterCloseIndex]->isGivenKind(\T_CLOSE_TAG) || null !== $tokens->getNextMeaningfulToken($afterCloseIndex))) {
5✔
171
            return;
×
172
        }
173

174
        // clear up
175
        $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex);
5✔
176
        $tokens[$index] = new Token(';');
5✔
177

178
        if ($tokens[$index - 1]->isWhitespace(" \t") && !$tokens[$index - 2]->isComment()) {
5✔
179
            $tokens->clearTokenAndMergeSurroundingWhitespace($index - 1);
5✔
180
        }
181
    }
182
}
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