From 7eccf595583c03f693af55284fb02f9caee7f859 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Mon, 8 Jun 2026 13:38:35 +0200 Subject: [PATCH] feat(checker): add reporter class --- midas/checker/diagnostic.py | 16 +++++++--- midas/checker/reporter.py | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 midas/checker/reporter.py diff --git a/midas/checker/diagnostic.py b/midas/checker/diagnostic.py index 77f687e..2925653 100644 --- a/midas/checker/diagnostic.py +++ b/midas/checker/diagnostic.py @@ -14,7 +14,7 @@ class DiagnosticType(StrEnum): @dataclass(frozen=True) class Diagnostic: - file_path: Path + file_path: Optional[str | Path] location: Location type: DiagnosticType message: str @@ -28,10 +28,16 @@ class Diagnostic: and self.location.end_col_offset is not None ): end_loc = f"L{self.location.end_lineno}:{self.location.end_col_offset+1}" - loc: str = ( - f"at {start_loc}" if end_loc is None else f"from {start_loc} to {end_loc}" - ) - return f"{self.type} in {self.file_path} {loc}" + + loc: str = "" + if self.file_path is not None: + loc += f" in {self.file_path}" + if end_loc is None: + loc += f" at {start_loc}" + else: + loc += f" from {start_loc} to {end_loc}" + + return f"{self.type}{loc}" def __str__(self) -> str: return f"{self.location_str}: {self.message}" diff --git a/midas/checker/reporter.py b/midas/checker/reporter.py new file mode 100644 index 0000000..b68766a --- /dev/null +++ b/midas/checker/reporter.py @@ -0,0 +1,63 @@ +from __future__ import annotations + +from typing import Optional + +from midas.ast.location import Location +from midas.checker.diagnostic import Diagnostic, DiagnosticType + + +class Reporter: + def __init__(self): + self.diagnostics: list[Diagnostic] = [] + + def report( + self, + path: Optional[str], + type: DiagnosticType, + location: Location, + message: str, + ): + self.diagnostics.append( + Diagnostic( + file_path=path, + location=location, + type=type, + message=message, + ) + ) + + def for_file(self, path: Optional[str]) -> FileReporter: + return FileReporter(self, path) + + +class FileReporter: + def __init__(self, base_reporter: Reporter, path: Optional[str]) -> None: + self.base_reporter: Reporter = base_reporter + self.path: Optional[str] = path + + def for_file(self, path: Optional[str]) -> FileReporter: + return FileReporter(self.base_reporter, path) + + def report(self, type: DiagnosticType, location: Location, message: str): + self.base_reporter.report(self.path, type, location, message) + + def error(self, location: Location, message: str): + self.report( + type=DiagnosticType.ERROR, + location=location, + message=message, + ) + + def warning(self, location: Location, message: str): + self.report( + type=DiagnosticType.WARNING, + location=location, + message=message, + ) + + def info(self, location: Location, message: str): + self.report( + type=DiagnosticType.INFO, + location=location, + message=message, + )