Parse a ReScript `.res` or `.resi` file. Extracts modules, let bindings, types, external bindings, open/include imports, and function calls. Interface files (`.resi`) are flagged via ``File`` node ``extra["rescript_interface"]=True`` and skip call extraction since si
(
self, path: Path, source: bytes,
)
| 1605 | # ------------------------------------------------------------------ |
| 1606 | |
| 1607 | def _parse_rescript( |
| 1608 | self, path: Path, source: bytes, |
| 1609 | ) -> tuple[list[NodeInfo], list[EdgeInfo]]: |
| 1610 | """Parse a ReScript `.res` or `.resi` file. |
| 1611 | |
| 1612 | Extracts modules, let bindings, types, external bindings, open/include |
| 1613 | imports, and function calls. Interface files (`.resi`) are flagged via |
| 1614 | ``File`` node ``extra["rescript_interface"]=True`` and skip call |
| 1615 | extraction since signatures have no call sites. |
| 1616 | """ |
| 1617 | text = source.decode("utf-8", errors="replace") |
| 1618 | file_path_str = str(path) |
| 1619 | test_file = _is_test_file(file_path_str) |
| 1620 | is_interface = path.suffix.lower() == ".resi" |
| 1621 | |
| 1622 | # Strip comments and string/backtick literal content so downstream |
| 1623 | # regex matches are not fooled by code-looking text inside strings. |
| 1624 | # Newlines are preserved so offset→line mapping stays accurate. |
| 1625 | cleaned = _strip_rescript_noise(text) |
| 1626 | |
| 1627 | # Build offset → line index (1-based). |
| 1628 | line_starts = [0] |
| 1629 | for i, ch in enumerate(cleaned): |
| 1630 | if ch == "\n": |
| 1631 | line_starts.append(i + 1) |
| 1632 | |
| 1633 | def offset_to_line(off: int) -> int: |
| 1634 | lo, hi = 0, len(line_starts) - 1 |
| 1635 | while lo < hi: |
| 1636 | mid = (lo + hi + 1) // 2 |
| 1637 | if line_starts[mid] <= off: |
| 1638 | lo = mid |
| 1639 | else: |
| 1640 | hi = mid - 1 |
| 1641 | return lo + 1 |
| 1642 | |
| 1643 | nodes: list[NodeInfo] = [] |
| 1644 | edges: list[EdgeInfo] = [] |
| 1645 | |
| 1646 | file_extra: dict = {} |
| 1647 | if is_interface: |
| 1648 | file_extra["rescript_interface"] = True |
| 1649 | nodes.append(NodeInfo( |
| 1650 | kind="File", |
| 1651 | name=file_path_str, |
| 1652 | file_path=file_path_str, |
| 1653 | line_start=1, |
| 1654 | line_end=text.count("\n") + 1, |
| 1655 | language="rescript", |
| 1656 | is_test=test_file, |
| 1657 | extra=file_extra, |
| 1658 | )) |
| 1659 | |
| 1660 | # Modules with brace-matched offset ranges. |
| 1661 | modules = _scan_rescript_modules(cleaned, offset_to_line) |
| 1662 | depth_arr = _rescript_brace_depth_array(cleaned) |
| 1663 | |
| 1664 | def is_top_level(off: int, parent_mod: Optional[str]) -> bool: |
no test coverage detected