Skip to content

Commit a88ee34

Browse files
committed
refactor: separated XML processing and file reporting
1 parent 23be3fc commit a88ee34

35 files changed

Lines changed: 1361 additions & 992 deletions

src/Application.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public function run(): int
119119
$progress = $this->createProgress($options);
120120

121121
try {
122-
$report = new RunCoordinator($progress)->run($runPlan);
122+
$report = new RunCoordinator($progress, collectPerformance: $options['perf'])->runWithMetrics($runPlan);
123123
} catch (\Throwable $e) {
124124
$this->writeError('Runtime error: ' . $e->getMessage() . PHP_EOL);
125125

@@ -134,7 +134,7 @@ public function run(): int
134134

135135
$this->write($reporter->generate($report));
136136

137-
return (int) $report->hasViolations();
137+
return (int) $report->hasFinalViolations();
138138
}
139139

140140
/**

src/Fix/FixerException.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ public static function cannotFixInvalidContent(Violation $violation): self
2828
));
2929
}
3030

31-
public static function cannotReadFixedContent(): self
32-
{
33-
return new self('Cannot read fixed content when no fix application was attempted.');
34-
}
35-
3631
public static function invalidFixedXml(string $filePath): self
3732
{
3833
return new self(

src/Report/FileReport.php

Lines changed: 179 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,56 +9,215 @@
99

1010
final class FileReport
1111
{
12+
public private(set) float $totalSniffingTime = 0.0;
13+
14+
public private(set) float $totalFixingTime = 0.0;
15+
16+
/** @var array<string, float> */
17+
public private(set) array $sniffingTimes = [];
18+
19+
/** @var array<string, float> */
20+
public private(set) array $fixingTimes = [];
21+
22+
public private(set) int $fixingPasses = 0;
23+
24+
public private(set) bool $changed = false;
25+
26+
/** @var list<Violation> */
27+
public private(set) array $foundViolations;
28+
1229
/** @var list<Violation> */
13-
public private(set) array $violations = [];
30+
public private(set) array $finalViolations;
1431

1532
public function __construct(
1633
public readonly string $filePath,
34+
private readonly bool $collectPerformance = false,
1735
) {
1836
}
1937

20-
public function addViolation(Violation $violation): void
38+
public function markChanged(): void
2139
{
22-
$this->violations[] = $violation;
40+
$this->changed = true;
2341
}
2442

