Convert a node to a searchable text representation. Designed so natural-language queries land on the right node, not just on the enclosing class. We include the dotted ``Parent.name`` form, the identifier split into words, an explicit ``"in "`` phrase, the enclosing module d
(node: GraphNode)
| 797 | |
| 798 | |
| 799 | def _node_to_text(node: GraphNode) -> str: |
| 800 | """Convert a node to a searchable text representation. |
| 801 | |
| 802 | Designed so natural-language queries land on the right node, not just on |
| 803 | the enclosing class. We include the dotted ``Parent.name`` form, the |
| 804 | identifier split into words, an explicit ``"in <Parent>"`` phrase, the |
| 805 | enclosing module directory, and the language. Tested by the |
| 806 | ``multi_hop_retrieval`` benchmark — see ``docs/REPRODUCING.md``. |
| 807 | """ |
| 808 | parts: list[str] = [] |
| 809 | |
| 810 | # 1. Dotted form first — strongest lexical signal for "method in class" |
| 811 | if node.parent_name and node.kind != "File": |
| 812 | parts.append(f"{node.parent_name}.{node.name}") |
| 813 | |
| 814 | # 2. Bare name (always present) |
| 815 | parts.append(node.name) |
| 816 | |
| 817 | # 3. Split-words form of the name (only if it differs from the bare name) |
| 818 | name_split = _split_identifier(node.name) |
| 819 | if name_split and name_split.lower() != node.name.lower(): |
| 820 | parts.append(name_split) |
| 821 | |
| 822 | # 4. Kind ("function", "class", "test", ...) |
| 823 | if node.kind != "File": |
| 824 | parts.append(node.kind.lower()) |
| 825 | |
| 826 | # 5. Parent context with the split form too |
| 827 | if node.parent_name: |
| 828 | parts.append(f"in {node.parent_name}") |
| 829 | parent_split = _split_identifier(node.parent_name) |
| 830 | if parent_split and parent_split.lower() != node.parent_name.lower(): |
| 831 | parts.append(parent_split) |
| 832 | |
| 833 | # 6. Signature bits |
| 834 | if node.params: |
| 835 | parts.append(node.params) |
| 836 | if node.return_type: |
| 837 | parts.append(f"returns {node.return_type}") |
| 838 | |
| 839 | # 7. Module / directory context from the file path — gives queries a |
| 840 | # term like "routing" or "client" to anchor against. |
| 841 | if node.file_path: |
| 842 | parent_dir = Path(node.file_path).parent.name |
| 843 | if parent_dir and parent_dir not in (".", "src", "lib"): |
| 844 | parts.append(parent_dir) |
| 845 | |
| 846 | # 8. Language |
| 847 | if node.language: |
| 848 | parts.append(node.language) |
| 849 | |
| 850 | return " ".join(parts) |
| 851 | |
| 852 | |
| 853 | class EmbeddingStore: |