mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-02 01:37:32 +08:00
`fmt::format("{}", x)` resolves through the macro-namespace matcher
(#2176), which took the first same-named function of the namespace -
color.h's `format(const text_style&, format_string, T&&...)` - for all of
fmt's 1,400 `fmt::format` calls, and likewise `print`, `format_to`,
`vformat`.
Among an overload set the call's arguments are now read (to a dozen lines)
and each overload's parameter list from source (C++ signatures are empty):
an argument count outside the parameters' is out; a string-literal argument
fits a parameter that names a string type best, a template parameter
(`const S&`) less, anything else not; a narrow literal never fits a wide
parameter (`wformat_string`, `wstring_view`) nor a wide one a narrow one.
`...` inside `format_string<T...>` is not a pack.
fmt: `format` -> format.h (1,363) and xchar.h for `L"..."` (57),
`format_to`/`print` -> core.h, `vformat` -> format-inl.h; spdlog's bundled
fmt the same; pybind11's `py::set()` -> pytypes.h's `set` class. json,
rapidjson, leveldb unchanged. Edge counts unchanged (targets only).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
3.0 KiB
TypeScript
101 lines
3.0 KiB
TypeScript
/**
|
|
* `lib::format("{}", x)` among overloads opened by a namespace macro picks the
|
|
* one the arguments fit: fmt's 1,400 `fmt::format("{}", …)` calls all went to
|
|
* color.h's `format(const text_style&, …)` — the first of the set indexed.
|
|
* A narrow literal fits a `format_string`, a wide one (`L"{}"`) the
|
|
* `wformat_string` overload, and a style argument the style overload.
|
|
*/
|
|
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
import { CodeGraph } from '../src';
|
|
|
|
let root = '';
|
|
let cg: CodeGraph;
|
|
|
|
beforeAll(async () => {
|
|
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-cpp-overload-'));
|
|
const files: Record<string, string> = {
|
|
'include/lib/base.h': `#pragma once
|
|
#define LIB_BEGIN_NAMESPACE namespace lib {
|
|
#define LIB_END_NAMESPACE }
|
|
|
|
LIB_BEGIN_NAMESPACE
|
|
template <typename... T> struct format_string {};
|
|
template <typename... T> struct wformat_string {};
|
|
LIB_END_NAMESPACE
|
|
`,
|
|
'include/lib/color.h': `#pragma once
|
|
#include "base.h"
|
|
|
|
LIB_BEGIN_NAMESPACE
|
|
struct text_style {};
|
|
|
|
template <typename... T>
|
|
inline auto format(const text_style& ts, format_string<T...> fmt, T&&... args) -> int {
|
|
return 0;
|
|
}
|
|
LIB_END_NAMESPACE
|
|
`,
|
|
'include/lib/format.h': `#pragma once
|
|
#include "base.h"
|
|
|
|
LIB_BEGIN_NAMESPACE
|
|
template <typename... T>
|
|
inline auto format(format_string<T...> fmt, T&&... args) -> int {
|
|
return 1;
|
|
}
|
|
LIB_END_NAMESPACE
|
|
`,
|
|
'include/lib/xchar.h': `#pragma once
|
|
#include "base.h"
|
|
|
|
LIB_BEGIN_NAMESPACE
|
|
template <typename... T>
|
|
inline auto format(wformat_string<T...> fmt, T&&... args) -> int {
|
|
return 2;
|
|
}
|
|
LIB_END_NAMESPACE
|
|
`,
|
|
'test/use.cc': `#include "lib/color.h"
|
|
#include "lib/format.h"
|
|
#include "lib/xchar.h"
|
|
|
|
int narrow() { return lib::format("{}", 1); }
|
|
int wide() { return lib::format(L"{}", 2); }
|
|
int styled() { return lib::format(lib::text_style{}, "{}", 3); }
|
|
`,
|
|
};
|
|
for (const [rel, content] of Object.entries(files)) {
|
|
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
|
|
fs.writeFileSync(path.join(root, rel), content);
|
|
}
|
|
cg = await CodeGraph.init(root, { index: true });
|
|
});
|
|
|
|
afterAll(() => {
|
|
cg?.close();
|
|
if (root) fs.rmSync(root, { recursive: true, force: true });
|
|
});
|
|
|
|
const formatFileCalledBy = (fn: string): string[] => {
|
|
const node = cg.getNodesInFile('test/use.cc').find((n) => n.name === fn)!;
|
|
return cg.getOutgoingEdges(node.id).filter((e) => e.kind === 'calls').map((e) => cg.getNode(e.target)!)
|
|
.filter((t) => t.name === 'format').map((t) => t.filePath);
|
|
};
|
|
|
|
describe('C++ overloads in a macro-opened namespace', () => {
|
|
it('a narrow literal picks the format_string overload', () => {
|
|
expect(formatFileCalledBy('narrow')).toEqual(['include/lib/format.h']);
|
|
});
|
|
|
|
it('a wide literal picks the wformat_string overload', () => {
|
|
expect(formatFileCalledBy('wide')).toEqual(['include/lib/xchar.h']);
|
|
});
|
|
|
|
it('a style argument picks the style overload', () => {
|
|
expect(formatFileCalledBy('styled')).toEqual(['include/lib/color.h']);
|
|
});
|
|
});
|