80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""诊断系统 — 收集编译过程中的警告和错误
|
|
|
|
替代原先静默回退的模式:
|
|
- return 'i32' → 记录 Warning + 回退到 'i32'
|
|
- return [] → 记录 Error + 回退到 []
|
|
|
|
使用方式:
|
|
diag = DiagnosticCollector()
|
|
diag.warn(file, lineno, "无法解析类型,回退到 i32")
|
|
diag.error(file, lineno, f"加载模块失败: {path}")
|
|
diag.report() # 打印所有诊断信息
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass, field
|
|
from enum import Enum
|
|
from typing import List, Optional
|
|
|
|
|
|
class DiagnosticLevel(Enum):
|
|
WARNING = "WARNING"
|
|
ERROR = "ERROR"
|
|
|
|
|
|
@dataclass
|
|
class Diagnostic:
|
|
level: DiagnosticLevel
|
|
file: str
|
|
lineno: int
|
|
message: str
|
|
|
|
def __str__(self):
|
|
short_file = os.path.basename(self.file) if self.file else "<unknown>"
|
|
return f"[{self.level.value}] {short_file}:{self.lineno} — {self.message}"
|
|
|
|
|
|
class DiagnosticCollector:
|
|
"""诊断信息收集器"""
|
|
|
|
def __init__(self):
|
|
self._diagnostics: List[Diagnostic] = []
|
|
|
|
def warn(self, file: str, lineno: int, message: str):
|
|
self._diagnostics.append(Diagnostic(DiagnosticLevel.WARNING, file, lineno, message))
|
|
|
|
def error(self, file: str, lineno: int, message: str):
|
|
self._diagnostics.append(Diagnostic(DiagnosticLevel.ERROR, file, lineno, message))
|
|
|
|
@property
|
|
def warnings(self) -> List[Diagnostic]:
|
|
return [d for d in self._diagnostics if d.level == DiagnosticLevel.WARNING]
|
|
|
|
@property
|
|
def errors(self) -> List[Diagnostic]:
|
|
return [d for d in self._diagnostics if d.level == DiagnosticLevel.ERROR]
|
|
|
|
@property
|
|
def has_errors(self) -> bool:
|
|
return any(d.level == DiagnosticLevel.ERROR for d in self._diagnostics)
|
|
|
|
@property
|
|
def has_warnings(self) -> bool:
|
|
return any(d.level == DiagnosticLevel.WARNING for d in self._diagnostics)
|
|
|
|
def report(self, min_level: DiagnosticLevel = DiagnosticLevel.WARNING):
|
|
"""打印所有诊断信息"""
|
|
for d in self._diagnostics:
|
|
if d.level.value >= min_level.value:
|
|
print(d)
|
|
|
|
def clear(self):
|
|
self._diagnostics.clear()
|
|
|
|
def __len__(self):
|
|
return len(self._diagnostics)
|
|
|
|
def __bool__(self):
|
|
return len(self._diagnostics) > 0
|