data: name hierarchy refactoring

* replaced typenames (which have been stored as single sting where "::" indicated hierarchy levels) by a vector of strings where each element indicates a hierarchy level.
* introduced this change to the Storage method signatures, the ParseFunction and ParseVariable
* this way the SearchIndex creates a node for each level of the hierarchy.
This commit is contained in:
malte_langkabel
2014-10-24 11:25:34 +02:00
parent ce91216e97
commit a1b874c520
21 changed files with 341 additions and 232 deletions
+20 -19
View File
@@ -7,6 +7,7 @@
#include "data/parser/ParseTypeUsage.h"
#include "data/parser/ParseVariable.h"
#include "utility/text/TextAccess.h"
#include "utility/utilityString.h"
class CxxParserTestSuite: public CxxTest::TestSuite
{
@@ -1005,28 +1006,28 @@ private:
{
public:
virtual Id onTypedefParsed(
const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType,
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
AccessType access
)
{
std::string str = addAccessPrefix(underlyingType.dataType.getFullTypeName() + " -> " + fullName, access);
std::string str = addAccessPrefix(underlyingType.dataType.getFullTypeName() + " -> " + utility::join(nameHierarchy, "::"), access);
typedefs.push_back(addLocationSuffix(str, location));
return 0;
}
virtual Id onClassParsed(
const ParseLocation& location, const std::string& fullName, AccessType access,
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, AccessType access,
const ParseLocation& scopeLocation)
{
classes.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation));
classes.push_back(addLocationSuffix(addAccessPrefix(utility::join(nameHierarchy, "::"), access), location, scopeLocation));
return 0;
}
virtual Id onStructParsed(
const ParseLocation& location, const std::string& fullName, AccessType access,
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, AccessType access,
const ParseLocation& scopeLocation)
{
structs.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation));
structs.push_back(addLocationSuffix(addAccessPrefix(utility::join(nameHierarchy, "::"), access), location, scopeLocation));
return 0;
}
@@ -1074,30 +1075,30 @@ private:
}
virtual Id onNamespaceParsed(
const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation)
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseLocation& scopeLocation)
{
namespaces.push_back(addLocationSuffix(fullName, location, scopeLocation));
namespaces.push_back(addLocationSuffix(utility::join(nameHierarchy, "::"), location, scopeLocation));
return 0;
}
virtual Id onEnumParsed(
const ParseLocation& location, const std::string& fullName, AccessType access,
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, AccessType access,
const ParseLocation& scopeLocation)
{
enums.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation));
enums.push_back(addLocationSuffix(addAccessPrefix(utility::join(nameHierarchy, "::"), access), location, scopeLocation));
return 0;
}
virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName)
virtual Id onEnumFieldParsed(const ParseLocation& location, const std::vector<std::string>& nameHierarchy)
{
enumFields.push_back(addLocationSuffix(fullName, location));
enumFields.push_back(addLocationSuffix(utility::join(nameHierarchy, "::"), location));
return 0;
}
virtual Id onInheritanceParsed(
const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access)
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const std::vector<std::string>& baseNameHierarchy, AccessType access)
{
std::string str = fullName + " : " + addAccessPrefix(baseName, access);
std::string str = utility::join(nameHierarchy, "::") + " : " + addAccessPrefix(utility::join(baseNameHierarchy, "::"), access);
inheritances.push_back(addLocationSuffix(str, location));
return 0;
}
@@ -1112,21 +1113,21 @@ private:
virtual Id onCallParsed(
const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee)
{
calls.push_back(addLocationSuffix(caller.fullName + " -> " + functionStr(callee), location));
calls.push_back(addLocationSuffix(caller.getFullName() + " -> " + functionStr(callee), location));
return 0;
}
virtual Id onFieldUsageParsed(
const ParseLocation& location, const ParseFunction& user, const std::string& usedName)
const ParseLocation& location, const ParseFunction& user, const std::vector<std::string>& usedNameHierarchy)
{
usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location));
usages.push_back(addLocationSuffix(functionStr(user) + " -> " + utility::join(usedNameHierarchy, "::"), location));
return 0;
}
virtual Id onGlobalVariableUsageParsed(
const ParseLocation& location, const ParseFunction& user, const std::string& usedName)
const ParseLocation& location, const ParseFunction& user, const std::vector<std::string>& usedNameHierarchy)
{
usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location));
usages.push_back(addLocationSuffix(functionStr(user) + " -> " + utility::join(usedNameHierarchy, "::"), location));
return 0;
}
+34 -33
View File
@@ -1,6 +1,7 @@
#include "cxxtest/TestSuite.h"
#include "data/SearchIndex.h"
#include "utility/utilityString.h"
class SearchIndexTestSuite : public CxxTest::TestSuite
{
@@ -16,7 +17,7 @@ public:
void test_add_node()
{
SearchIndex index;
SearchIndex::SearchNode* node = index.addNode("util");
SearchIndex::SearchNode* node = index.addNode(utility::splitToVector("util", "::"));
TS_ASSERT(node);
TS_ASSERT_EQUALS("util", node->getName());
@@ -30,7 +31,7 @@ public:
void test_get_node()
{
SearchIndex index;
index.addNode("util");
index.addNode(utility::splitToVector("util", "::"));
SearchIndex::SearchNode* node = index.getNode("util");
TS_ASSERT(node);
@@ -48,7 +49,7 @@ public:
void test_add_hierarchy_node()
{
SearchIndex index;
SearchIndex::SearchNode* node = index.addNode("util::math::pow");
SearchIndex::SearchNode* node = index.addNode(utility::splitToVector("util::math::pow", "::"));
TS_ASSERT(node);
TS_ASSERT_EQUALS("pow", node->getName());
@@ -67,23 +68,23 @@ public:
void test_reuse_hierarchy_node()
{
SearchIndex index;
SearchIndex::SearchNode* node = index.addNode("math::pow");
SearchIndex::SearchNode* node2 = index.addNode("math::floor");
SearchIndex::SearchNode* node1 = index.addNode(utility::splitToVector("math::pow", "::"));
SearchIndex::SearchNode* node2 = index.addNode(utility::splitToVector("math::floor", "::"));
TS_ASSERT(node);
TS_ASSERT(node1);
TS_ASSERT(node2);
TS_ASSERT_EQUALS("pow", node->getName());
TS_ASSERT_EQUALS("pow", node1->getName());
TS_ASSERT_EQUALS("floor", node2->getName());
TS_ASSERT_EQUALS(node->getParent(), node2->getParent());
TS_ASSERT_EQUALS(node1->getParent(), node2->getParent());
}
void test_clear()
{
SearchIndex index;
index.addNode("math");
index.addNode("string");
index.addNode(utility::splitToVector("math", "::"));
index.addNode(utility::splitToVector("string", "::"));
TS_ASSERT(index.getNode("math"));
@@ -95,9 +96,9 @@ public:
void test_fuzzy_matching()
{
SearchIndex index;
index.addNode("util");
index.addNode("math");
index.addNode("string");
index.addNode(utility::splitToVector("util", "::"));
index.addNode(utility::splitToVector("math", "::"));
index.addNode(utility::splitToVector("string", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("u");
@@ -114,8 +115,8 @@ public:
void test_fuzzy_matching_is_case_insensitive()
{
SearchIndex index;
index.addNode("util");
index.addNode("MATH");
index.addNode(utility::splitToVector("util", "::"));
index.addNode(utility::splitToVector("MATH", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("t");
@@ -133,9 +134,9 @@ public:
void test_fuzzy_matching_wheighs_by_distance_and_alphabet()
{
SearchIndex index;
index.addNode("util");
index.addNode("math");
index.addNode("string");
index.addNode(utility::splitToVector("util", "::"));
index.addNode(utility::splitToVector("math", "::"));
index.addNode(utility::splitToVector("string", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("t");
@@ -157,8 +158,8 @@ public:
void test_fuzzy_matching_wheighs_higher_by_uppercase()
{
SearchIndex index;
index.addNode("uTil");
index.addNode("string");
index.addNode(utility::splitToVector("uTil", "::"));
index.addNode(utility::splitToVector("string", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("t");
@@ -170,8 +171,8 @@ public:
void test_fuzzy_matching_wheighs_higher_on_consecutive_letters()
{
SearchIndex index;
index.addNode("oaabbcc");
index.addNode("ocbaabc");
index.addNode(utility::splitToVector("oaabbcc", "::"));
index.addNode(utility::splitToVector("ocbaabc", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("abc");
@@ -183,9 +184,9 @@ public:
void test_fuzzy_matching_in_hierarchy()
{
SearchIndex index;
index.addNode("util::math::ceil");
index.addNode("util::math::floor");
index.addNode("util::string::concat");
index.addNode(utility::splitToVector("util::math::ceil", "::"));
index.addNode(utility::splitToVector("util::math::floor", "::"));
index.addNode(utility::splitToVector("util::string::concat", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("t");
@@ -202,9 +203,9 @@ public:
void test_fuzzy_matching_in_hierarchy_respects_collin()
{
SearchIndex index;
index.addNode("util::math::ceil");
index.addNode("util::math::floor");
index.addNode("util::string::concat");
index.addNode(utility::splitToVector("util::math::ceil", "::"));
index.addNode(utility::splitToVector("util::math::floor", "::"));
index.addNode(utility::splitToVector("util::string::concat", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("u:i");
@@ -221,8 +222,8 @@ public:
void test_fuzzy_matching_in_hierarchy_weighs_front_letters_higher()
{
SearchIndex index;
index.addNode("abc::dfe::ghi");
index.addNode("abc::hgi");
index.addNode(utility::splitToVector("abc::dfe::ghi", "::"));
index.addNode(utility::splitToVector("abc::hgi", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("g");
@@ -234,9 +235,9 @@ public:
void test_fuzzy_matching_with_defined_start_node()
{
SearchIndex index;
index.addNode("math::ceil");
index.addNode("math::floor");
index.addNode("string::concat");
index.addNode(utility::splitToVector("math::ceil", "::"));
index.addNode(utility::splitToVector("math::floor", "::"));
index.addNode(utility::splitToVector("string::concat", "::"));
std::vector<SearchIndex::SearchMatch> matches = index.findFuzzyMatches("\"math\"c");
+2 -2
View File
@@ -295,14 +295,14 @@ private:
public:
Node* createNodeHierarchy(Node::NodeType type, const std::string& name)
{
SearchIndex::SearchNode* searchNode = m_index.addNode(name);
SearchIndex::SearchNode* searchNode = m_index.addNode(utility::splitToVector(name, "::"));
return StorageGraph::createNodeHierarchy(type, searchNode);
}
Node* createNodeHierarchyWithDistinctSignature(
Node::NodeType type, const std::string& name, Id signatureId
){
SearchIndex::SearchNode* searchNode = m_index.addNode(name);
SearchIndex::SearchNode* searchNode = m_index.addNode(utility::splitToVector(name, "::"));
std::shared_ptr<TokenComponentSignature> signature = std::make_shared<TokenComponentSignature>(signatureId);
return StorageGraph::createNodeHierarchyWithDistinctSignature(type, searchNode, signature);
}
+44 -37
View File
@@ -18,7 +18,7 @@ public:
void test_storage_saves_typedef()
{
TestStorage storage;
Id id = storage.onTypedefParsed(validLocation(1), "type", typeUsage("int"), ParserClient::ACCESS_NONE);
Id id = storage.onTypedefParsed(validLocation(1), utility::splitToVector("type", "::"), typeUsage("int"), ParserClient::ACCESS_NONE);
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -37,7 +37,7 @@ public:
void test_storage_saves_class()
{
TestStorage storage;
Id id = storage.onClassParsed(validLocation(1), "Class", ParserClient::ACCESS_NONE, validLocation(2));
Id id = storage.onClassParsed(validLocation(1), utility::splitToVector("Class", "::"), ParserClient::ACCESS_NONE, validLocation(2));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -54,7 +54,7 @@ public:
void test_storage_saves_struct()
{
TestStorage storage;
Id id = storage.onStructParsed(validLocation(1), "Struct", ParserClient::ACCESS_NONE, validLocation(2));
Id id = storage.onStructParsed(validLocation(1), utility::splitToVector("Struct", "::"), ParserClient::ACCESS_NONE, validLocation(2));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -71,7 +71,7 @@ public:
void test_storage_saves_global_variable()
{
TestStorage storage;
Id id = storage.onGlobalVariableParsed(validLocation(42), ParseVariable(typeUsage("char"), "Global", false));
Id id = storage.onGlobalVariableParsed(validLocation(42), ParseVariable(typeUsage("char"), utility::splitToVector("Global", "::"), false));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -91,7 +91,7 @@ public:
void test_storage_saves_global_variable_static()
{
TestStorage storage;
Id id = storage.onGlobalVariableParsed(validLocation(7), ParseVariable(typeUsage("char"), "Global", true));
Id id = storage.onGlobalVariableParsed(validLocation(7), ParseVariable(typeUsage("char"), utility::splitToVector("Global", "::"), true));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -108,7 +108,7 @@ public:
{
TestStorage storage;
Id id = storage.onFieldParsed(
validLocation(3), ParseVariable(typeUsage("bool"), "m_field", false), ParserClient::ACCESS_NONE
validLocation(3), ParseVariable(typeUsage("bool"), utility::splitToVector("m_field", "::"), false), ParserClient::ACCESS_NONE
);
Node* node = storage.getNodeWithId(id);
@@ -129,7 +129,7 @@ public:
{
TestStorage storage;
Id id = storage.onFieldParsed(
validLocation(11), ParseVariable(typeUsage("bool"), "Struct::m_field", false), ParserClient::ACCESS_PUBLIC
validLocation(11), ParseVariable(typeUsage("bool"), utility::splitToVector("Struct::m_field", "::"), false), ParserClient::ACCESS_PUBLIC
);
Node* node = storage.getNodeWithId(id);
@@ -163,7 +163,7 @@ public:
{
TestStorage storage;
Id id = storage.onFunctionParsed(
validLocation(14), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation(41)
validLocation(14), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")), validLocation(41)
);
Node* node = storage.getNodeWithId(id);
@@ -194,7 +194,7 @@ public:
TestStorage storage;
Id id = storage.onMethodParsed(
validLocation(9),
ParseFunction(typeUsage("void"), "isMethod", parameters("bool")),
ParseFunction(typeUsage("void"), utility::splitToVector("isMethod", "::"), parameters("bool")),
ParserClient::ACCESS_NONE,
ParserClient::ABSTRACTION_NONE,
validLocation(4)
@@ -228,7 +228,7 @@ public:
TestStorage storage;
Id id = storage.onMethodParsed(
validLocation(1),
ParseFunction(typeUsage("void"), "isMethod", parameters("bool"), true),
ParseFunction(typeUsage("void"), utility::splitToVector("isMethod", "::"), parameters("bool"), true),
ParserClient::ACCESS_NONE,
ParserClient::ABSTRACTION_NONE,
validLocation(4)
@@ -246,7 +246,7 @@ public:
TestStorage storage;
Id id = storage.onMethodParsed(
validLocation(1),
ParseFunction(typeUsage("void"), "Class::isMethod", parameters("bool")),
ParseFunction(typeUsage("void"), utility::splitToVector("Class::isMethod", "::"), parameters("bool")),
ParserClient::ACCESS_PROTECTED,
ParserClient::ABSTRACTION_VIRTUAL,
validLocation(4)
@@ -280,7 +280,7 @@ public:
void test_storage_saves_namespace()
{
TestStorage storage;
Id id = storage.onNamespaceParsed(validLocation(1), "utility", validLocation(2));
Id id = storage.onNamespaceParsed(validLocation(1), utility::splitToVector("utility", "::"), validLocation(2));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -297,7 +297,7 @@ public:
void test_storage_saves_enum()
{
TestStorage storage;
Id id = storage.onEnumParsed(validLocation(17), "Category", ParserClient::ACCESS_NONE, validLocation(23));
Id id = storage.onEnumParsed(validLocation(17), utility::splitToVector("Category", "::"), ParserClient::ACCESS_NONE, validLocation(23));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -315,7 +315,9 @@ public:
{
TestStorage storage;
Id id =
storage.onEnumParsed(validLocation(1), "Class::Category", ParserClient::ACCESS_PRIVATE, validLocation(2));
storage.onEnumParsed(validLocation(1), utility::splitToVector("Class::Category", "::"),
ParserClient::ACCESS_PRIVATE, validLocation(2)
);
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -338,7 +340,7 @@ public:
void test_storage_saves_enum_field()
{
TestStorage storage;
Id id = storage.onEnumFieldParsed(validLocation(1), "VALUE");
Id id = storage.onEnumFieldParsed(validLocation(1), utility::splitToVector("VALUE", "::"));
Node* node = storage.getNodeWithId(id);
TS_ASSERT(node);
@@ -353,9 +355,12 @@ public:
void test_storage_saves_inheritance()
{
TestStorage storage;
storage.onClassParsed(validLocation(), "ClassA", ParserClient::ACCESS_NONE, validLocation());
storage.onClassParsed(validLocation(), "ClassB", ParserClient::ACCESS_NONE, validLocation());
Id id = storage.onInheritanceParsed(validLocation(5), "ClassB", "ClassA", ParserClient::ACCESS_PUBLIC);
storage.onClassParsed(validLocation(), utility::splitToVector("ClassA", "::"), ParserClient::ACCESS_NONE, validLocation());
storage.onClassParsed(validLocation(), utility::splitToVector("ClassB", "::"), ParserClient::ACCESS_NONE, validLocation());
Id id =
storage.onInheritanceParsed(validLocation(5), utility::splitToVector("ClassB", "::"),
utility::splitToVector("ClassA", "::"), ParserClient::ACCESS_PUBLIC
);
Edge* edge = storage.getEdgeWithId(id);
TS_ASSERT(edge);
@@ -376,15 +381,15 @@ public:
{
TestStorage storage;
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation()
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")), validLocation()
);
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("void"), "func", parameters("bool")), validLocation()
validLocation(), ParseFunction(typeUsage("void"), utility::splitToVector("func", "::"), parameters("bool")), validLocation()
);
Id id = storage.onCallParsed(
validLocation(9),
ParseFunction(typeUsage("bool"), "isTrue", parameters("char")),
ParseFunction(typeUsage("void"), "func", parameters("bool"))
ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")),
ParseFunction(typeUsage("void"), utility::splitToVector("func", "::"), parameters("bool"))
);
Edge* edge = storage.getEdgeWithId(id);
@@ -402,15 +407,15 @@ public:
void test_storage_saves_call_in_global_variable_declaration()
{
TestStorage storage;
storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false));
storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), utility::splitToVector("global", "::"), false));
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation()
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")), validLocation()
);
Id id = storage.onCallParsed(
validLocation(7),
ParseVariable(typeUsage("bool"), "global", false),
ParseFunction(typeUsage("bool"), "isTrue", parameters("char"))
ParseVariable(typeUsage("bool"), utility::splitToVector("global", "::"), false),
ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char"))
);
Edge* edge = storage.getEdgeWithId(id);
@@ -429,16 +434,16 @@ public:
{
TestStorage storage;
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation()
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")), validLocation()
);
storage.onFieldParsed(
validLocation(), ParseVariable(typeUsage("bool"), "Foo::m_field", false), ParserClient::ACCESS_PRIVATE
validLocation(), ParseVariable(typeUsage("bool"), utility::splitToVector("Foo::m_field", "::"), false), ParserClient::ACCESS_PRIVATE
);
Id id = storage.onFieldUsageParsed(
validLocation(7),
ParseFunction(typeUsage("bool"), "isTrue", parameters("char")),
"Foo::m_field"
ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")),
utility::splitToVector("Foo::m_field", "::")
);
Edge* edge = storage.getEdgeWithId(id);
@@ -457,14 +462,14 @@ public:
{
TestStorage storage;
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation()
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")), validLocation()
);
storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false));
storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), utility::splitToVector("global", "::"), false));
Id id = storage.onGlobalVariableUsageParsed(
validLocation(7),
ParseFunction(typeUsage("bool"), "isTrue", parameters("char")),
"global"
ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char")),
utility::splitToVector("global", "::")
);
Edge* edge = storage.getEdgeWithId(id);
@@ -483,13 +488,15 @@ public:
{
TestStorage storage;
storage.onFunctionParsed(
validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation()
validLocation(), ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"),
parameters("char")), validLocation()
);
storage.onStructParsed(validLocation(), "Struct", ParserClient::ACCESS_NONE, validLocation());
storage.onStructParsed(
validLocation(), utility::splitToVector("Struct", "::"), ParserClient::ACCESS_NONE, validLocation());
Id id = storage.onTypeUsageParsed(
typeUsage("Struct"),
ParseFunction(typeUsage("bool"), "isTrue", parameters("char"))
ParseFunction(typeUsage("bool"), utility::splitToVector("isTrue", "::"), parameters("char"))
);
Edge* edge = storage.getEdgeWithId(id);