mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-17 05:07:37 +08:00
fix(cpp): a smart pointer's held class lacking a method gets no edge only when its bases are known (#2530)
matchCppHeldTypeCall (#2440) returned null (no edge) for a `->` call on a `std::unique_ptr`/`std::shared_ptr`/`std::optional` whose held class lacks the method, unless that class is a class template. #2493 found the gap in the same rule for raw pointers and values: a base the index can't link may declare the method. protobuf's `class FlatAllocator : public decltype(ApplyTypeList<FlatAllocatorImpl>(…))` has no extends edge to `FlatAllocatorImpl`, and rocksdb's `WritePreparedTxnDB` derives from an alias each `#if` arm declares differently. Both paths now share one verdict, cppLacksMethod: no class template, and cppBasesKnown (every base on the way is linked to a class, or is a library type). Otherwise the call goes on as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,9 +17,9 @@
|
||||
* `Iterator` the call means inherits `Valid` from `IteratorBase`. A template
|
||||
* parameter, a library type and an alias of a type outside the project hold
|
||||
* no project class, so those calls get no edge; neither does a call the held
|
||||
* class has no method for (unless a class template's specialization may
|
||||
* declare it). A held type the project doesn't declare — a generated message
|
||||
* — leaves the call as it was.
|
||||
* class has no method for (unless a class template's specialization, or a
|
||||
* base the index doesn't link, may declare it). A held type the project
|
||||
* doesn't declare — a generated message — leaves the call as it was.
|
||||
*/
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import * as fs from 'fs';
|
||||
@@ -447,4 +447,35 @@ describe('what keeps the call as it was', () => {
|
||||
cg.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('a held class with a base the index does not link, which may declare the method', async () => {
|
||||
// protobuf's FlatAllocator derives from a `decltype(…)` that names FlatAllocatorImpl.
|
||||
const cg = await indexed({
|
||||
'src/google/protobuf/descriptor.cc': lines(
|
||||
'#include <memory>',
|
||||
'namespace google {',
|
||||
'namespace protobuf {',
|
||||
'namespace internal {',
|
||||
'template <typename... T>',
|
||||
'class FlatAllocatorImpl {',
|
||||
' public:',
|
||||
' void PlanArray(int array_size) {}',
|
||||
'};',
|
||||
'template <typename... T>',
|
||||
'FlatAllocatorImpl<T...> ApplyTypeList(int);',
|
||||
'class FlatAllocator : public decltype(ApplyTypeList<char, int>(0)) {};',
|
||||
'} // namespace internal',
|
||||
'void PlanAllocationSize(std::unique_ptr<internal::FlatAllocator>& alloc) {',
|
||||
' alloc->PlanArray(1);',
|
||||
'}',
|
||||
'} // namespace protobuf',
|
||||
'} // namespace google',
|
||||
),
|
||||
});
|
||||
try {
|
||||
expect(calls(cg, 'google::protobuf::PlanAllocationSize')).toEqual(['google::protobuf::internal::FlatAllocatorImpl::PlanArray']);
|
||||
} finally {
|
||||
cg.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user