• 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.94
/src/Fixer/LanguageConstruct/SingleSpaceAroundConstructFixer.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\LanguageConstruct;
16

17
use PhpCsFixer\AbstractFixer;
18
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
19
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
20
use PhpCsFixer\FixerConfiguration\AllowedValueSubset;
21
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
22
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
23
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
24
use PhpCsFixer\FixerDefinition\CodeSample;
25
use PhpCsFixer\FixerDefinition\FixerDefinition;
26
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
27
use PhpCsFixer\Preg;
28
use PhpCsFixer\Tokenizer\CT;
29
use PhpCsFixer\Tokenizer\FCT;
30
use PhpCsFixer\Tokenizer\Token;
31
use PhpCsFixer\Tokenizer\Tokens;
32

33
/**
34
 * @phpstan-type _AutogeneratedInputConfiguration array{
35
 *  constructs_contain_a_single_space?: list<'yield_from'>,
36
 *  constructs_followed_by_a_single_space?: list<'abstract'|'as'|'attribute'|'break'|'case'|'catch'|'class'|'clone'|'comment'|'const'|'const_import'|'continue'|'do'|'echo'|'else'|'elseif'|'enum'|'extends'|'final'|'finally'|'for'|'foreach'|'function'|'function_import'|'global'|'goto'|'if'|'implements'|'include'|'include_once'|'instanceof'|'insteadof'|'interface'|'match'|'named_argument'|'namespace'|'new'|'open_tag_with_echo'|'php_doc'|'php_open'|'print'|'private'|'private_set'|'protected'|'protected_set'|'public'|'public_set'|'readonly'|'require'|'require_once'|'return'|'static'|'switch'|'throw'|'trait'|'try'|'type_colon'|'use'|'use_lambda'|'use_trait'|'var'|'while'|'yield'|'yield_from'>,
37
 *  constructs_preceded_by_a_single_space?: list<'as'|'else'|'elseif'|'use_lambda'>,
38
 * }
39
 * @phpstan-type _AutogeneratedComputedConfiguration array{
40
 *  constructs_contain_a_single_space: list<'yield_from'>,
41
 *  constructs_followed_by_a_single_space: list<'abstract'|'as'|'attribute'|'break'|'case'|'catch'|'class'|'clone'|'comment'|'const'|'const_import'|'continue'|'do'|'echo'|'else'|'elseif'|'enum'|'extends'|'final'|'finally'|'for'|'foreach'|'function'|'function_import'|'global'|'goto'|'if'|'implements'|'include'|'include_once'|'instanceof'|'insteadof'|'interface'|'match'|'named_argument'|'namespace'|'new'|'open_tag_with_echo'|'php_doc'|'php_open'|'print'|'private'|'private_set'|'protected'|'protected_set'|'public'|'public_set'|'readonly'|'require'|'require_once'|'return'|'static'|'switch'|'throw'|'trait'|'try'|'type_colon'|'use'|'use_lambda'|'use_trait'|'var'|'while'|'yield'|'yield_from'>,
42
 *  constructs_preceded_by_a_single_space: list<'as'|'else'|'elseif'|'use_lambda'>,
43
 * }
44
 *
45
 * @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
46
 *
47
 * @author Andreas Möller <am@localheinz.com>
48
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
49
 *
50
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
51
 */
