v0.2.5-pre.010.fix.003
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_general_rules.py
|
||||
# version: 4
|
||||
# version: 5
|
||||
|
||||
"""Audit mechanically verifiable Rust normalization rules used by KSP."""
|
||||
|
||||
@@ -186,13 +186,6 @@ def preceding_doc_line(lines: list[str], index: int) -> bool:
|
||||
return cursor >= 0 and lines[cursor].lstrip().startswith("///")
|
||||
|
||||
|
||||
def export_symbol(line: str) -> str:
|
||||
"""Return the re-exported symbol name from one ungrouped re-export."""
|
||||
|
||||
path = line.split(" use ", 1)[1].split(";", 1)[0].strip()
|
||||
return path.rsplit("::", 1)[-1]
|
||||
|
||||
|
||||
def natural_key(value: str) -> tuple[tuple[int, object], ...]:
|
||||
"""Return a natural case-sensitive ordering key."""
|
||||
|
||||
@@ -523,12 +516,12 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]:
|
||||
for attribute in ("#![warn(missing_docs)]", "#![deny(unreachable_pub)]", "#![forbid(unsafe_code)]"):
|
||||
if attribute not in lines[:24]:
|
||||
violations.append(Violation("RUST-BASE-103", relative, 1, f"missing `{attribute}`"))
|
||||
exports: list[tuple[int, str, str]] = []
|
||||
exports: list[tuple[int, str]] = []
|
||||
for idx, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("pub use ") or stripped.startswith("pub(crate) use "):
|
||||
visibility = "pub(crate)" if stripped.startswith("pub(crate) use ") else "pub"
|
||||
exports.append((idx, visibility, export_symbol(stripped)))
|
||||
exports.append((idx, visibility))
|
||||
if not preceding_doc_line(lines, idx):
|
||||
violations.append(Violation("RUST-DOC-102", relative, idx, "crate-root re-export requires adjacent rustdoc"))
|
||||
source_match = re.match(r"^pub(?:\(crate\))?\s+use\s+(?:self::)?([A-Za-z_][A-Za-z0-9_]*)::", stripped)
|
||||
@@ -544,22 +537,21 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]:
|
||||
if blank_count != 1:
|
||||
violations.append(Violation("RUST-FMT-113", relative, crate_start, f"pub use and pub(crate) use blocks require exactly one blank line; found {blank_count}"))
|
||||
crate_seen = False
|
||||
previous_by_visibility: dict[str, tuple[int, str]] = {}
|
||||
for idx, visibility, symbol in exports:
|
||||
previous_by_visibility: dict[str, int] = {}
|
||||
for idx, visibility in exports:
|
||||
if visibility == "pub(crate)":
|
||||
crate_seen = True
|
||||
elif crate_seen:
|
||||
violations.append(Violation("RUST-FMT-105", relative, idx, "pub use block must precede pub(crate) use block"))
|
||||
previous = previous_by_visibility.get(visibility)
|
||||
if previous is not None:
|
||||
previous_idx, previous_symbol = previous
|
||||
previous_idx = previous_by_visibility.get(visibility)
|
||||
if previous_idx is not None:
|
||||
# One homogeneous block may contain rustdocs but no blank line.
|
||||
# rustfmt is authoritative for intra-block re-export ordering;
|
||||
# this audit must not impose a competing exported-symbol sort.
|
||||
between = lines[previous_idx:idx - 1]
|
||||
if any(not candidate.strip() for candidate in between):
|
||||
violations.append(Violation("RUST-FMT-106", relative, idx, f"{visibility} use block contains an empty line"))
|
||||
if natural_key(symbol) < natural_key(previous_symbol):
|
||||
violations.append(Violation("RUST-FMT-107", relative, idx, f"{visibility} use block is not alphabetically ordered by exported symbol"))
|
||||
previous_by_visibility[visibility] = (idx, symbol)
|
||||
previous_by_visibility[visibility] = idx
|
||||
violations.extend(audit_blank_lines_in_bodies(relative, lines, masked_lines, depths))
|
||||
violations.extend(audit_item_spacing_and_nesting(relative, lines, masked_lines, depths))
|
||||
violations.extend(audit_module_order(relative, lines, depths))
|
||||
|
||||
Reference in New Issue
Block a user