Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions src/processors/cargo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@

from .. import config
from .base import Processor
from .utils import (
RUST_COMPILING_RE,
RUST_ERROR_START_RE,
RUST_FINISHED_RE,
RUST_SPAN_LINE_RE,
RUST_WARNING_START_RE,
RUST_WARNING_SUMMARY_RE,
)

_CARGO_CMD_RE = re.compile(r"\bcargo\s+(build|check|doc|update|bench)\b")
_COMPILING_RE = re.compile(r"^\s*Compiling\s+\S+\s+v")
_DOWNLOADING_RE = re.compile(r"^\s*Downloading\s+\S+\s+v")
_DOCUMENTING_RE = re.compile(r"^\s*Documenting\s+\S+\s+v")
_RUNNING_RE = re.compile(r"^\s*Running\s+")
_FINISHED_RE = re.compile(r"^\s*Finished\s+")
_WARNING_START_RE = re.compile(r"^warning(?:\[(\S+)\])?:\s+(.+)")
_ERROR_START_RE = re.compile(r"^error(?:\[(\S+)\])?:\s+(.+)")
_SPAN_LINE_RE = re.compile(r"^\s*(-->|\d+\s*\||=\s+)")
_WARNING_SUMMARY_RE = re.compile(r"^warning:\s+.+generated\s+\d+\s+warning")
_UPDATE_LINE_RE = re.compile(
r"^\s*(Updating|Removing|Adding)\s+(\S+)\s+v([\d.]+)(?:\s*->\s*v([\d.]+))?"
)
Expand Down Expand Up @@ -89,15 +91,15 @@ def _process_cargo_build(self, output: str) -> str:
for line in lines:
stripped = line.strip()

if _COMPILING_RE.match(stripped):
if RUST_COMPILING_RE.match(stripped):
compiling_count += 1
continue
if _DOWNLOADING_RE.match(stripped):
downloading_count += 1
continue

# Error start
if _ERROR_START_RE.match(stripped):
if RUST_ERROR_START_RE.match(stripped):
# Flush current warning block
if current_type and current_block:
warnings_by_type[current_type].append(current_block)
Expand All @@ -111,8 +113,8 @@ def _process_cargo_build(self, output: str) -> str:
continue

# Warning start
wm = _WARNING_START_RE.match(stripped)
if wm and not _WARNING_SUMMARY_RE.match(stripped):
wm = RUST_WARNING_START_RE.match(stripped)
if wm and not RUST_WARNING_SUMMARY_RE.match(stripped):
# Flush previous
if in_error and current_error:
error_blocks.append(current_error)
Expand All @@ -127,7 +129,7 @@ def _process_cargo_build(self, output: str) -> str:
current_block = [line]
continue

if _WARNING_SUMMARY_RE.match(stripped):
if RUST_WARNING_SUMMARY_RE.match(stripped):
if current_type and current_block:
warnings_by_type[current_type].append(current_block)
current_block = []
Expand All @@ -139,7 +141,7 @@ def _process_cargo_build(self, output: str) -> str:
warning_summary_lines.append(line)
continue

if _FINISHED_RE.match(stripped):
if RUST_FINISHED_RE.match(stripped):
if current_type and current_block:
warnings_by_type[current_type].append(current_block)
current_block = []
Expand Down Expand Up @@ -201,16 +203,16 @@ def _process_cargo_doc(self, output: str) -> str:

for line in lines:
stripped = line.strip()
if _COMPILING_RE.match(stripped):
if RUST_COMPILING_RE.match(stripped):
compiling_count += 1
elif _DOCUMENTING_RE.match(stripped):
documenting_count += 1
elif (
_FINISHED_RE.match(stripped)
RUST_FINISHED_RE.match(stripped)
or re.match(r"^\s*Generated\s+", stripped)
or re.search(r"\bwarning\b", stripped)
or _ERROR_START_RE.match(stripped)
or (_SPAN_LINE_RE.match(stripped) and result)
or RUST_ERROR_START_RE.match(stripped)
or (RUST_SPAN_LINE_RE.match(stripped) and result)
):
result.append(line)

