46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
import re
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
HEADER_ROOT = ROOT / "src" / "fesa"
|
|
|
|
|
|
def _looks_like_function_definition(prefix):
|
|
if "(" not in prefix or ")" not in prefix:
|
|
return False
|
|
|
|
stripped = prefix.strip()
|
|
control_prefixes = ("if ", "for ", "while ", "switch ", "catch ")
|
|
declaration_prefixes = ("namespace ", "class ", "struct ", "enum ")
|
|
return not stripped.startswith(control_prefixes + declaration_prefixes)
|
|
|
|
|
|
class HeaderDeclarationOnlyTests(unittest.TestCase):
|
|
def test_solver_headers_do_not_contain_function_bodies(self):
|
|
violations = []
|
|
|
|
for header in sorted(HEADER_ROOT.rglob("*.hpp")):
|
|
candidate = ""
|
|
for line_number, line in enumerate(header.read_text(encoding="utf-8").splitlines(), start=1):
|
|
stripped = line.strip()
|
|
if not stripped:
|
|
continue
|
|
|
|
candidate = f"{candidate} {stripped}".strip()
|
|
if "{" in stripped and _looks_like_function_definition(candidate.split("{", 1)[0]):
|
|
violations.append(f"{header.relative_to(ROOT)}:{line_number}: function body in header")
|
|
|
|
if re.search(r"\([^;{}]*\)\s*=\s*(default|delete)\s*;", stripped):
|
|
violations.append(f"{header.relative_to(ROOT)}:{line_number}: function definition in header")
|
|
|
|
if stripped.endswith(";") or stripped.endswith("}") or stripped.endswith(":"):
|
|
candidate = ""
|
|
|
|
self.assertEqual([], violations)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|