mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
Make KeyCapture work with nested typedefs (#473)
This commit is contained in:
parent
617493ddf5
commit
31bf9e7b59
@ -83,6 +83,10 @@ namespace {
|
|||||||
std::vector<std::string_view> enumerateTypeNames(Type& type) {
|
std::vector<std::string_view> enumerateTypeNames(Type& type) {
|
||||||
std::vector<std::string_view> names;
|
std::vector<std::string_view> names;
|
||||||
Type* t = &type;
|
Type* t = &type;
|
||||||
|
|
||||||
|
if (const auto* ck = dynamic_cast<CaptureKeys*>(t))
|
||||||
|
t = &ck->underlyingType();
|
||||||
|
|
||||||
while (const Typedef* td = dynamic_cast<Typedef*>(t)) {
|
while (const Typedef* td = dynamic_cast<Typedef*>(t)) {
|
||||||
names.emplace_back(t->inputName());
|
names.emplace_back(t->inputName());
|
||||||
t = &td->underlyingType();
|
t = &td->underlyingType();
|
||||||
@ -1152,9 +1156,14 @@ void CodeGen::addTypeHandlers(const TypeGraph& typeGraph, std::string& code) {
|
|||||||
genContainerTypeHandler(
|
genContainerTypeHandler(
|
||||||
definedContainers_, con->containerInfo_, con->templateParams, code);
|
definedContainers_, con->containerInfo_, con->templateParams, code);
|
||||||
} else if (const auto* cap = dynamic_cast<const CaptureKeys*>(&t)) {
|
} else if (const auto* cap = dynamic_cast<const CaptureKeys*>(&t)) {
|
||||||
|
auto* container =
|
||||||
|
dynamic_cast<Container*>(&(stripTypedefs(cap->underlyingType())));
|
||||||
|
if (!container)
|
||||||
|
throw std::runtime_error("KaptureKeys requires a container");
|
||||||
|
|
||||||
genContainerTypeHandler(definedContainers_,
|
genContainerTypeHandler(definedContainers_,
|
||||||
cap->containerInfo(),
|
cap->containerInfo(),
|
||||||
cap->container().templateParams,
|
container->templateParams,
|
||||||
code);
|
code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ void KeyCapture::visit(Class& c) {
|
|||||||
* [VAL]
|
* [VAL]
|
||||||
*/
|
*/
|
||||||
Type& KeyCapture::captureKey(Type& type) {
|
Type& KeyCapture::captureKey(Type& type) {
|
||||||
auto* container = dynamic_cast<Container*>(&type);
|
auto* container = dynamic_cast<Container*>(&(stripTypedefs(type)));
|
||||||
if (!container) // We only want to capture keys from containers
|
if (!container) // We only want to capture keys from containers
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
@ -114,7 +114,9 @@ Type& KeyCapture::captureKey(Type& type) {
|
|||||||
auto infoPtr = std::make_unique<ContainerInfo>(std::move(newContainerInfo));
|
auto infoPtr = std::make_unique<ContainerInfo>(std::move(newContainerInfo));
|
||||||
const auto& info = containerInfos_.emplace_back(std::move(infoPtr));
|
const auto& info = containerInfos_.emplace_back(std::move(infoPtr));
|
||||||
|
|
||||||
auto& captureKeysNode = typeGraph_.makeType<CaptureKeys>(*container, *info);
|
// auto& captureKeysNode = typeGraph_.makeType<CaptureKeys>(*container,
|
||||||
|
// *info);
|
||||||
|
auto& captureKeysNode = typeGraph_.makeType<CaptureKeys>(type, *info);
|
||||||
return captureKeysNode;
|
return captureKeysNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ void Printer::visit(const DummyAllocator& d) {
|
|||||||
void Printer::visit(const CaptureKeys& d) {
|
void Printer::visit(const CaptureKeys& d) {
|
||||||
prefix();
|
prefix();
|
||||||
out_ << "CaptureKeys" << std::endl;
|
out_ << "CaptureKeys" << std::endl;
|
||||||
print(d.container());
|
print(d.underlyingType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Printer::prefix() {
|
void Printer::prefix() {
|
||||||
|
@ -150,7 +150,7 @@ void TopoSorter::visit(Reference& r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TopoSorter::visit(CaptureKeys& c) {
|
void TopoSorter::visit(CaptureKeys& c) {
|
||||||
accept(c.container());
|
accept(c.underlyingType());
|
||||||
sortedTypes_.push_back(c);
|
sortedTypes_.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,9 @@ class ConstVisitor;
|
|||||||
Type& accept(Visitor<Type&>& m) override; \
|
Type& accept(Visitor<Type&>& m) override; \
|
||||||
void accept(ConstVisitor& v) const override;
|
void accept(ConstVisitor& v) const override;
|
||||||
|
|
||||||
|
class Type;
|
||||||
|
Type& stripTypedefs(Type& type);
|
||||||
|
|
||||||
// TODO delete copy and move ctors
|
// TODO delete copy and move ctors
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -934,8 +937,8 @@ class DummyAllocator : public Type {
|
|||||||
*/
|
*/
|
||||||
class CaptureKeys : public Type {
|
class CaptureKeys : public Type {
|
||||||
public:
|
public:
|
||||||
explicit CaptureKeys(Container& c, const ContainerInfo& info)
|
explicit CaptureKeys(Type& t, const ContainerInfo& info)
|
||||||
: container_(c), containerInfo_(info) {
|
: underlyingType_(t), containerInfo_(info) {
|
||||||
regenerateName();
|
regenerateName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,19 +951,19 @@ class CaptureKeys : public Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string_view inputName() const override {
|
virtual std::string_view inputName() const override {
|
||||||
return container_.get().inputName();
|
return underlyingType_.get().inputName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void regenerateName() {
|
void regenerateName() {
|
||||||
name_ = "OICaptureKeys<" + container_.get().name() + ">";
|
name_ = "OICaptureKeys<" + underlyingType_.get().name() + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t size() const override {
|
virtual size_t size() const override {
|
||||||
return container_.get().size();
|
return underlyingType_.get().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint64_t align() const override {
|
virtual uint64_t align() const override {
|
||||||
return container_.get().align();
|
return underlyingType_.get().align();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual NodeId id() const override {
|
virtual NodeId id() const override {
|
||||||
@ -971,22 +974,20 @@ class CaptureKeys : public Type {
|
|||||||
return containerInfo_;
|
return containerInfo_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Container& container() const {
|
Type& underlyingType() const {
|
||||||
return container_;
|
return underlyingType_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setContainer(Container& container) {
|
void setUnderlyingType(Type& t) {
|
||||||
container_ = container;
|
underlyingType_ = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<Container> container_;
|
std::reference_wrapper<Type> underlyingType_;
|
||||||
const ContainerInfo& containerInfo_;
|
const ContainerInfo& containerInfo_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
Type& stripTypedefs(Type& type);
|
|
||||||
|
|
||||||
} // namespace oi::detail::type_graph
|
} // namespace oi::detail::type_graph
|
||||||
|
|
||||||
#undef DECLARE_ACCEPT
|
#undef DECLARE_ACCEPT
|
||||||
|
@ -117,7 +117,7 @@ class RecursiveVisitor : public Visitor<void> {
|
|||||||
accept(d.allocType());
|
accept(d.allocType());
|
||||||
}
|
}
|
||||||
virtual void visit(CaptureKeys& c) {
|
virtual void visit(CaptureKeys& c) {
|
||||||
accept(c.container());
|
accept(c.underlyingType());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -190,8 +190,7 @@ class RecursiveMutator : public Visitor<Type&> {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
virtual Type& visit(CaptureKeys& c) {
|
virtual Type& visit(CaptureKeys& c) {
|
||||||
auto& newContainer = dynamic_cast<Container&>(mutate(c.container()));
|
c.setUnderlyingType(mutate(c.underlyingType()));
|
||||||
c.setContainer(newContainer);
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,11 @@ struct MapHolder {
|
|||||||
std::map<int, int> dontCaptureKeysHere;
|
std::map<int, int> dontCaptureKeysHere;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using MyIntMap = std::map<int,int>;
|
||||||
|
struct MyTypedefIntMapHolder {
|
||||||
|
MyIntMap captureMyKeys;
|
||||||
|
};
|
||||||
|
|
||||||
enum class MyEnum {
|
enum class MyEnum {
|
||||||
One = 1,
|
One = 1,
|
||||||
Two = 2,
|
Two = 2,
|
||||||
@ -320,6 +325,48 @@ class FixedAllocator {
|
|||||||
]
|
]
|
||||||
}]'''
|
}]'''
|
||||||
|
|
||||||
|
|
||||||
|
[cases.typedef]
|
||||||
|
oid_skip = "Requires TreeBuilderV2"
|
||||||
|
param_types = ["const MyTypedefIntMapHolder&"]
|
||||||
|
setup = '''return {MyTypedefIntMapHolder{
|
||||||
|
.captureMyKeys{ {1,2},{3,4} },
|
||||||
|
}};'''
|
||||||
|
config_suffix = '''
|
||||||
|
[[codegen.capture_keys]]
|
||||||
|
type = "MyTypedefIntMapHolder"
|
||||||
|
members = ["captureMyKeys"]
|
||||||
|
'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"name": "captureMyKeys",
|
||||||
|
"typePath": ["a0","captureMyKeys"],
|
||||||
|
"typeNames": ["MyIntMap", "std::map<int32_t, int32_t, less<int>, std::allocator<std::pair<int32_t const, int32_t>>>"],
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"name": "[1]",
|
||||||
|
"typePath": ["a0","captureMyKeys","[1]"],
|
||||||
|
"data": 1,
|
||||||
|
"members": [
|
||||||
|
{"name": "key", "typePath": ["a0","captureMyKeys","[1]","key"]},
|
||||||
|
{"name": "value", "typePath": ["a0","captureMyKeys","[1]","value"]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[3]",
|
||||||
|
"typePath": ["a0","captureMyKeys","[3]"],
|
||||||
|
"data": 3,
|
||||||
|
"members": [
|
||||||
|
{"name": "key", "typePath": ["a0","captureMyKeys","[3]","key"]},
|
||||||
|
{"name": "value", "typePath": ["a0","captureMyKeys","[3]","value"]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]'''
|
||||||
|
|
||||||
[cases.std_unordered_map]
|
[cases.std_unordered_map]
|
||||||
oid_skip = "Requires TreeBuilderV2"
|
oid_skip = "Requires TreeBuilderV2"
|
||||||
param_types = ["const std::unordered_map<int, int>&"]
|
param_types = ["const std::unordered_map<int, int>&"]
|
||||||
|
@ -76,6 +76,35 @@ TEST(KeyCaptureTest, MapInMap) {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(KeyCaptureTest, Typedef) {
|
||||||
|
std::vector<OICodeGen::Config::KeyToCapture> keysToCapture = {
|
||||||
|
{"MyClass", "a"},
|
||||||
|
};
|
||||||
|
std::vector<std::unique_ptr<ContainerInfo>> containerInfos;
|
||||||
|
test(KeyCapture::createPass(keysToCapture, containerInfos),
|
||||||
|
R"(
|
||||||
|
[0] Class: MyClass (size: 12)
|
||||||
|
Member: a (offset: 8)
|
||||||
|
[1] Typedef: MyTypeDef
|
||||||
|
[2] Container: std::map (size: 24)
|
||||||
|
Param
|
||||||
|
Primitive: int32_t
|
||||||
|
Param
|
||||||
|
Primitive: int32_t
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
[0] Class: MyClass (size: 12)
|
||||||
|
Member: a (offset: 8)
|
||||||
|
CaptureKeys
|
||||||
|
[1] Typedef: MyTypeDef
|
||||||
|
[2] Container: std::map (size: 24)
|
||||||
|
Param
|
||||||
|
Primitive: int32_t
|
||||||
|
Param
|
||||||
|
Primitive: int32_t
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(KeyCaptureTest, TopLevel) {
|
TEST(KeyCaptureTest, TopLevel) {
|
||||||
std::vector<OICodeGen::Config::KeyToCapture> keysToCapture = {
|
std::vector<OICodeGen::Config::KeyToCapture> keysToCapture = {
|
||||||
{{}, {}, true},
|
{{}, {}, true},
|
||||||
|
Loading…
Reference in New Issue
Block a user