Expand Down Expand Up @@ -274,15 +276,15 @@ def _process_cargo_bench(self, output: str) -> str:

for line in lines:
stripped = line.strip()
if _COMPILING_RE.match(stripped):
if RUST_COMPILING_RE.match(stripped):
compiling_count += 1
elif _RUNNING_RE.match(stripped):
continue
elif (
re.match(r"^test\s+.+\s+bench:", stripped)
or re.match(r"^test result:", stripped)
or _FINISHED_RE.match(stripped)
or _ERROR_START_RE.match(stripped)
or RUST_FINISHED_RE.match(stripped)
or RUST_ERROR_START_RE.match(stripped)
):
result.append(line)

Expand Down
25 changes: 13 additions & 12 deletions src/processors/cargo_clippy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@

from .. import config
from .base import Processor
from .utils import (
RUST_COMPILING_RE,
RUST_ERROR_START_RE,
RUST_FINISHED_RE,
RUST_WARNING_START_RE,
RUST_WARNING_SUMMARY_RE,
)

_CLIPPY_CMD_RE = re.compile(r"\bcargo\s+clippy\b")
_WARNING_START_RE = re.compile(r"^warning(?:\[(\S+)\])?:\s+(.+)")
_ERROR_START_RE = re.compile(r"^error(?:\[(\S+)\])?:\s+(.+)")
_SPAN_LINE_RE = re.compile(r"^\s*(-->|\d+\s*\||=\s+)")
_WARNING_SUMMARY_RE = re.compile(r"^warning:\s+.+generated\s+\d+\s+warning")
_FINISHED_RE = re.compile(r"^\s*Finished\s+")
_CHECKING_RE = re.compile(r"^\s*Checking\s+\S+\s+v")
_COMPILING_RE = re.compile(r"^\s*Compiling\s+\S+\s+v")

