"""Locate `resource` blocks in .tf files and intersect with changed lines.""" from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path _HEADER_RE = re.compile( r'^\s*resource\s+"(?P[^"]+)"\s+"(?P[^"]+)"\s*\{' ) @dataclass(frozen=True) class ResourceBlock: type: str name: str start: int end: int def find_resource_blocks(path: Path) -> list[ResourceBlock]: """Locate top-level `resource` blocks by tracking brace depth.""" text = path.read_text() lines = text.splitlines() blocks: list[ResourceBlock] = [] i = 0 while i < len(lines): line = lines[i] m = _HEADER_RE.match(line) if not m: i += 1 continue start = i + 1 depth = line.count("{") - line.count("}") j = i while depth > 0 and j + 1 < len(lines): j += 1 depth += lines[j].count("{") - lines[j].count("}") blocks.append(ResourceBlock( type=m.group("type"), name=m.group("name"), start=start, end=j + 1, )) i = j + 1 return blocks def _intersects(a: tuple[int, int], b: tuple[int, int]) -> bool: return not (a[1] < b[0] or b[1] < a[0]) def touched_resources( path: Path, added_ranges: list[tuple[int, int]], ) -> list[ResourceBlock]: if not added_ranges: return [] blocks = find_resource_blocks(path) out: list[ResourceBlock] = [] for blk in blocks: if any(_intersects((blk.start, blk.end), r) for r in added_ranges): out.append(blk) return out