52
final class SingleSpaceAroundConstructFixer extends AbstractFixer implements ConfigurableFixerInterface
53
{
54
    /** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
55
    use ConfigurableFixerTrait;
56

57
    /**
58
     * @var array<string, int>
59
     */
60
    private const TOKEN_MAP_CONTAIN_A_SINGLE_SPACE = [
61
        // for now, only one case - but we are ready to extend it, when we learn about new cases to cover
62
        'yield_from' => \T_YIELD_FROM,
63
    ];
64

65
    /**
66
     * @var array<string, int>
67
     */
68
    private const TOKEN_MAP_PRECEDED_BY_A_SINGLE_SPACE = [
69
        'as' => \T_AS,
70
        'else' => \T_ELSE,
71
        'elseif' => \T_ELSEIF,
72
        'use_lambda' => CT::T_USE_LAMBDA,
73
    ];
74

75
    /**
76
     * @var array<string, int>
77
     */
78
    private const TOKEN_MAP_FOLLOWED_BY_A_SINGLE_SPACE = [
79
        'abstract' => \T_ABSTRACT,
80
        'as' => \T_AS,
81
        'attribute' => CT::T_ATTRIBUTE_CLOSE,
82
        'break' => \T_BREAK,
83
        'case' => \T_CASE,
84
        'catch' => \T_CATCH,
85
        'class' => \T_CLASS,
86
        'clone' => \T_CLONE,
87
        'comment' => \T_COMMENT,
88
        'const' => \T_CONST,
89
        'const_import' => CT::T_CONST_IMPORT,
90
        'continue' => \T_CONTINUE,
91
        'do' => \T_DO,
92
        'echo' => \T_ECHO,
93
        'else' => \T_ELSE,
94
        'elseif' => \T_ELSEIF,
95
        'enum' => FCT::T_ENUM,
96
        'extends' => \T_EXTENDS,
97
        'final' => \T_FINAL,
98
        'finally' => \T_FINALLY,
99
        'for' => \T_FOR,
100
        'foreach' => \T_FOREACH,
101
        'function' => \T_FUNCTION,
102
        'function_import' => CT::T_FUNCTION_IMPORT,
103
        'global' => \T_GLOBAL,
104
        'goto' => \T_GOTO,
105
        'if' => \T_IF,
106
        'implements' => \T_IMPLEMENTS,
107
        'include' => \T_INCLUDE,
108
        'include_once' => \T_INCLUDE_ONCE,
109
        'instanceof' => \T_INSTANCEOF,
110
        'insteadof' => \T_INSTEADOF,
111
        'interface' => \T_INTERFACE,
112
        'match' => FCT::T_MATCH,
113
        'named_argument' => CT::T_NAMED_ARGUMENT_COLON,
114
        'namespace' => \T_NAMESPACE,
115
        'new' => \T_NEW,
116
        'open_tag_with_echo' => \T_OPEN_TAG_WITH_ECHO,
117
        'php_doc' => \T_DOC_COMMENT,
118
        'php_open' => \T_OPEN_TAG,
119
        'print' => \T_PRINT,
120
        'private' => \T_PRIVATE,
121
        'private_set' => FCT::T_PRIVATE_SET,
122
        'protected' => \T_PROTECTED,
123
        'protected_set' => FCT::T_PROTECTED_SET,
124
        'public' => \T_PUBLIC,
125
        'public_set' => FCT::T_PUBLIC_SET,
126
        'readonly' => FCT::T_READONLY,
127
        'require' => \T_REQUIRE,
128
        'require_once' => \T_REQUIRE_ONCE,
129
        'return' => \T_RETURN,
130
        'static' => \T_STATIC,
131
        'switch' => \T_SWITCH,
132
        'throw' => \T_THROW,
133
        'trait' => \T_TRAIT,
134
        'try' => \T_TRY,
135
        'type_colon' => CT::T_TYPE_COLON,
136
        'use' => \T_USE,
137
        'use_lambda' => CT::T_USE_LAMBDA,
138
        'use_trait' => CT::T_USE_TRAIT,
139
        'var' => \T_VAR,
140
        'while' => \T_WHILE,
141
        'yield' => \T_YIELD,
142
        'yield_from' => \T_YIELD_FROM,
143
    ];
144

145
    /**
146
     * @var array<string, int>
147
     */
148
    private array $fixTokenMapFollowedByASingleSpace = [];
149

150
    /**
151
     * @var array<string, int>
152
     */
153
    private array $fixTokenMapContainASingleSpace = [];
154

155
    /**
156
     * @var array<string, int>
157
     */
158
    private array $fixTokenMapPrecededByASingleSpace = [];
159

160
    public function getDefinition(): FixerDefinitionInterface
161
    {
162
        return new FixerDefinition(
3✔
163
            'Ensures a single space after language constructs.',
3✔
164
            [
3✔
165
                new CodeSample(
3✔
166
                    '<?php
3✔
167

168
throw  new  \Exception();
169
'
3✔
170
                ),
3✔
171
                new CodeSample(
3✔
172
                    '<?php
3✔
173

174
function foo() { yield  from  baz(); }
175
',
3✔
176
                    [
3✔
177
                        'constructs_contain_a_single_space' => [
3✔
178
                            'yield_from',
3✔
179
                        ],
3✔
180
                        'constructs_followed_by_a_single_space' => [
3✔
181
                            'yield_from',
3✔
182
                        ],
3✔
183
                    ]
3✔
184
                ),
3✔
185
                new CodeSample(
3✔
186
                    '<?php
3✔
187

188
$foo = function& ()use($bar) {
189
};
190
',
3✔
191
                    [
3✔
192
                        'constructs_preceded_by_a_single_space' => [
3✔
193
                            'use_lambda',
3✔
194
                        ],
3✔
195
                        'constructs_followed_by_a_single_space' => [
3✔
196
                            'use_lambda',
3✔
197
                        ],
3✔
198
                    ]
3✔
199
                ),
3✔
200
                new CodeSample(
3✔
201
                    '<?php
3✔
202

203
echo  "Hello!";
204
',
3✔
205
                    [
3✔
206
                        'constructs_followed_by_a_single_space' => [
3✔
207
                            'echo',
3✔
208
                        ],
3✔
209
                    ]
3✔
210
                ),
3✔
211
                new CodeSample(
3✔
212
                    '<?php
3✔
213

214
yield  from  baz();
215
',
3✔
216
                    [
3✔
217
                        'constructs_followed_by_a_single_space' => [
3✔
218
                            'yield_from',
3✔
219
                        ],
3✔
220
                    ]
3✔
221
                ),
3✔
222
            ]
3✔
223
        );
3✔
224
    }
225

226
    /**
227
     * {@inheritdoc}
228
     *
229
     * Must run before BracesFixer, FunctionDeclarationFixer.
230
     * Must run after ArraySyntaxFixer, ModernizeStrposFixer.
231
     */
232
    public function getPriority(): int
233
    {
234
        return 36;
1✔
235
    }
236

237
    public function isCandidate(Tokens $tokens): bool
238
    {
239
        $tokenKinds = [
401✔
240
            ...array_values($this->fixTokenMapContainASingleSpace),
401✔
241
            ...array_values($this->fixTokenMapPrecededByASingleSpace),
401✔
242
            ...array_values($this->fixTokenMapFollowedByASingleSpace),
401✔
243
        ];
401✔
244

245
        return $tokens->isAnyTokenKindsFound($tokenKinds);
401✔
246
    }
247

248
    protected function configurePostNormalisation(): void
249
    {
250
        $this->fixTokenMapContainASingleSpace = [];
418✔
251

252
        foreach ($this->configuration['constructs_contain_a_single_space'] as $key) {
418✔
253
            $this->fixTokenMapContainASingleSpace[$key] = self::TOKEN_MAP_CONTAIN_A_SINGLE_SPACE[$key];
418✔
254
        }
255

256
        $this->fixTokenMapPrecededByASingleSpace = [];
418✔
257

258
        foreach ($this->configuration['constructs_preceded_by_a_single_space'] as $key) {
418✔
259
            $this->fixTokenMapPrecededByASingleSpace[$key] = self::TOKEN_MAP_PRECEDED_BY_A_SINGLE_SPACE[$key];
418✔
260
        }
261

262
        $this->fixTokenMapFollowedByASingleSpace = [];
418✔
263

264
        foreach ($this->configuration['constructs_followed_by_a_single_space'] as $key) {
418✔
265
            $this->fixTokenMapFollowedByASingleSpace[$key] = self::TOKEN_MAP_FOLLOWED_BY_A_SINGLE_SPACE[$key];
418✔
266
        }
267

268
        if (isset($this->fixTokenMapFollowedByASingleSpace['public'])) {
418✔
269
            $this->fixTokenMapFollowedByASingleSpace['constructor_public'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC;
418✔
270
        }
271

272
        if (isset($this->fixTokenMapFollowedByASingleSpace['protected'])) {
418✔
273
            $this->fixTokenMapFollowedByASingleSpace['constructor_protected'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED;
418✔
274
        }
275

276
        if (isset($this->fixTokenMapFollowedByASingleSpace['private'])) {
418✔
277
            $this->fixTokenMapFollowedByASingleSpace['constructor_private'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE;
418✔
278
        }
279
    }
280

281
    protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
282
    {
283
        $tokenKindsContainASingleSpace = array_values($this->fixTokenMapContainASingleSpace);
400✔
284

285
        for ($index = $tokens->count() - 1; $index > 0; --$index) {
400✔
286
            if ($tokens[$index]->isGivenKind($tokenKindsContainASingleSpace)) {
398✔
287
                $token = $tokens[$index];
6✔
288

289
                if (
290
                    $token->isGivenKind(\T_YIELD_FROM)
6✔
291
                    && 'yield from' !== strtolower($token->getContent())
6✔
292
                ) {
293
                    $tokens[$index] = new Token([\T_YIELD_FROM, Preg::replace(
6✔
294
                        '/\s+/',
6✔
295
                        ' ',
6✔
296
                        $token->getContent()
6✔
297
                    )]);
6✔
298
                }
299
            }
300
        }
301

302
        $tokenKindsPrecededByASingleSpace = array_values($this->fixTokenMapPrecededByASingleSpace);
400✔
303

304
        for ($index = $tokens->count() - 1; $index > 0; --$index) {
400✔
305
            if ($tokens[$index]->isGivenKind($tokenKindsPrecededByASingleSpace)) {
398✔
306
                if (!$this->isFullLineCommentBefore($tokens, $index)) {
29✔
307
                    $tokens->ensureWhitespaceAtIndex($index - 1, 1, ' ');
27✔
308
                }
309
            }
310
        }
311

312
        $tokenKindsFollowedByASingleSpace = array_values($this->fixTokenMapFollowedByASingleSpace);
400✔
313

314
        for ($index = $tokens->count() - 2; $index >= 0; --$index) {
400✔
315
            $token = $tokens[$index];
398✔
316

317
            if (!$token->isGivenKind($tokenKindsFollowedByASingleSpace)) {
398✔
318
                continue;
398✔
319
            }
320

321
            $whitespaceTokenIndex = $index + 1;
381✔
322

323
            if ($tokens[$whitespaceTokenIndex]->equalsAny([',', ':', ';', ')', [CT::T_ARRAY_SQUARE_BRACE_CLOSE], [CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE]])) {
381✔
324
                continue;
5✔
325
            }
326

327
            if (
328
                $token->isGivenKind(\T_STATIC)
376✔
329
                && !$tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind([\T_FN, \T_FUNCTION, \T_NS_SEPARATOR, \T_STRING, \T_VARIABLE, CT::T_ARRAY_TYPEHINT, CT::T_NULLABLE_TYPE])
376✔
330
            ) {
331
                continue;
2✔
332
            }
333

334
            if ($token->isGivenKind(\T_OPEN_TAG)) {
374✔
335
                if ($tokens[$whitespaceTokenIndex]->isGivenKind(\T_WHITESPACE) && !str_contains($tokens[$whitespaceTokenIndex]->getContent(), "\n") && !str_contains($token->getContent(), "\n")) {
22✔
336
                    $tokens->clearAt($whitespaceTokenIndex);
2✔
337
                }
338

339
                continue;
22✔
340
            }
341

342
            if ($token->isGivenKind(\T_CLASS) && $tokens[$tokens->getNextMeaningfulToken($index)]->equals('(')) {
369✔
343
                continue;
1✔
344
            }
345

346
            if ($token->isGivenKind([\T_EXTENDS, \T_IMPLEMENTS]) && $this->isMultilineExtendsOrImplementsWithMoreThanOneAncestor($tokens, $index)) {
368✔
347
                continue;
2✔
348
            }
349

350
            if ($token->isGivenKind(\T_RETURN) && $this->isMultiLineReturn($tokens, $index)) {
366✔
351
                continue;
10✔
352
            }
353

354
            if ($token->isGivenKind(\T_CONST) && $this->isMultilineCommaSeparatedConstant($tokens, $index)) {
356✔
355
                continue;
2✔
356
            }
357

358
            if ($token->isComment() || $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
354✔
359
                if ($tokens[$whitespaceTokenIndex]->isGivenKind(\T_WHITESPACE) && str_contains($tokens[$whitespaceTokenIndex]->getContent(), "\n")) {
4✔
360
                    continue;
4✔
361
                }
362
            }
363

364
            if ($tokens[$whitespaceTokenIndex]->isWhitespace() && str_contains($tokens[$whitespaceTokenIndex]->getContent(), "\n")) {
354✔
365
                $nextNextToken = $tokens[$whitespaceTokenIndex + 1];
82✔
366
                if (
367
                    $nextNextToken->isGivenKind(FCT::T_ATTRIBUTE)
82✔
368
                    || $nextNextToken->isComment() && str_starts_with($nextNextToken->getContent(), '#[')
82✔
369
                ) {
370
                    continue;
1✔
371
                }
372

373
                if ($nextNextToken->isGivenKind(\T_DOC_COMMENT)) {
81✔
374
                    continue;
1✔
375
                }
376
            }
377

378
            $tokens->ensureWhitespaceAtIndex($whitespaceTokenIndex, 0, ' ');
352✔
379
        }
380
    }
381

382
    protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
383
    {
384
        $tokenMapContainASingleSpaceKeys = array_keys(self::TOKEN_MAP_CONTAIN_A_SINGLE_SPACE);
418✔
385
        $tokenMapPrecededByASingleSpaceKeys = array_keys(self::TOKEN_MAP_PRECEDED_BY_A_SINGLE_SPACE);
418✔
386
        $tokenMapFollowedByASingleSpaceKeys = array_keys(self::TOKEN_MAP_FOLLOWED_BY_A_SINGLE_SPACE);
418✔
387

388
        return new FixerConfigurationResolver([
418✔
389
            (new FixerOptionBuilder('constructs_contain_a_single_space', 'List of constructs which must contain a single space.'))
418✔
390
                ->setAllowedTypes(['string[]'])
418✔
391
                ->setAllowedValues([new AllowedValueSubset($tokenMapContainASingleSpaceKeys)])
418✔
392
                ->setDefault($tokenMapContainASingleSpaceKeys)
418✔
393
                ->getOption(),
418✔
394
            (new FixerOptionBuilder('constructs_preceded_by_a_single_space', 'List of constructs which must be preceded by a single space.'))
418✔
395
                ->setAllowedTypes(['string[]'])
418✔
396
                ->setAllowedValues([new AllowedValueSubset($tokenMapPrecededByASingleSpaceKeys)])
418✔
397
                ->setDefault(['as', 'use_lambda'])
418✔
398
                ->getOption(),
418✔
399
            (new FixerOptionBuilder('constructs_followed_by_a_single_space', 'List of constructs which must be followed by a single space.'))
418✔
400
                ->setAllowedTypes(['string[]'])
418✔
401
                ->setAllowedValues([new AllowedValueSubset($tokenMapFollowedByASingleSpaceKeys)])
418✔
402
                ->setDefault($tokenMapFollowedByASingleSpaceKeys)
418✔
403
                ->getOption(),
418✔
404
        ]);
418✔
405
    }
406

407
    private function isMultiLineReturn(Tokens $tokens, int $index): bool
408
    {
409
        ++$index;
18✔
410
        $tokenFollowingReturn = $tokens[$index];
18✔
411

412
        if (
413
            !$tokenFollowingReturn->isGivenKind(\T_WHITESPACE)
18✔
414
            || !str_contains($tokenFollowingReturn->getContent(), "\n")
18✔
415
        ) {
416
            return false;
8✔
417
        }
418

419
        $nestedCount = 0;
13✔
420

421
        for ($indexEnd = \count($tokens) - 1, ++$index; $index < $indexEnd; ++$index) {
13✔
422
            if (str_contains($tokens[$index]->getContent(), "\n")) {
13✔
423
                return true;
10✔
424
            }
425

426
            if ($tokens[$index]->equals('{')) {
13✔
427
                ++$nestedCount;
1✔
428
            } elseif ($tokens[$index]->equals('}')) {
13✔
429
                --$nestedCount;
1✔
430
            } elseif (0 === $nestedCount && $tokens[$index]->equalsAny([';', [\T_CLOSE_TAG]])) {
13✔
431
                break;
×
432
            }
433
        }
434

435
        return false;
3✔
436
    }
437

438
    private function isMultilineExtendsOrImplementsWithMoreThanOneAncestor(Tokens $tokens, int $index): bool
439
    {
440
        $hasMoreThanOneAncestor = false;
26✔
441

442
        while (true) {
26✔
443
            ++$index;
26✔
444
            $token = $tokens[$index];
26✔
445

446
            if ($token->equals(',')) {
26✔
447
                $hasMoreThanOneAncestor = true;
6✔
448

449
                continue;
6✔
450
            }
451

452
            if ($token->equals('{')) {
26✔
453
                return false;
24✔
454
            }
455

456
            if ($hasMoreThanOneAncestor && str_contains($token->getContent(), "\n")) {
26✔
457
                return true;
2✔
458
            }
459
        }
460

461
        return LogicException('Not reachable code was reached.'); // @phpstan-ignore deadCode.unreachable
×
462
    }
463

464
    private function isMultilineCommaSeparatedConstant(Tokens $tokens, int $constantIndex): bool
465
    {
466
        $isMultilineConstant = false;
10✔
467
        $hasMoreThanOneConstant = false;
10✔
468
        $index = $constantIndex;
10✔
469
        while (!$tokens[$index]->equalsAny([';', [\T_CLOSE_TAG]])) {
10✔
470
            ++$index;
10✔
471

472
            $isMultilineConstant = $isMultilineConstant || str_contains($tokens[$index]->getContent(), "\n");
10✔
473

474
            if ($tokens[$index]->equals(',')) {
10✔
475
                $hasMoreThanOneConstant = true;
2✔
476
            }
477

478
            $blockType = Tokens::detectBlockType($tokens[$index]);
10✔
479

480
            if (null !== $blockType && true === $blockType['isStart']) {
10✔
481
                $index = $tokens->findBlockEnd($blockType['type'], $index);
1✔
482
            }
483
        }
484

485
        return $hasMoreThanOneConstant && $isMultilineConstant;
10✔
486
    }
487

488
    private function isFullLineCommentBefore(Tokens $tokens, int $index): bool
489
    {
490
        $beforeIndex = $tokens->getPrevNonWhitespace($index);
29✔
491

492
        if (!$tokens[$beforeIndex]->isGivenKind(\T_COMMENT)) {
29✔
493
            return false;
25✔
494
        }
495

496
        $content = $tokens[$beforeIndex]->getContent();
4✔
497

498
        return str_starts_with($content, '#') || str_starts_with($content, '//');
4✔
499
    }
500
}
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