0.0.1-alpha.3
This commit is contained in:
83
scripts/audit_rust_blank_lines.py
Normal file
83
scripts/audit_rust_blank_lines.py
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_blank_lines.py
|
||||
# version: 1
|
||||
|
||||
"""Audit blank-line spacing in explicitly selected Rust sources."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
from _rust_audit_common import line_depths, mask_source, selected_files
|
||||
|
||||
_BODY = re.compile(r"^\s*(?:(?:pub(?:\([^)]*\))?|async|const|unsafe|extern|default)\s+)*(fn|struct|enum)\b")
|
||||
|
||||
|
||||
def audit_file(path: pathlib.Path) -> list[str]:
|
||||
"""Check successive empty lines and empty function/struct/enum body lines."""
|
||||
|
||||
text = path.read_text(encoding="utf-8")
|
||||
lines = text.splitlines()
|
||||
masked, protected = mask_source(text)
|
||||
masked_lines = masked.splitlines()
|
||||
depths = line_depths(masked)
|
||||
errors: list[str] = []
|
||||
previous_blank = False
|
||||
pending: tuple[str, int] | None = None
|
||||
active: tuple[str, int] | None = None
|
||||
|
||||
for number, (original, code, depth) in enumerate(zip(lines, masked_lines, depths, strict=True), 1):
|
||||
blank = not original.strip() and number not in protected
|
||||
if blank and previous_blank:
|
||||
errors.append(f"{path}:{number}: consecutive blank Rust source lines")
|
||||
previous_blank = blank
|
||||
|
||||
if active is not None and depth <= active[1]:
|
||||
active = None
|
||||
if active is not None and blank:
|
||||
errors.append(f"{path}:{number}: blank line inside {active[0]} body")
|
||||
|
||||
if active is None and pending is None:
|
||||
match = _BODY.match(code)
|
||||
if match is not None:
|
||||
pending = (match.group(1), depth)
|
||||
if pending is not None:
|
||||
if "{" in code:
|
||||
active = pending
|
||||
pending = None
|
||||
elif ";" in code:
|
||||
pending = None
|
||||
return errors
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Run the read-only spacing audit on explicitly selected Rust files."""
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("paths", nargs="+", help="Rust files or directories to inspect")
|
||||
args = parser.parse_args()
|
||||
files, errors = selected_files(args.paths)
|
||||
if errors or not files:
|
||||
for error in errors or ["no Rust files selected"]:
|
||||
print(f"Rust blank-line audit: {error}", file=sys.stderr)
|
||||
return 2
|
||||
for path in files:
|
||||
try:
|
||||
errors.extend(audit_file(path))
|
||||
except (OSError, UnicodeError) as error:
|
||||
print(f"Rust blank-line audit: cannot read {path}: {error}", file=sys.stderr)
|
||||
return 2
|
||||
for error in errors:
|
||||
print(error, file=sys.stderr)
|
||||
if errors:
|
||||
print(f"Rust blank-line audit: {len(errors)} error(s) across {len(files)} file(s)", file=sys.stderr)
|
||||
return 1
|
||||
print(f"Rust blank-line audit: clean ({len(files)} file(s))")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user