# Clippy lint categories
_CLIPPY_CATEGORIES = {
Expand Down Expand Up @@ -83,12 +84,12 @@ def process(self, command: str, output: str) -> str:
if _CHECKING_RE.match(stripped):
checking_count += 1
continue
if _COMPILING_RE.match(stripped):
if RUST_COMPILING_RE.match(stripped):
compiling_count += 1
continue

# Error start
if _ERROR_START_RE.match(stripped):
if RUST_ERROR_START_RE.match(stripped):
# Flush current warning block
if current_rule and current_block:
warnings_by_rule[current_rule].append(current_block)
Expand All @@ -102,8 +103,8 @@ def process(self, command: str, output: str) -> str:
continue

# Warning start
wm = _WARNING_START_RE.match(stripped)
if wm and not _WARNING_SUMMARY_RE.match(stripped):
wm = RUST_WARNING_START_RE.match(stripped)
if wm and not RUST_WARNING_SUMMARY_RE.match(stripped):
# Flush previous
if in_error and current_error:
error_blocks.append(current_error)
Expand All @@ -117,7 +118,7 @@ def process(self, command: str, output: str) -> str:
current_block = [line]
continue

if _WARNING_SUMMARY_RE.match(stripped):
if RUST_WARNING_SUMMARY_RE.match(stripped):
if current_rule and current_block:
warnings_by_rule[current_rule].append(current_block)
current_block = []
Expand All @@ -129,7 +130,7 @@ def process(self, command: str, output: str) -> str:
summary_lines.append(line)
continue

if _FINISHED_RE.match(stripped):
if RUST_FINISHED_RE.match(stripped):
if current_rule and current_block:
warnings_by_rule[current_rule].append(current_block)
current_block = []
Expand Down
33 changes: 9 additions & 24 deletions src/processors/file_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ def _compress_yarn_lock(self, lines: list[str], total: int) -> str:
result.append(f" ... ({len(deps) - 50} more)")
return "\n".join(result)

def _compress_poetry_lock(self, lines: list[str], total: int) -> str:
"""poetry.lock: extract [[package]] name and version."""
def _compress_toml_lock(self, lines: list[str], total: int, label: str) -> str:
"""Extract [[package]] name and version from TOML lock files (poetry.lock, Cargo.lock)."""
deps = []
current_name = None
for line in lines:
Expand All @@ -417,35 +417,20 @@ def _compress_poetry_lock(self, lines: list[str], total: int) -> str:
deps.append(f"{current_name}@{val}")
current_name = None

result = [f"poetry.lock ({len(deps)} packages, {total} lines):"]
result = [f"{label} ({len(deps)} packages, {total} lines):"]
for d in deps[:50]:
result.append(f" {d}")
if len(deps) > 50:
result.append(f" ... ({len(deps) - 50} more)")
return "\n".join(result)

def _compress_poetry_lock(self, lines: list[str], total: int) -> str:
"""poetry.lock: extract [[package]] name and version."""
return self._compress_toml_lock(lines, total, "poetry.lock")

def _compress_cargo_lock(self, lines: list[str], total: int) -> str:
"""Cargo.lock: extract [[package]] name and version."""
deps = []
current_name = None
for line in lines:
stripped = line.strip()
if stripped == "[[package]]":
current_name = None
elif stripped.startswith("name = "):
val = stripped.split('"')[1] if '"' in stripped else stripped.split("=")[1].strip()
current_name = val
elif stripped.startswith("version = ") and current_name:
val = stripped.split('"')[1] if '"' in stripped else stripped.split("=")[1].strip()
deps.append(f"{current_name}@{val}")
current_name = None

result = [f"Cargo.lock ({len(deps)} packages, {total} lines):"]
for d in deps[:50]:
result.append(f" {d}")
if len(deps) > 50:
result.append(f" ... ({len(deps) - 50} more)")
return "\n".join(result)
return self._compress_toml_lock(lines, total, "Cargo.lock")

def _compress_json_lock(self, raw: str, total: int) -> str:
"""composer.lock / Pipfile.lock: extract package names + versions from JSON."""
Expand All @@ -465,7 +450,7 @@ def _compress_json_lock(self, raw: str, total: int) -> str:
for section in ("default", "develop"):
for name, info in data.get(section, {}).items():
version = info.get("version", "?") if isinstance(info, dict) else "?"
deps.append(f"{name}{version}")
deps.append(f"{name}@{version}")

result = [f"lock file ({len(deps)} packages, {total} lines):"]
for d in deps[:50]:
Expand Down
2 changes: 1 addition & 1 deletion src/processors/file_listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def _process_tree(self, output: str) -> str:
# Find the summary line (usually last line like "X directories, Y files")
summary = ""
for line in reversed(lines):
if re.match(r"\d+\s+director", line):
if re.match(r"\d+\s+director(?:ies|y)\b", line):
summary = line
break

Expand Down
2 changes: 1 addition & 1 deletion src/processors/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,6 @@ def _truncate_middle(self, lines: list[str]) -> list[str]:
removed = total - keep_head - keep_tail
return [
*lines[:keep_head],
f"\n... ({removed} lines truncated, {total} total) ...\n",
f"... ({removed} lines truncated, {total} total) ...",
*lines[-keep_tail:],
]
8 changes: 8 additions & 0 deletions src/processors/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
import re
from collections import defaultdict

# Shared Rust compiler output patterns (used by cargo and cargo_clippy processors)
RUST_WARNING_START_RE = re.compile(r"^warning(?:\[(\S+)\])?:\s+(.+)")
RUST_ERROR_START_RE = re.compile(r"^error(?:\[(\S+)\])?:\s+(.+)")
RUST_SPAN_LINE_RE = re.compile(r"^\s*(-->|\d+\s*\||=\s+)")
RUST_WARNING_SUMMARY_RE = re.compile(r"^warning:\s+.+generated\s+\d+\s+warning")
RUST_FINISHED_RE = re.compile(r"^\s*Finished\s+")
RUST_COMPILING_RE = re.compile(r"^\s*Compiling\s+\S+\s+v")

_DEFAULT_ERROR_RE = re.compile(
r"\b(error|Error|ERROR|exception|Exception|EXCEPTION|"
r"fatal|Fatal|FATAL|panic|Panic|PANIC|traceback|Traceback)\b"
Expand Down
Loading