mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-14 09:18:04 -05:00
80 lines
2.2 KiB
Python
80 lines
2.2 KiB
Python
from abc import ABC, abstractmethod
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class LintResult(BaseModel):
|
|
file: str
|
|
line: int # 1-indexed
|
|
column: int # 1-indexed
|
|
message: str
|
|
|
|
def visualize(self, half_window: int = 3) -> str:
|
|
"""Visualize the lint result by print out all the lines where the lint result is found.
|
|
|
|
Args:
|
|
half_window: The number of context lines to display around the error on each side.
|
|
"""
|
|
with open(self.file, 'r') as f:
|
|
file_lines = f.readlines()
|
|
|
|
# Add line numbers
|
|
_span_size = len(str(len(file_lines)))
|
|
file_lines = [
|
|
f'{i + 1:>{_span_size}}|{line.rstrip()}'
|
|
for i, line in enumerate(file_lines)
|
|
]
|
|
|
|
# Get the window of lines to display
|
|
assert self.line <= len(file_lines) and self.line > 0
|
|
line_idx = self.line - 1
|
|
begin_window = max(0, line_idx - half_window)
|
|
end_window = min(len(file_lines), line_idx + half_window + 1)
|
|
|
|
selected_lines = file_lines[begin_window:end_window]
|
|
line_idx_in_window = line_idx - begin_window
|
|
|
|
# Add character hint
|
|
_character_hint = (
|
|
_span_size * ' '
|
|
+ ' ' * (self.column)
|
|
+ '^'
|
|
+ ' ERROR HERE: '
|
|
+ self.message
|
|
)
|
|
selected_lines[line_idx_in_window] = (
|
|
f'\033[91m{selected_lines[line_idx_in_window]}\033[0m'
|
|
+ '\n'
|
|
+ _character_hint
|
|
)
|
|
return '\n'.join(selected_lines)
|
|
|
|
|
|
class LinterException(Exception):
|
|
"""Base class for all linter exceptions."""
|
|
|
|
pass
|
|
|
|
|
|
class BaseLinter(ABC):
|
|
"""Base class for all linters.
|
|
|
|
Each linter should be able to lint files of a specific type and return a list of (parsed) lint results.
|
|
"""
|
|
|
|
encoding: str = 'utf-8'
|
|
|
|
@property
|
|
@abstractmethod
|
|
def supported_extensions(self) -> list[str]:
|
|
"""The file extensions that this linter supports, such as .py or .tsx."""
|
|
return []
|
|
|
|
@abstractmethod
|
|
def lint(self, file_path: str) -> list[LintResult]:
|
|
"""Lint the given file.
|
|
|
|
file_path: The path to the file to lint. Required to be absolute.
|
|
"""
|
|
pass
|