Coverage for lintro / parsers / oxfmt / oxfmt_parser.py: 90%
29 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Parser for oxfmt output.
3Handles oxfmt CLI output in --list-different mode which outputs
4one file path per line for files that need formatting.
5"""
7from loguru import logger
9from lintro.parsers.base_parser import strip_ansi_codes
10from lintro.parsers.oxfmt.oxfmt_issue import OxfmtIssue
12# Known error message patterns from oxfmt that should be ignored
13_ERROR_PATTERNS: tuple[str, ...] = (
14 "Expected at least one target file",
15 "error:",
16 "Error:",
17 "ERROR:",
18 "warning:",
19 "Warning:",
20 "WARNING:",
21 "Usage:",
22 "usage:",
23 "USAGE:",
24)
26# Valid file extensions that oxfmt processes
27_VALID_EXTENSIONS: tuple[str, ...] = (
28 ".js",
29 ".mjs",
30 ".cjs",
31 ".jsx",
32 ".ts",
33 ".mts",
34 ".cts",
35 ".tsx",
36 ".vue",
37)
40def _is_valid_file_path(line: str) -> bool:
41 """Check if a line looks like a valid file path that oxfmt would process.
43 Args:
44 line: The line to check.
46 Returns:
47 True if the line appears to be a valid file path, False otherwise.
48 """
49 # Skip known error message patterns
50 for pattern in _ERROR_PATTERNS:
51 if pattern in line:
52 return False
54 # Check if it has a valid extension
55 lower_line = line.lower()
56 return any(lower_line.endswith(ext) for ext in _VALID_EXTENSIONS)
59def parse_oxfmt_output(output: str | None) -> list[OxfmtIssue]:
60 """Parse oxfmt output into a list of OxfmtIssue objects.
62 Args:
63 output: The raw output from oxfmt --list-different.
65 Returns:
66 List of OxfmtIssue objects for each file needing formatting.
67 """
68 issues: list[OxfmtIssue] = []
70 if not output:
71 return issues
73 # Normalize output by stripping ANSI escape sequences
74 normalized_output = strip_ansi_codes(output)
76 for line in normalized_output.splitlines():
77 try:
78 line = line.strip()
79 if not line:
80 continue
82 # Skip lines that don't look like valid file paths
83 if not _is_valid_file_path(line):
84 logger.debug(f"Skipping non-file-path line from oxfmt: '{line}'")
85 continue
87 # Each valid line is a file path that needs formatting
88 issues.append(
89 OxfmtIssue(
90 file=line,
91 line=1,
92 column=1,
93 message="File is not formatted",
94 ),
95 )
96 except (AttributeError, TypeError) as e:
97 logger.debug(f"Failed to parse oxfmt line '{line}': {e}")
98 continue
100 return issues