25-
/** @param list<Violation> $violations */
26-
public function addViolations(array $violations): void
43+
/** @throws ReportException if found violations were already added */
44+
public function addFailedViolation(Violation $violation): void
2745
{
28-
foreach ($violations as $violation) {
29-
$this->addViolation($violation);
46+
if (isset($this->foundViolations)) {
47+
throw ReportException::foundViolationsAlreadyAdded($this->filePath);
3048
}
49+
50+
$this->foundViolations = [$violation];
51+
$this->finalViolations = [$violation];
3152
}
3253

33-
/** @return list<Violation> */
34-
public function getViolations(): array
54+
/**
55+
* @param list<Violation> $violations
56+
* @throws ReportException if found violations were already added
57+
*/
58+
public function addFoundViolations(array $violations): void
3559
{
36-
return $this->violations;
60+
if (isset($this->foundViolations)) {
61+
throw ReportException::foundViolationsAlreadyAdded($this->filePath);
62+
}
63+
64+
$this->foundViolations = $violations;
65+
$this->finalViolations = $violations;
66+
}
67+
68+
public function getFoundViolationCount(): int
69+
{
70+
return isset($this->foundViolations) ? count($this->foundViolations) : 0;
3771
}
3872

39-
public function getViolationCount(): int
73+
/**
74+
* @param list<Violation> $violations
75+
* @throws ReportException if found violations were not added
76+
*/
77+
public function addFinalViolations(array $violations): void
4078
{
41-
return count($this->violations);
79+
if (!isset($this->foundViolations)) {
80+
throw ReportException::cannotSetFinalViolationsBeforeFoundViolations($this->filePath);
81+
}
82+
83+
$this->finalViolations = $violations;
4284
}
4385

44-
public function hasViolations(): bool
86+
public function hasFinalViolations(): bool
4587
{
46-
return $this->violations !== [];
88+
return isset($this->finalViolations) && $this->finalViolations !== [];
89+
}
90+
91+
public function getFinalViolationCount(): int
92+
{
93+
return isset($this->finalViolations) ? count($this->finalViolations) : 0;
94+
}
95+
96+
public function getAppliedFixesCount(): int
97+
{
98+
return $this->fixingPasses > 0
99+
? max(0, $this->getFoundViolationCount() - $this->getFinalViolationCount())
100+
: 0;
101+
}
102+
103+
public function getSkippedFixesCount(): int
104+
{
105+
return $this->fixingPasses > 0
106+
? $this->getFinalViolationCount()
107+
: 0;
108+
}
109+
110+
public function recordFixingPass(): void
111+
{
112+
$this->fixingPasses++;
47113
}
48114

49115
public function getErrorCount(): int
50116
{
51-
return array_filter(
52-
$this->violations,
53-
static fn(Violation $v): bool => $v->severity === Severity::ERROR,
54-
) |> count(...);
117+
return $this->countSeverity(Severity::ERROR);
55118
}
56119

57120
public function getWarningCount(): int
58121
{
122+
return $this->countSeverity(Severity::WARNING);
123+
}
124+
125+
public function getInfoCount(): int
126+
{
127+
return $this->countSeverity(Severity::INFO);
128+
}
129+
130+
/**
131+
* @template T
132+
* @param callable(): T $operation
133+
* @return T
134+
*/
135+
public function measureFixing(callable $operation): mixed
136+
{
137+
if (!$this->collectPerformance) {
138+
return $operation();
139+
}
140+
141+
$start = microtime(true);
142+
143+
try {
144+
return $operation();
145+
} finally {
146+
$this->totalFixingTime += microtime(true) - $start;
147+
}
148+
}
149+
150+
/**
151+
* @template T
152+
* @param callable(): T $operation
153+
* @return T
154+
*/
155+
public function measureFixer(string $sniffCode, callable $operation): mixed
156+
{
157+
if (!$this->collectPerformance) {
158+
return $operation();
159+
}
160+
161+
$start = microtime(true);
162+
163+
try {
164+
return $operation();
165+
} finally {
166+
$this->fixingTimes[$sniffCode] ??= 0.0;
167+
$this->fixingTimes[$sniffCode] += microtime(true) - $start;
168+
}
169+
}
170+
171+
/**
172+
* @template T
173+
* @param callable(): T $operation
174+
* @return T
175+
*/
176+
public function measureSniffing(callable $operation): mixed
177+
{
178+
if (!$this->collectPerformance) {
179+
return $operation();
180+
}
181+
182+
$start = microtime(true);
183+
184+
try {
185+
return $operation();
186+
} finally {
187+
$this->totalSniffingTime += microtime(true) - $start;
188+
}
189+
}
190+
191+
/**
192+
* @template T
193+
* @param callable(): T $operation
194+
* @return T
195+
*/
196+
public function measureSniffer(string $sniffCode, callable $operation): mixed
197+
{
198+
if (!$this->collectPerformance) {
199+
return $operation();
200+
}
201+
202+
$start = microtime(true);
203+
204+
try {
205+
return $operation();
206+
} finally {
207+
$this->sniffingTimes[$sniffCode] ??= 0.0;
208+
$this->sniffingTimes[$sniffCode] += microtime(true) - $start;
209+
}
210+
}
211+
212+
private function countSeverity(Severity $severity): int
213+
{
214+
if (!isset($this->finalViolations)) {
215+
return 0;
216+
}
217+
59218
return array_filter(
60-
$this->violations,
61-
static fn(Violation $v): bool => $v->severity === Severity::WARNING,
219+
$this->finalViolations,
220+
static fn(Violation $violation): bool => $violation->severity === $severity,
62221
) |> count(...);
63222
}
64223
}

0 commit comments

Comments
 (0)