* Extract a method
(node: SyntaxNode)
| 1735 | * Extract a method |
| 1736 | */ |
| 1737 | private extractMethod(node: SyntaxNode): void { |
| 1738 | if (!this.extractor) return; |
| 1739 | |
| 1740 | // For languages with receiver types (Go, Rust), include receiver in qualified name |
| 1741 | // so FTS can match "scrapeLoop.run" → qualified_name "...::scrapeLoop::run" |
| 1742 | const receiverType = this.extractor.getReceiverType?.(node, this.source); |
| 1743 | |
| 1744 | // For most languages, only extract as method if inside a class-like node |
| 1745 | // Languages with methodsAreTopLevel (e.g. Go) always treat them as methods |
| 1746 | // Languages with getReceiverType (e.g. Rust) extract as method when receiver is found |
| 1747 | if (!this.isInsideClassLikeNode() && !this.extractor.methodsAreTopLevel && !receiverType) { |
| 1748 | // Skip method_definition nodes inside object literals (getters/setters/methods |
| 1749 | // in inline objects). These are ephemeral and create noise (e.g., Svelte context |
| 1750 | // objects: `ctx.set({ get view() { ... } })`). |
| 1751 | if (node.parent?.type === 'object' || node.parent?.type === 'object_expression') { |
| 1752 | const body = this.extractor.resolveBody?.(node, this.extractor.bodyField) |
| 1753 | ?? getChildByField(node, this.extractor.bodyField); |
| 1754 | if (body) { |
| 1755 | this.visitFunctionBody(body, ''); |
| 1756 | } |
| 1757 | return; |
| 1758 | } |
| 1759 | // Not inside a class-like node and no receiver type, treat as function |
| 1760 | this.extractFunction(node); |
| 1761 | return; |
| 1762 | } |
| 1763 | |
| 1764 | const name = extractName(node, this.source, this.extractor); |
| 1765 | |
| 1766 | // Check for misparse artifacts (e.g. C++ "switch" inside macro-confused class body) |
| 1767 | if (this.extractor.isMisparsedFunction?.(name, node)) { |
| 1768 | const body = this.extractor.resolveBody?.(node, this.extractor.bodyField) |
| 1769 | ?? getChildByField(node, this.extractor.bodyField); |
| 1770 | if (body) { |
| 1771 | this.visitFunctionBody(body, ''); |
| 1772 | } |
| 1773 | return; |
| 1774 | } |
| 1775 | |
| 1776 | const docstring = getPrecedingDocstring(node, this.source); |
| 1777 | const signature = this.extractor.getSignature?.(node, this.source); |
| 1778 | const visibility = this.extractor.getVisibility?.(node); |
| 1779 | const isAsync = this.extractor.isAsync?.(node); |
| 1780 | const isStatic = this.extractor.isStatic?.(node); |
| 1781 | const returnType = this.extractor.getReturnType?.(node, this.source); |
| 1782 | const extraProps: Partial<Node> = { |
| 1783 | docstring, |
| 1784 | signature, |
| 1785 | visibility, |
| 1786 | isAsync, |
| 1787 | isStatic, |
| 1788 | returnType, |
| 1789 | }; |
| 1790 | if (receiverType) { |
| 1791 | extraProps.qualifiedName = this.composeReceiverQualifiedName(receiverType, name); |
| 1792 | } |
| 1793 | |
| 1794 | const methodNode = this.createNode('method', name, node, extraProps); |
no test coverage detected