feat: add ErrorContextAnalyser for sliding-window error/warning surfacing
Walks Entry[] once and emits one ErrorContextProblem per ERROR or WARNING entry, attaching up to 20 entries before and 20 after as context. Overlapping windows clip the second hit's before- and after-ranges so no Entry appears in two context arrays. Caps emission at 500 hits and adds an ErrorContextTruncatedInformation when reached. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
130
src/Analysis/ProjectZomboid/ErrorContextProblem.php
Normal file
130
src/Analysis/ProjectZomboid/ErrorContextProblem.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace IndifferentKetchup\Codex\Analysis\ProjectZomboid;
|
||||
|
||||
use IndifferentKetchup\Codex\Analysis\InsightInterface;
|
||||
use IndifferentKetchup\Codex\Analysis\Problem;
|
||||
use IndifferentKetchup\Codex\Log\EntryInterface;
|
||||
|
||||
/**
|
||||
* Problem emitted by ErrorContextAnalyser for each ERROR or WARNING entry,
|
||||
* carrying a sliding window of surrounding entries as before/after
|
||||
* context. Coalesced by 1-based entryIndex so re-adding the same hit
|
||||
* never produces duplicate problems.
|
||||
*/
|
||||
class ErrorContextProblem extends Problem
|
||||
{
|
||||
private string $type = 'error';
|
||||
private int $entryIndex = 0;
|
||||
|
||||
/**
|
||||
* @var EntryInterface[]
|
||||
*/
|
||||
private array $before = [];
|
||||
|
||||
/**
|
||||
* @var EntryInterface[]
|
||||
*/
|
||||
private array $after = [];
|
||||
|
||||
/**
|
||||
* @param string $type 'error' or 'warning'
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $entryIndex 1-based index of the hit entry within the log
|
||||
* @return $this
|
||||
*/
|
||||
public function setEntryIndex(int $entryIndex): static
|
||||
{
|
||||
$this->entryIndex = $entryIndex;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int 1-based index of the hit entry within the log
|
||||
*/
|
||||
public function getEntryIndex(): int
|
||||
{
|
||||
return $this->entryIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryInterface[] $entries
|
||||
* @return $this
|
||||
*/
|
||||
public function setBefore(array $entries): static
|
||||
{
|
||||
$this->before = $entries;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntryInterface[]
|
||||
*/
|
||||
public function getBefore(): array
|
||||
{
|
||||
return $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntryInterface[] $entries
|
||||
* @return $this
|
||||
*/
|
||||
public function setAfter(array $entries): static
|
||||
{
|
||||
$this->after = $entries;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntryInterface[]
|
||||
*/
|
||||
public function getAfter(): array
|
||||
{
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience accessor returning before-context, hit entry, and
|
||||
* after-context as a single ordered array of at most
|
||||
* ErrorContextAnalyser::CONTEXT_BEFORE + 1 + CONTEXT_AFTER = 41
|
||||
* entries.
|
||||
*
|
||||
* @return EntryInterface[]
|
||||
*/
|
||||
public function getContext(): array
|
||||
{
|
||||
return [...$this->before, $this->getEntry(), ...$this->after];
|
||||
}
|
||||
|
||||
public function getMessage(): string
|
||||
{
|
||||
return sprintf(
|
||||
'%s at entry %d (%d before, %d after)',
|
||||
strtoupper($this->type),
|
||||
$this->entryIndex,
|
||||
count($this->before),
|
||||
count($this->after)
|
||||
);
|
||||
}
|
||||
|
||||
public function isEqual(InsightInterface $insight): bool
|
||||
{
|
||||
return $insight instanceof self && $insight->getEntryIndex() === $this->entryIndex;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user