diff --git a/src/models/finding.py b/src/models/finding.py new file mode 100644 index 0000000..f75a1cc --- /dev/null +++ b/src/models/finding.py @@ -0,0 +1,70 @@ +"""Finding model for validation results.""" + +import re +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class Finding: + """Represents a validation finding.""" + + rule_id: str + rule_name: str + severity: str + message: str + suggestion: str = "" + line_number: Optional[int] = None + column: Optional[int] = None + matched_text: str = "" + context: str = "" + + def to_dict(self) -> dict: + """Convert finding to dictionary.""" + return { + "rule_id": self.rule_id, + "rule_name": self.rule_name, + "severity": self.severity, + "message": self.message, + "suggestion": self.suggestion, + "line_number": self.line_number, + "column": self.column, + "matched_text": self.matched_text, + "context": self.context, + } + + @classmethod + def from_match( + cls, + rule, + match: re.Match[str], + line_number: Optional[int] = None, + context: str = "", + ) -> "Finding": + """Create a Finding from a regex match.""" + return cls( + rule_id=rule.id, + rule_name=rule.name, + severity=rule.severity, + message=rule.message, + suggestion=rule.suggestion, + line_number=line_number, + column=match.start() + 1 if match.start() >= 0 else None, + matched_text=match.group(0), + context=context, + ) + + @classmethod + def from_dict(cls, data: dict) -> "Finding": + """Create a Finding from a dictionary.""" + return cls( + rule_id=data["rule_id"], + rule_name=data["rule_name"], + severity=data["severity"], + message=data["message"], + suggestion=data.get("suggestion", ""), + line_number=data.get("line_number"), + column=data.get("column"), + matched_text=data.get("matched_text", ""), + context=data.get("context", ""), + )