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

dg / dresscode / 39958301154

09 Oct 2026 03:22PM UTC coverage: 97.773% (+0.004%) from 97.769%
39958301154

push

github

dg
released version 1.3.0

22739 of 23257 relevant lines covered (97.77%)

0.98 hits per line

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

98.61
/src/Engine/WorkerCodec.php
1
<?php declare(strict_types=1);
2

3
/**
4
 * This file is part of the DressCode, a coding style and upgrade tool for PHP (https://dresscode.run)
5
 * Copyright (c) 2026 David Grudl (https://davidgrudl.com)
6
 */
7

8
namespace DressCode\Engine;
9

10
use DressCode\{FileResult, Risk, Rule, Severity, Violation};
11
use function is_array, is_string;
12

13

14
/**
15
 * The result of a file as a worker sends it to the parent: the output only where it differs from the code, which
16
 * the parent has, the output and the path base64-encoded since neither need be UTF-8.
17
 * @internal
18
 */
19
final class WorkerCodec
20
{
21
        /** @return array<string, mixed> */
22
        public static function encode(FileResult $result): array
23
        {
24
                return [
25
                        'path' => base64_encode($result->path),
1 ✔
26
                        'output' => $result->output === $result->code ? true : ($result->output === null ? null : base64_encode($result->output)),
1 ✔
27
                        'violations' => array_map(self::encodeViolation(...), $result->violations),
1 ✔
28
                        'warnings' => $result->warnings,
1 ✔
29
                        'syntaxError' => $result->syntaxError,
1 ✔
30
                        'syntaxErrorLine' => $result->syntaxErrorLine,
1 ✔
31
                        'passes' => $result->passes,
1 ✔
32
                        'failure' => $result->failure,
1 ✔
33
                        'failureDocs' => $result->failureDocs,
1 ✔
34
                        'baselined' => $result->baselined,
1 ✔
35
                        'remaining' => array_map(self::encodeViolation(...), $result->remaining),
1 ✔
36
                        'written' => $result->written,
1 ✔
37
                        'cached' => $result->cached,
1 ✔
38
                        'removedImports' => $result->removedImports,
1 ✔
39
                        'mutatedRules' => $result->mutatedRules,
1 ✔
40
                ];
41
        }
42

43

44
        /**
45
         * @param  array<string, mixed>  $data  as `encode()` made it
46
         * @param  string  $code  the content the parent handed the worker
47
         */
48
        public static function decode(array $data, string $code): FileResult
49
        {
50
                $output = $data['output'];
1 ✔
51
                return new FileResult(
1 ✔
52
                        path: (string) base64_decode((string) $data['path'], strict: true),
1 ✔
53
                        code: $code,
54
                        output: $output === true ? $code : ($output === null ? null : (string) base64_decode((string) $output, strict: true)),
1 ✔
55
                        violations: self::decodeViolations($data['violations']),
1 ✔
56
                        warnings: is_array($data['warnings']) ? array_values(array_map(strval(...), $data['warnings'])) : [],
1 ✔
57
                        syntaxError: $data['syntaxError'] === null ? null : (string) $data['syntaxError'],
1 ✔
58
                        syntaxErrorLine: $data['syntaxErrorLine'] === null ? null : (int) $data['syntaxErrorLine'],
1 ✔
59
                        passes: (int) $data['passes'],
1 ✔
60
                        failure: $data['failure'] === null ? null : (string) $data['failure'],
1 ✔
61
                        failureDocs: $data['failureDocs'] === null ? null : (string) $data['failureDocs'],
1 ✔
62
                        baselined: is_array($data['baselined']) ? array_values(array_map(strval(...), $data['baselined'])) : [],
1 ✔
63
                        remaining: self::decodeViolations($data['remaining']),
1 ✔
64
                        written: (bool) $data['written'],
1 ✔
65
                        cached: (bool) $data['cached'],
1 ✔
66
                        removedImports: array_values(array_map(fn(array $import) => [
1 ✔
67
                                'kind' => match ($import['kind']) {
1 ✔
68
                                        'function' => 'function',
1 ✔
69
                                        'const' => 'const',
×
70
                                        default => 'class',
1 ✔
71
                                },
72
                                'name' => (string) $import['name'],
1 ✔
73
                                'alias' => $import['alias'] === null ? null : (string) $import['alias'],
1 ✔
74
                                'namespace' => (string) $import['namespace'],
1 ✔
75
                        ], is_array($data['removedImports']) ? $data['removedImports'] : [])),
1 ✔
76
                        mutatedRules: is_array($data['mutatedRules']) ? array_values(array_filter($data['mutatedRules'], self::isRule(...))) : [],
1 ✔
77
                );
78
        }
79

80

81
        /** @return array<string, mixed> */
82
        private static function encodeViolation(Violation $violation): array
83
        {
84
                return [
85
                        'decision' => $violation->decision,
1 ✔
86
                        'message' => $violation->message,
1 ✔
87
                        'line' => $violation->line,
1 ✔
88
                        'column' => $violation->column,
1 ✔
89
                        'severity' => $violation->severity->value,
1 ✔
90
                        'fingerprint' => $violation->fingerprint,
1 ✔
91
                        'fixable' => $violation->fixable,
1 ✔
92
                        'risk' => $violation->risk?->value,
1 ✔
93
                        'refused' => $violation->refused,
1 ✔
94
                        'because' => $violation->because,
1 ✔
95
                        'derivedFrom' => $violation->derivedFrom,
1 ✔
96
                        'offset' => $violation->offset,
1 ✔
97
                        'length' => $violation->length,
1 ✔
98
                        'originalLines' => $violation->originalLines,
1 ✔
99
                ];
100
        }
101

102

103
        /** @return list<Violation> */
104
        private static function decodeViolations(mixed $data): array
105
        {
106
                return array_values(array_map(fn(array $item) => new Violation(
1 ✔
107
                        (string) $item['decision'],
1 ✔
108
                        (string) $item['message'],
1 ✔
109
                        (int) $item['line'],
1 ✔
110
                        $item['column'] === null ? null : (int) $item['column'],
1 ✔
111
                        Severity::from((string) $item['severity']),
1 ✔
112
                        (string) $item['fingerprint'],
1 ✔
113
                        (bool) $item['fixable'],
1 ✔
114
                        $item['risk'] === null ? null : Risk::from((string) $item['risk']),
1 ✔
115
                        (bool) $item['refused'],
1 ✔
116
                        $item['because'] === null ? null : (string) $item['because'],
1 ✔
117
                        $item['derivedFrom'] === null ? null : (string) $item['derivedFrom'],
1 ✔
118
                        $item['offset'] === null ? null : (int) $item['offset'],
1 ✔
119
                        $item['length'] === null ? null : (int) $item['length'],
1 ✔
120
                        is_array($item['originalLines']) ? [(int) $item['originalLines'][0], (int) $item['originalLines'][1]] : null,
1 ✔
121
                ), is_array($data) ? $data : []));
1 ✔
122
        }
123

124

125
        /** @phpstan-assert-if-true class-string<Rule> $class */
126
        private static function isRule(mixed $class): bool
127
        {
128
                return is_string($class) && is_a($class, Rule::class, allow_string: true);
1 ✔
129
        }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc