Initial upload: ErrorFix CLI with rule engine and pattern matching
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-02-01 03:56:25 +00:00
parent b7b4174169
commit e671b76452

View File

@@ -0,0 +1,139 @@
from abc import ABC, abstractmethod
from typing import List, TextIO, Dict, Any
from errorfix.patterns import MatchResult
class Formatter(ABC):
@abstractmethod
def format(self, results: List[MatchResult], error_text: str) -> str:
pass
@abstractmethod
def write(self, results: List[MatchResult], error_text: str, output: TextIO):
pass
class TextFormatter(Formatter):
def __init__(self, use_colors: bool = True):
self.use_colors = use_colors
self._colors = {
'reset': '\033[0m',
'red': '\033[31m',
'green': '\033[32m',
'yellow': '\033[33m',
'blue': '\033[34m',
'magenta': '\033[35m',
}
def _color(self, text: str, color: str) -> str:
if not self.use_colors:
return text
return f"{self._colors.get(color, '')}{text}{self._colors['reset']}"
def format(self, results: List[MatchResult], error_text: str) -> str:
if not results:
return self._format_no_match(error_text)
output = []
for i, result in enumerate(results, 1):
output.append(self._format_result(i, result))
return '\n'.join(output)
def _format_result(self, index: int, result: MatchResult) -> str:
lines = []
lines.append(self._color(f"Fix #{index}: {result.rule.name}", 'magenta'))
lines.append(self._color("-" * 50, 'blue'))
lines.append(f"Rule ID: {result.rule.id}")
lines.append(f"Description: {result.rule.description}")
lines.append(f"Severity: {result.rule.severity.value}")
if result.rule.language:
lines.append(f"Language: {result.rule.language}")
if result.rule.tool:
lines.append(f"Tool: {result.rule.tool}")
lines.append("")
lines.append(self._color("Matched:", 'yellow'))
lines.append(result.matched_text)
lines.append("")
lines.append(self._color("Suggested Fix:", 'green'))
fix = result.apply_fix()
lines.append(fix)
if result.groups:
lines.append("")
lines.append(self._color("Captured Variables:", 'yellow'))
for key, value in result.groups.items():
lines.append(f" {key} = {value}")
return '\n'.join(lines)
def _format_no_match(self, error_text: str) -> str:
lines = []
lines.append(self._color("No matching rules found", 'yellow'))
lines.append("-" * 50)
lines.append("Error text:")
lines.append(error_text[:200] + "..." if len(error_text) > 200 else error_text)
lines.append("")
lines.append("Suggestions:")
lines.append(" - Check if the correct rule files are loaded")
lines.append(" - Verify the error pattern matches any known rules")
lines.append(" - Add a custom rule for this error type")
return '\n'.join(lines)
def write(self, results: List[MatchResult], error_text: str, output: TextIO):
output.write(self.format(results, error_text))
class JSONFormatter(Formatter):
def __init__(self, pretty: bool = True):
self.pretty = pretty
def format(self, results: List[MatchResult], error_text: str) -> str:
data = self._to_dict(results, error_text)
if self.pretty:
import json
return json.dumps(data, indent=2)
import json
return json.dumps(data)
def _to_dict(self, results: List[MatchResult], error_text: str) -> Dict[str, Any]:
return {
'input_text': error_text,
'match_count': len(results),
'matches': [
{
'rule': {
'id': r.rule.id,
'name': r.rule.name,
'description': r.rule.description,
'severity': r.rule.severity.value if hasattr(r.rule.severity, 'value') else str(r.rule.severity),
'language': r.rule.language,
'tool': r.rule.tool,
'tags': r.rule.tags,
},
'matched_text': r.matched_text,
'captured_variables': r.groups,
'suggested_fix': r.apply_fix(),
}
for r in results
]
}
def write(self, results: List[MatchResult], error_text: str, output: TextIO):
output.write(self.format(results, error_text))
class StructuredFormatter(Formatter):
def format(self, results: List[MatchResult], error_text: str) -> str:
output = []
for result in results:
output.append({
'rule_id': result.rule.id,
'rule_name': result.rule.name,
'match': result.matched_text,
'fix': result.apply_fix(),
'variables': result.groups,
})
return str(output)
def write(self, results: List[MatchResult], error_text: str, output: TextIO):
output.write(self.format(results, error_text))