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

keradus / PHP-CS-Fixer / 17319949156

29 Aug 2025 09:20AM UTC coverage: 94.696% (-0.05%) from 94.744%
17319949156

push

github

keradus
CS

28333 of 29920 relevant lines covered (94.7%)

45.63 hits per line

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

97.78
/src/Fixer/DoctrineAnnotation/DoctrineAnnotationBracesFixer.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\DoctrineAnnotation;
16

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

30
/**
31
 * Adds braces to Doctrine annotations when missing.
32
 *
33
 * @phpstan-type _AutogeneratedInputConfiguration array{
34
 *  ignored_tags?: list<string>,
35
 *  syntax?: 'with_braces'|'without_braces',
36
 * }
37
 * @phpstan-type _AutogeneratedComputedConfiguration array{
38
 *  ignored_tags: list<string>,
39
 *  syntax: 'with_braces'|'without_braces',
40
 * }
41
 *
42
 * @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
43
 *
44
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
45
 */
46
final class DoctrineAnnotationBracesFixer extends AbstractDoctrineAnnotationFixer implements ConfigurableFixerInterface
47
{
48
    /** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
49
    use ConfigurableFixerTrait;
50

51
    public function getDefinition(): FixerDefinitionInterface
52
    {
53
        return new FixerDefinition(
3✔
54
            'Doctrine annotations without arguments must use the configured syntax.',
3✔
55
            [
3✔
56
                new CodeSample(
3✔
57
                    "<?php\n/**\n * @Foo()\n */\nclass Bar {}\n"
3✔
58
                ),
3✔
59
                new CodeSample(
3✔
60
                    "<?php\n/**\n * @Foo\n */\nclass Bar {}\n",
3✔
61
                    ['syntax' => 'with_braces']
3✔
62
                ),
3✔
63
            ]
3✔
64
        );
3✔
65
    }
66

67
    protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
68
    {
69
        return new FixerConfigurationResolver([
154✔
70
            ...parent::createConfigurationDefinition()->getOptions(),
154✔
71
            (new FixerOptionBuilder('syntax', 'Whether to add or remove braces.'))
154✔
72
                ->setAllowedValues(['with_braces', 'without_braces'])
154✔
73
                ->setDefault('without_braces')
154✔
74
                ->getOption(),
154✔
75
        ]);
154✔
76
    }
77

78
    protected function fixAnnotations(Tokens $doctrineAnnotationTokens): void
79
    {
80
        if ('without_braces' === $this->configuration['syntax']) {
107✔
81
            $this->removesBracesFromAnnotations($doctrineAnnotationTokens);
56✔
82
        } else {
83
            $this->addBracesToAnnotations($doctrineAnnotationTokens);
52✔
84
        }
85
    }
86

87
    private function addBracesToAnnotations(Tokens $tokens): void
88
    {
89
        foreach ($tokens as $index => $token) {
52✔
90
            if (!$token->isType(DocLexer::T_AT)) {
52✔
91
                continue;
52✔
92
            }
93

94
            $braceIndex = $tokens->getNextMeaningfulToken($index + 1);
40✔
95
            if (null !== $braceIndex && $tokens[$braceIndex]->isType(DocLexer::T_OPEN_PARENTHESIS)) {
40✔
96
                continue;
39✔
97
            }
98

99
            $tokens->insertAt($index + 2, new Token(DocLexer::T_OPEN_PARENTHESIS, '('));
25✔
100
            $tokens->insertAt($index + 3, new Token(DocLexer::T_CLOSE_PARENTHESIS, ')'));
25✔
101
        }
102
    }
103

104
    private function removesBracesFromAnnotations(Tokens $tokens): void
105
    {
106
        for ($index = 0, $max = \count($tokens); $index < $max; ++$index) {
56✔
107
            if (!$tokens[$index]->isType(DocLexer::T_AT)) {
56✔
108
                continue;
56✔
109
            }
110

111
            $openBraceIndex = $tokens->getNextMeaningfulToken($index + 1);
44✔
112
            if (null === $openBraceIndex) {
44✔
113
                continue;
22✔
114
            }
115

116
            if (!$tokens[$openBraceIndex]->isType(DocLexer::T_OPEN_PARENTHESIS)) {
41✔
117
                continue;
21✔
118
            }
119

120
            $closeBraceIndex = $tokens->getNextMeaningfulToken($openBraceIndex);
41✔
121
            if (null === $closeBraceIndex) {
41✔
122
                continue;
×
123
            }
124

125
            if (!$tokens[$closeBraceIndex]->isType(DocLexer::T_CLOSE_PARENTHESIS)) {
41✔
126
                continue;
21✔
127
            }
128

129
            for ($currentIndex = $index + 2; $currentIndex <= $closeBraceIndex; ++$currentIndex) {
32✔
130
                $tokens[$currentIndex]->clear();
32✔
131
            }
132
        }
133
    }
134
}
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