|
|
@@ -2864,6 +2864,70 @@ class APXCharacter { // the one real definition
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ describe('C++ reference-return method/function names (#1093 follow-up)', () => {
|
|
|
+ // An inline method/function returning a reference parses with a
|
|
|
+ // `reference_declarator` wrapping the `function_declarator`. That wrapper
|
|
|
+ // wasn't unwrapped (only `pointer_declarator` was), so the name captured the
|
|
|
+ // whole declarator — `const int& getRef() const {…}` became the method named
|
|
|
+ // "& getRef() const" instead of "getRef", polluting search and callers. Very
|
|
|
+ // common in Unreal Engine headers (`const FGameplayTagContainer& GetActiveTags() const`).
|
|
|
+ const namesOf = (code: string) =>
|
|
|
+ extractFromSource('r.cpp', code).nodes
|
|
|
+ .filter((n) => n.kind === 'method' || n.kind === 'function')
|
|
|
+ .map((n) => n.name);
|
|
|
+
|
|
|
+ it('names an inline reference-returning method by its identifier, not the declarator', () => {
|
|
|
+ const names = namesOf('class C {\npublic:\n const int& getRef() const { return x; }\n int& mutRef() { return x; }\n int x;\n};');
|
|
|
+ expect(names).toContain('getRef');
|
|
|
+ expect(names).toContain('mutRef');
|
|
|
+ // No name leaks the reference sigil or the parameter/qualifier tail.
|
|
|
+ expect(names.some((n) => /[&()]/.test(n))).toBe(false);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('handles rvalue-reference returns and reference-returning free functions', () => {
|
|
|
+ expect(namesOf('class C { int&& take() { return 1; } };')).toContain('take');
|
|
|
+ expect(namesOf('const int& globalRef() { static int x; return x; }')).toContain('globalRef');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('leaves pointer, value, and out-of-line reference returns unchanged (controls)', () => {
|
|
|
+ expect(namesOf('class C { int* getPtr() { return &x; } int x; };')).toContain('getPtr');
|
|
|
+ expect(namesOf('class C { int getVal() const { return x; } int x; };')).toContain('getVal');
|
|
|
+ // Out-of-line `T& C::f()` already resolves via the qualified-name hook.
|
|
|
+ expect(namesOf('const int& C::getRef() const { return x; }')).toContain('getRef');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('C++ user-defined conversion operator names (#1093 follow-up)', () => {
|
|
|
+ // A conversion operator's declarator is an `operator_cast` (target type +
|
|
|
+ // `() const` tail). It was named with the whole declarator —
|
|
|
+ // `operator EALSMovementState() const` — so it didn't match the symbolic-
|
|
|
+ // overload style (`operator+`) and carried parameter noise. It's now named
|
|
|
+ // `operator <type>`. Common in Unreal Engine enum-wrapper structs.
|
|
|
+ const namesOf = (code: string) =>
|
|
|
+ extractFromSource('o.cpp', code).nodes
|
|
|
+ .filter((n) => n.kind === 'method' || n.kind === 'function')
|
|
|
+ .map((n) => n.name);
|
|
|
+
|
|
|
+ it('names a conversion operator as "operator <type>", not the full declarator', () => {
|
|
|
+ const names = namesOf('struct S {\n operator int() const { return 1; }\n operator bool() { return true; }\n int x;\n};');
|
|
|
+ expect(names).toContain('operator int');
|
|
|
+ expect(names).toContain('operator bool');
|
|
|
+ expect(names.some((n) => n.includes('(') || n.includes('const'))).toBe(false);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('handles a user-type conversion operator', () => {
|
|
|
+ expect(
|
|
|
+ namesOf('struct FALSMovementState {\n operator EALSMovementState() const { return State; }\n EALSMovementState State;\n};')
|
|
|
+ ).toContain('operator EALSMovementState');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('leaves symbolic operator overloads unchanged (control)', () => {
|
|
|
+ const names = namesOf('struct S {\n S operator+(const S& o) const { return o; }\n int& operator[](int i) { return x; }\n int x;\n};');
|
|
|
+ expect(names).toContain('operator+');
|
|
|
+ expect(names).toContain('operator[]'); // reference-returning subscript, name still clean
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
describe('C++ templated base-class inheritance (#1043)', () => {
|
|
|
// Inheriting from a template (`class D : public Base<int>`) recorded the base
|
|
|
// ref as the full instantiation `Base<int>`, which never name-matched the
|