mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-26 12:30:04 +08:00
fix(cpp): a function is named by its declarator, never by its noexcept, throw or requires clause (#2727)
Both C++ extractors name a function by the first qualified identifier found breadth-first in its declarator, which is how an out-of-line `Foo::bar` is named. The walk skipped only the parameter list and the trailing return type, so a qualified name in the clauses after them became the name of a function whose own name is plain. nlohmann/json's constructor `basic_json(CompatibleType&& val) noexcept(noexcept( JSONSerializer<U>::to_json(…)))` was indexed as a method `JSONSerializer::to_json` that doesn't exist, with no node for the constructor; `throw(std::bad_alloc)` named a method `std::bad_alloc`, and a trailing `requires std::integral<T>` a function `std::integral<T>`. The walk now also skips `noexcept`, `throw_specifier` and `requires_clause`, in the TS extractor and the kernel alike; the parity fixture covers all three. Measured on main226ac930with fresh indexes, and byte-identical again after syncing ontoe97012eb: json 42, abseil 28 and protobuf 1 phantom nodes become the real functions at the same lines; fmt, leveldb, rocksdb, redis and three controls in other languages are byte-identical. Kernel parity sweeps on json, fmt, abseil, leveldb and rocksdb find no file with diffs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e97012eb31
commit
f66d064279
@@ -100,9 +100,11 @@ function findDeclaratorQualifiedId(declarator: SyntaxNode): SyntaxNode | undefin
|
||||
if (current.type === 'qualified_identifier') return current;
|
||||
for (let i = 0; i < current.namedChildCount; i++) {
|
||||
const child = current.namedChild(i);
|
||||
// Don't descend into parameters or the trailing return type — their types
|
||||
// (`const std::string&`, `-> std::string`) aren't the function name.
|
||||
if (child && child.type !== 'parameter_list' && child.type !== 'trailing_return_type') {
|
||||
// Don't descend into parameters, the trailing return type or the
|
||||
// clauses after them — `const std::string&`, `-> std::string`,
|
||||
// nlohmann/json's `noexcept(noexcept(JSONSerializer<U>::to_json(…)))`,
|
||||
// `throw(std::bad_alloc)`, `requires std::integral<T>` name no function.
|
||||
if (child && !DECLARATOR_NON_NAME_PARTS.has(child.type)) {
|
||||
queue.push(child);
|
||||
}
|
||||
}
|
||||
@@ -110,6 +112,11 @@ function findDeclaratorQualifiedId(declarator: SyntaxNode): SyntaxNode | undefin
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** The parts of a function declarator that hold types or expressions, never its name. */
|
||||
const DECLARATOR_NON_NAME_PARTS: ReadonlySet<string> = new Set([
|
||||
'parameter_list', 'trailing_return_type', 'noexcept', 'throw_specifier', 'requires_clause',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Single-argument macros are ambiguous without their definition (#1373).
|
||||
* Require a preceding local #define whose replacement uses its sole parameter
|
||||
|
||||
Reference in New Issue
Block a user