* Extract a method
(node: SyntaxNode)
| 1608 | * Extract a method |
| 1609 | */ |
| 1610 | private extractMethod(node: SyntaxNode): void { |
| 1611 | if (!this.extractor) return; |
| 1612 | |
| 1613 | // For languages with receiver types (Go, Rust), include receiver in qualified name |
| 1614 | // so FTS can match "scrapeLoop.run" → qualified_name "...::scrapeLoop::run" |
| 1615 | const receiverType = this.extractor.getReceiverType?.(node, this.source); |
| 1616 | |
| 1617 | // For most languages, only extract as method if inside a class-like node |
| 1618 | // Languages with methodsAreTopLevel (e.g. Go) always treat them as methods |
| 1619 | // Languages with getReceiverType (e.g. Rust) extract as method when receiver is found |
| 1620 | if (!this.isInsideClassLikeNode() && !this.extractor.methodsAreTopLevel && !receiverType) { |
| 1621 | // Skip method_definition nodes inside object literals (getters/setters/methods |
| 1622 | // in inline objects). These are ephemeral and create noise (e.g., Svelte context |
| 1623 | // objects: `ctx.set({ get view() { ... } })`). |
| 1624 | if (node.parent?.type === 'object' || node.parent?.type === 'object_expression') { |
| 1625 | const body = this.extractor.resolveBody?.(node, this.extractor.bodyField) |
| 1626 | ?? getChildByField(node, this.extractor.bodyField); |
| 1627 | if (body) { |
| 1628 | this.visitFunctionBody(body, ''); |
| 1629 | } |
| 1630 | return; |
| 1631 | } |
| 1632 | // Not inside a class-like node and no receiver type, treat as function |
| 1633 | this.extractFunction(node); |
| 1634 | return; |
| 1635 | } |
| 1636 | |
| 1637 | const name = extractName(node, this.source, this.extractor); |
| 1638 | |
| 1639 | // Check for misparse artifacts (e.g. C++ "switch" inside macro-confused class body) |
| 1640 | if (this.extractor.isMisparsedFunction?.(name, node)) { |
| 1641 | const body = this.extractor.resolveBody?.(node, this.extractor.bodyField) |
| 1642 | ?? getChildByField(node, this.extractor.bodyField); |
| 1643 | if (body) { |
| 1644 | this.visitFunctionBody(body, ''); |
| 1645 | } |
| 1646 | return; |
| 1647 | } |
| 1648 | |
| 1649 | const docstring = getPrecedingDocstring(node, this.source); |
| 1650 | const signature = this.extractor.getSignature?.(node, this.source); |
| 1651 | const visibility = this.extractor.getVisibility?.(node); |
| 1652 | const isAsync = this.extractor.isAsync?.(node); |
| 1653 | const isStatic = this.extractor.isStatic?.(node); |
| 1654 | const returnType = this.extractor.getReturnType?.(node, this.source); |
| 1655 | const extraProps: Partial<Node> = { |
| 1656 | docstring, |
| 1657 | signature, |
| 1658 | visibility, |
| 1659 | isAsync, |
| 1660 | isStatic, |
| 1661 | returnType, |
| 1662 | }; |
| 1663 | if (receiverType) { |
| 1664 | extraProps.qualifiedName = `${receiverType}::${name}`; |
| 1665 | } |
| 1666 | |
| 1667 | const methodNode = this.createNode('method', name, node, extraProps); |
no test coverage detected