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

keradus / PHP-CS-Fixer / 17253322895

26 Aug 2025 11:52PM UTC coverage: 94.753% (+0.008%) from 94.745%
17253322895

push

github

keradus
add to git-blame-ignore-revs

28316 of 29884 relevant lines covered (94.75%)

45.64 hits per line

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

94.37
/src/Utils.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;
16

17
use PhpCsFixer\Fixer\FixerInterface;
18
use PhpCsFixer\Tokenizer\Token;
19

20
/**
21
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
22
 * @author Graham Campbell <hello@gjcampbell.co.uk>
23
 * @author Odín del Río <odin.drp@gmail.com>
24
 *
25
 * @internal
26
 *
27
 * @deprecated This is a God Class anti-pattern. Don't expand it. It is fine to use logic that is already here (that's why we don't trigger deprecation warnings), but over time logic should be moved to dedicated, single-responsibility classes.
28
 *
29
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
30
 */
31
final class Utils
32
{
33
    /**
34
     * @var array<string, true>
35
     */
36
    private static array $deprecations = [];
37

38
    private function __construct()
39
    {
40
        // cannot create instance of util. class
41
    }
×
42

43
    /**
44
     * Converts a camel cased string to a snake cased string.
45
     */
46
    public static function camelCaseToUnderscore(string $string): string
47
    {
48
        return mb_strtolower(Preg::replace('/(?<!^)(?<!_)((?=[\p{Lu}][^\p{Lu}])|(?<![\p{Lu}])(?=[\p{Lu}]))/', '_', $string));
13✔
49
    }
50

51
    /**
52
     * Calculate the trailing whitespace.
53
     *
54
     * What we're doing here is grabbing everything after the final newline.
55
     */
56
    public static function calculateTrailingWhitespaceIndent(Token $token): string
57
    {
58
        if (!$token->isWhitespace()) {
7✔
59
            throw new \InvalidArgumentException(\sprintf('The given token must be whitespace, got "%s".', $token->getName()));
1✔
60
        }
61

62
        $str = strrchr(
6✔
63
            str_replace(["\r\n", "\r"], "\n", $token->getContent()),
6✔
64
            "\n"
6✔
65
        );
6✔
66

67
        if (false === $str) {
6✔
68
            return '';
1✔
69
        }
70

71
        return ltrim($str, "\n");
5✔
72
    }
73

74
    /**
75
     * Perform stable sorting using provided comparison function.
76
     *
77
     * Stability is ensured by using Schwartzian transform.
78
     *
79
     * @template T
80
     * @template R
81
     *
82
     * @param list<T>             $elements
83
     * @param callable(T): R      $getComparedValue a callable that takes a single element and returns the value to compare
84
     * @param callable(R, R): int $compareValues    a callable that compares two values
85
     *
86
     * @return list<T>
87
     */
88
    public static function stableSort(array $elements, callable $getComparedValue, callable $compareValues): array
89
    {
90
        array_walk($elements, static function (&$element, int $index) use ($getComparedValue): void {
5✔
91
            $element = [$element, $index, $getComparedValue($element)];
5✔
92
        });
5✔
93

94
        usort($elements, static function ($a, $b) use ($compareValues): int {
5✔
95
            $comparison = $compareValues($a[2], $b[2]);
5✔
96

97
            if (0 !== $comparison) {
5✔
98
                return $comparison;
3✔
99
            }
100

101
            return $a[1] <=> $b[1];
3✔
102
        });
5✔
103

104
        return array_map(static fn (array $item) => $item[0], $elements);
5✔
105
    }
106

107
    /**
108
     * Sort fixers by their priorities.
109
     *
110
     * @param list<FixerInterface> $fixers
111
     *
112
     * @return list<FixerInterface>
113
     */
114
    public static function sortFixers(array $fixers): array
115
    {
116
        // Schwartzian transform is used to improve the efficiency and avoid
117
        // `usort(): Array was modified by the user comparison function` warning for mocked objects.
118
        return self::stableSort(
1✔
119
            $fixers,
1✔
120
            static fn (FixerInterface $fixer): int => $fixer->getPriority(),
1✔
121
            static fn (int $a, int $b): int => $b <=> $a
1✔
122
        );
1✔
123
    }
124

125
    /**
126
     * Join names in natural language using specified wrapper (double quote by default).
127
     *
128
     * @param list<string> $names
129
     *
130
     * @throws \InvalidArgumentException
131
     */
132
    public static function naturalLanguageJoin(array $names, string $wrapper = '"', string $lastJoin = 'and'): string
133
    {
134
        if (0 === \count($names)) {
24✔
135
            throw new \InvalidArgumentException('Array of names cannot be empty.');
2✔
136
        }
137

138
        if (\strlen($wrapper) > 1) {
22✔
139
            throw new \InvalidArgumentException('Wrapper should be a single-char string or empty.');
1✔
140
        }
141

142
        $names = array_map(static fn (string $name): string => \sprintf('%2$s%1$s%2$s', $name, $wrapper), $names);
21✔
143

144
        $last = array_pop($names);
21✔
145

146
        if (\count($names) > 0) {
21✔
147
            return implode(', ', $names).' '.$lastJoin.' '.$last;
14✔
148
        }
149

150
        return $last;
7✔
151
    }
152

153
    /**
154
     * Join names in natural language wrapped in backticks, e.g. `a`, `b` and `c`.
155
     *
156
     * @param list<string> $names
157
     *
158
     * @throws \InvalidArgumentException
159
     */
160
    public static function naturalLanguageJoinWithBackticks(array $names, string $lastJoin = 'and'): string
161
    {
162
        return self::naturalLanguageJoin($names, '`', $lastJoin);
7✔
163
    }
164

165
    public static function isFutureModeEnabled(): bool
166
    {
167
        return filter_var(
2✔
168
            getenv('PHP_CS_FIXER_FUTURE_MODE'),
2✔
169
            \FILTER_VALIDATE_BOOL
2✔
170
        );
2✔
171
    }
172

173
    public static function triggerDeprecation(\Exception $futureException): void
174
    {
175
        if (self::isFutureModeEnabled()) {
2✔
176
            throw new \RuntimeException(
1✔
177
                'Your are using something deprecated, see previous exception. Aborting execution because `PHP_CS_FIXER_FUTURE_MODE` environment variable is set.',
1✔
178
                0,
1✔
179
                $futureException
1✔
180
            );
1✔
181
        }
182

183
        $message = $futureException->getMessage();
1✔
184

185
        self::$deprecations[$message] = true;
1✔
186
        @trigger_error($message, \E_USER_DEPRECATED);
1✔
187
    }
188

189
    /**
190
     * @return list<string>
191
     */
192
    public static function getTriggeredDeprecations(): array
193
    {
194
        $triggeredDeprecations = array_keys(self::$deprecations);
2✔
195
        sort($triggeredDeprecations);
2✔
196

197
        return $triggeredDeprecations;
2✔
198
    }
199

200
    public static function convertArrayTypeToList(string $type): string
201
    {
202
        $parts = explode('[]', $type);
×
203
        $count = \count($parts) - 1;
×
204

205
        return str_repeat('list<', $count).$parts[0].str_repeat('>', $count);
×
206
    }
207

208
    /**
209
     * @param mixed $value
210
     */
211
    public static function toString($value): string
212
    {
213
        return \is_array($value)
11✔
214
            ? self::arrayToString($value)
6✔
215
            : self::scalarToString($value);
11✔
216
    }
217

218
    /**
219
     * @param mixed $value
220
     */
221
    private static function scalarToString($value): string
222
    {
223
        $str = var_export($value, true);
10✔
224

225
        return Preg::replace('/\bNULL\b/', 'null', $str);
10✔
226
    }
227

228
    /**
229
     * @param array<array-key, mixed> $value
230
     */
231
    private static function arrayToString(array $value): string
232
    {
233
        if (0 === \count($value)) {
6✔
234
            return '[]';
1✔
235
        }
236

237
        $isHash = !array_is_list($value);
5✔
238
        $str = '[';
5✔
239

240
        foreach ($value as $k => $v) {
5✔
241
            if ($isHash) {
5✔
242
                $str .= self::scalarToString($k).' => ';
2✔
243
            }
244

245
            $str .= \is_array($v)
5✔
246
                ? self::arrayToString($v).', '
2✔
247
                : self::scalarToString($v).', ';
5✔
248
        }
249

250
        return substr($str, 0, -2).']';
5✔
251
    }
252
}
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