fix(cpp): compose namespace prefix into out-of-line method qualified names (#1310)
An out-of-line member definition inside a namespace block takes its
qualifiedName from the declarator's receiver, which is spelled RELATIVE
to the enclosing namespace — so `namespace simulator {
ManifestStartup::Output ManifestStartup::Apply(...) {} }` indexed as
ManifestStartup::Apply while the class node carried
simulator::ManifestStartup. Fully-qualified call sites
(simulator::ManifestStartup::Apply(...)) never resolved; callers and
file impact came up empty (#1291).
The receiver-based qualifiedName now composes the active namespace
prefix, anchored at the first prefix segment the receiver re-spells
(so `namespace sim { void sim::M::f() {} }` doesn't double-prefix).
namespacePrefix is only ever non-empty for C++ — Go/Rust/Kotlin/Lua
receivers pass through unchanged.
leveldb re-index: node count byte-stable (3,044), calls edges +6,
namespace-qualified method names 947 -> 1,252.
Fixes #1291
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4dd29ea5c1
commit
e437918026
@@ -1379,6 +1379,32 @@ export class TreeSitterExtractor {
|
||||
return ns?.id ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Qualified name for a method defined out-of-line via a receiver qualifier
|
||||
* (`Type::method() {}`). The declarator spells the receiver RELATIVE to the
|
||||
* enclosing namespace, so the active C++ namespace prefix must be composed
|
||||
* in — `namespace sim { Output ManifestStartup::Apply() {} }` previously
|
||||
* indexed as `ManifestStartup::Apply` while the class node carried
|
||||
* `sim::ManifestStartup`, so qualified call sites
|
||||
* (`sim::ManifestStartup::Apply(...)`) never resolved (#1291).
|
||||
*
|
||||
* The source may also re-spell part or all of the namespace path
|
||||
* (`namespace sim { void sim::M::f() {} }` is legal), so the receiver is
|
||||
* anchored at the first prefix segment it names: everything before that
|
||||
* anchor is taken from the prefix, the receiver supplies the rest. A
|
||||
* receiver naming no prefix segment gets the whole prefix prepended.
|
||||
* `namespacePrefix` is only ever non-empty for C++, so every other
|
||||
* receiver language (Go, Rust, Kotlin, Lua) passes through unchanged.
|
||||
*/
|
||||
private composeReceiverQualifiedName(receiverType: string, name: string): string {
|
||||
const base = `${receiverType}::${name}`;
|
||||
if (this.namespacePrefix.length === 0) return base;
|
||||
const receiverHead = receiverType.split('::')[0];
|
||||
const anchor = this.namespacePrefix.indexOf(receiverHead!);
|
||||
const prefix = anchor === -1 ? this.namespacePrefix : this.namespacePrefix.slice(0, anchor);
|
||||
return prefix.length > 0 ? `${prefix.join('::')}::${base}` : base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build qualified name from node stack
|
||||
*/
|
||||
@@ -1726,7 +1752,7 @@ export class TreeSitterExtractor {
|
||||
returnType,
|
||||
};
|
||||
if (receiverType) {
|
||||
extraProps.qualifiedName = `${receiverType}::${name}`;
|
||||
extraProps.qualifiedName = this.composeReceiverQualifiedName(receiverType, name);
|
||||
}
|
||||
|
||||
const methodNode = this.createNode('method', name, node, extraProps);
|
||||
|
||||
Reference in New Issue
Block a user