diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 57a99372..ae097708 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -19,6 +19,45 @@ ConfigManager.cpp ERROR: value Int is not present in config. ConfigManager.cpp ERROR: value Float is not present in config. ConfigManager.cpp ERROR: value String is not present in config. ConfigManager.cpp ERROR: value NewBool is not present in config. +Storage.cpp INFO: typedef: type -> int +Storage.cpp INFO: class: Class +Storage.cpp INFO: struct: Struct +Storage.cpp INFO: global: Global +Storage.cpp INFO: global: Global +Storage.cpp INFO: field: m_field +Storage.cpp ERROR: Field is not a member of anything. +Storage.cpp ERROR: Field needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: field: Struct::m_field +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: method: isMethod +Storage.cpp ERROR: Method is not a member of anything. +Storage.cpp ERROR: Method needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: method: isMethod +Storage.cpp ERROR: Method is not a member of anything. +Storage.cpp ERROR: Method needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: method: Class::isMethod +Storage.cpp INFO: namespace: utility +Storage.cpp INFO: enum: Category +Storage.cpp INFO: enum: Class::Category +Storage.cpp INFO: enum field: VALUE +Storage.cpp INFO: class: ClassA +Storage.cpp INFO: class: ClassB +Storage.cpp INFO: inheritance: ClassB : ClassA +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: function: func +Storage.cpp INFO: call: isTrue -> func +Storage.cpp INFO: global: global +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: call: global -> isTrue +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: field: Foo::m_field +Storage.cpp INFO: field usage: isTrue -> Foo::m_field +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: global: global +Storage.cpp INFO: global usage: isTrue -> global +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: struct: Struct +Storage.cpp INFO: type usage: isTrue -> Struct TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index a5f4d5df..26ca60fe 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -39,7 +39,7 @@ void Storage::logLocations() const } -void Storage::onTypedefParsed( +Id Storage::onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access ){ log("typedef", fullName + " -> " + underlyingType.dataType.getFullTypeName(), location); @@ -48,31 +48,37 @@ void Storage::onTypedefParsed( addAccess(node, access); addTokenLocation(node, location); addTypeEdge(node, Edge::EDGE_TYPEDEF_OF, underlyingType); + + return node->getId(); } -void Storage::onClassParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onClassParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("class", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_CLASS, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onStructParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onStructParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("struct", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_STRUCT, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) +Id Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) { log("global", variable.fullName, location); @@ -85,14 +91,21 @@ void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseV addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) +Id Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) { log("field", variable.fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, variable.fullName); + if (!node->getMemberEdge()) + { + LOG_ERROR("Field is not a member of anything."); + } + if (variable.isStatic) { node->addComponentStatic(std::make_shared()); @@ -101,15 +114,16 @@ void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& if (access == ACCESS_NONE) { LOG_ERROR("Field needs to have access type [public, protected, private] but has none."); - return; } addAccess(node, access); addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onFunctionParsed( +Id Storage::onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation ){ log("function", function.fullName, location); @@ -126,9 +140,11 @@ void Storage::onFunctionParsed( { addTypeEdge(node, Edge::EDGE_PARAMETER_TYPE_OF, parameter); } + + return node->getId(); } -void Storage::onMethodParsed( +Id Storage::onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation ){ @@ -138,6 +154,11 @@ void Storage::onMethodParsed( Node::NODE_METHOD, method.fullName, ParserClient::functionSignatureStr(method) ); + if (!node->getMemberEdge()) + { + LOG_ERROR("Method is not a member of anything."); + } + if (method.isConst) { node->addComponentConst(std::make_shared()); @@ -151,7 +172,6 @@ void Storage::onMethodParsed( if (access == ACCESS_NONE) { LOG_ERROR("Method needs to have access type [public, protected, private] but has none."); - return; } addAccess(node, access); @@ -163,40 +183,48 @@ void Storage::onMethodParsed( { addTypeEdge(node, Edge::EDGE_PARAMETER_TYPE_OF, parameter); } + + return node->getId(); } -void Storage::onNamespaceParsed( - const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) -{ +Id Storage::onNamespaceParsed( + const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation +){ log("namespace", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_NAMESPACE, fullName); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onEnumParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onEnumParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("enum", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_ENUM, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) +Id Storage::onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) { log("enum field", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, fullName); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onInheritanceParsed( - const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) -{ +Id Storage::onInheritanceParsed( + const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access +){ log("inheritance", fullName + " : " + baseName, location); Node* node = m_graph.createNodeHierarchy(fullName); @@ -206,9 +234,11 @@ void Storage::onInheritanceParsed( edge->addComponentAccess(std::make_shared(convertAccessType(access))); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onCallParsed(const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) +Id Storage::onCallParsed(const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) { log("call", caller.fullName + " -> " + callee.fullName, location); @@ -220,9 +250,11 @@ void Storage::onCallParsed(const ParseLocation& location, const ParseFunction& c Edge* edge = m_graph.createEdge(Edge::EDGE_CALL, callerNode, calleeNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onCallParsed(const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) +Id Storage::onCallParsed(const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) { log("call", caller.fullName + " -> " + callee.fullName, location); @@ -234,9 +266,11 @@ void Storage::onCallParsed(const ParseLocation& location, const ParseVariable& c Edge* edge = m_graph.createEdge(Edge::EDGE_CALL, callerNode, calleeNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunction& user, const std::string& usedName) +Id Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { log("field usage", user.fullName + " -> " + usedName, location); @@ -246,9 +280,11 @@ void Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunct Edge* edge = m_graph.createEdge(Edge::EDGE_USAGE, userNode, usedNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onGlobalVariableUsageParsed( +Id Storage::onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName ){ log("global usage", user.fullName + " -> " + usedName, location); @@ -259,15 +295,19 @@ void Storage::onGlobalVariableUsageParsed( Edge* edge = m_graph.createEdge(Edge::EDGE_USAGE, userNode, usedNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) +Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) { log("type usage", function.fullName + " -> " + type.dataType.getRawTypeName(), type.location); Node* functionNode = m_graph.createNodeHierarchyWithDistinctSignature(function.fullName, ParserClient::functionSignatureStr(function)); - addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type); + Edge* edge = addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type); + + return edge->getId(); } Id Storage::getIdForNodeWithName(const std::string& fullName) const @@ -571,6 +611,24 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile( return ret; } +Token* Storage::getTokenWithId(Id tokenId) const +{ + return m_graph.getTokenById(tokenId); +} + +std::vector Storage::getTokenLocationsForId(Id tokenId) const +{ + const std::vector& locationIds = getTokenWithId(tokenId)->getLocationIds(); + + std::vector result; + for (Id locationId : locationIds) + { + result.push_back(m_locationCollection.findTokenLocationById(locationId)); + } + + return result; +} + TokenComponentAccess::AccessType Storage::convertAccessType(ParserClient::AccessType access) const { switch (access) diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 5269f060..f4575a9c 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -26,41 +26,41 @@ public: void logLocations() const; // ParserClient implementation - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access); - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable); - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access); + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable); + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access); - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation); - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation); - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation); - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName); + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName); - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access); - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee); - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee); - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName); - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName); - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); // GraphAccess implementation virtual Id getIdForNodeWithName(const std::string& fullName) const; @@ -90,6 +90,10 @@ public: const std::string& filePath, uint firstLineNumber, uint lastLineNumber ) const; +protected: + Token* getTokenWithId(Id tokenId) const; + std::vector getTokenLocationsForId(Id tokenId) const; + private: TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const; TokenComponentAccess* addAccess(Node* node, ParserClient::AccessType access); diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 7e4b5e4d..00fb0eb2 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -4,6 +4,8 @@ #include #include +#include "utility/types.h" + struct ParseFunction; struct ParseLocation; struct ParseTypeUsage; @@ -42,44 +44,44 @@ public: ParserClient(); virtual ~ParserClient(); - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access) = 0; - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) = 0; - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) = 0; + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) = 0; + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) = 0; - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation) = 0; - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation) = 0; - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) = 0; - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) = 0; + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) = 0; - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) = 0; - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) = 0; - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) = 0; - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) = 0; - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) = 0; - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; }; #endif // PARSER_CLIENT_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index ee118fac..c751f0ab 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -9,6 +9,7 @@ add_files( LogManagerTestSuite.h MessageQueueTestSuite.h SettingsTestSuite.h + StorageTestSuite.h TestSuiteFixture.cpp TestSuiteFixture.h TextAccessTestSuite.h diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 8663dff6..3d36c2ca 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1,7 +1,5 @@ #include "cxxtest/TestSuite.h" -#include - #include "data/parser/cxx/CxxParser.h" #include "data/parser/ParseFunction.h" #include "data/parser/ParseLocation.h" @@ -992,40 +990,45 @@ private: class TestParserClient: public ParserClient { public: - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access ) { std::string str = addAccessPrefix(underlyingType.dataType.getFullTypeName() + " -> " + fullName, access); typedefs.push_back(addLocationSuffix(str, location)); + return 0; } - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { classes.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { structs.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) { globalVariables.push_back(addLocationSuffix(variableStr(variable), location)); + return 0; } - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) { fields.push_back(addLocationSuffix(addAccessPrefix(variableStr(variable), access), location)); + return 0; } - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation ){ functions.push_back(addLocationSuffix(functionStr(function), location, scopeLocation)); @@ -1035,9 +1038,10 @@ private: { addTypeUse(parameter); } + return 0; } - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation ){ @@ -1052,60 +1056,70 @@ private: { addTypeUse(parameter); } + return 0; } - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) { namespaces.push_back(addLocationSuffix(fullName, location, scopeLocation)); + return 0; } - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { enums.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) { enumFields.push_back(addLocationSuffix(fullName, location)); + return 0; } - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) { std::string str = fullName + " : " + addAccessPrefix(baseName, access); inheritances.push_back(addLocationSuffix(str, location)); + return 0; } - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) { calls.push_back(addLocationSuffix(functionStr(caller) + " -> " + functionStr(callee), location)); + return 0; } - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) { calls.push_back(addLocationSuffix(caller.fullName + " -> " + functionStr(callee), location)); + return 0; } - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location)); + return 0; } - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location)); + return 0; } - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) { addTypeUse(type, function); + return 0; } std::vector typedefs; diff --git a/src/test/StorageTestSuite.h b/src/test/StorageTestSuite.h new file mode 100644 index 00000000..425e0573 --- /dev/null +++ b/src/test/StorageTestSuite.h @@ -0,0 +1,545 @@ +#include "cxxtest/TestSuite.h" + +#include "data/graph/token_component/TokenComponentAccess.h" +#include "data/graph/token_component/TokenComponentSignature.h" +#include "data/graph/token_component/TokenComponentStatic.h" +#include "data/location/TokenLocation.h" +#include "data/parser/ParseFunction.h" +#include "data/parser/ParseLocation.h" +#include "data/parser/ParseTypeUsage.h" +#include "data/parser/ParseVariable.h" +#include "data/Storage.h" +#include "data/type/DataType.h" + +class StorageTestSuite: public CxxTest::TestSuite +{ +public: + void test_storage_saves_typedef() + { + TestStorage storage; + Id id = storage.onTypedefParsed(validLocation(1), "type", typeUsage("int"), ParserClient::ACCESS_NONE); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "type"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_TYPEDEF); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPEDEF_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "int"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 1)); + } + + void test_storage_saves_class() + { + TestStorage storage; + Id id = storage.onClassParsed(validLocation(1), "Class", ParserClient::ACCESS_NONE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Class"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_CLASS); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_struct() + { + TestStorage storage; + Id id = storage.onStructParsed(validLocation(1), "Struct", ParserClient::ACCESS_NONE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Struct"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_STRUCT); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_global_variable() + { + TestStorage storage; + Id id = storage.onGlobalVariableParsed(validLocation(42), ParseVariable(typeUsage("char"), "Global", false)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Global"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_GLOBAL_VARIABLE); + TS_ASSERT(!node->getComponent()); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "char"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 42)); + } + + void test_storage_saves_global_variable_static() + { + TestStorage storage; + Id id = storage.onGlobalVariableParsed(validLocation(7), ParseVariable(typeUsage("char"), "Global", true)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Global"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_GLOBAL_VARIABLE); + TS_ASSERT(node->getComponent()); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_field() + { + TestStorage storage; + Id id = storage.onFieldParsed( + validLocation(3), ParseVariable(typeUsage("bool"), "m_field", false), ParserClient::ACCESS_NONE + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "m_field"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "bool"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 3)); + } + + void test_storage_saves_field_as_member() + { + TestStorage storage; + Id id = storage.onFieldParsed( + validLocation(11), ParseVariable(typeUsage("bool"), "Struct::m_field", false), ParserClient::ACCESS_PUBLIC + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getName(), "m_field"); + TS_ASSERT_EQUALS(node->getFullName(), "Struct::m_field"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PUBLIC + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Struct"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "bool"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 11)); + } + + void test_storage_saves_function() + { + TestStorage storage; + Id id = storage.onFunctionParsed( + validLocation(14), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation(41) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FUNCTION); + + Edge* returnEdge = node->findEdgeOfType(Edge::EDGE_RETURN_TYPE_OF); + TS_ASSERT(returnEdge); + TS_ASSERT_EQUALS(returnEdge->getTo()->getFullName(), "bool"); + + Edge* paramEdge = node->findEdgeOfType(Edge::EDGE_PARAMETER_TYPE_OF); + TS_ASSERT(paramEdge); + TS_ASSERT_EQUALS(paramEdge->getTo()->getFullName(), "char"); + + TS_ASSERT(node->getComponent()); + TS_ASSERT_EQUALS(node->getComponent()->getSignature(), "isTrue(char)"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 14)); + TS_ASSERT(isValidLocation(locations[1], 41)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_method() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(9), + ParseFunction(typeUsage("void"), "isMethod", parameters("bool")), + ParserClient::ACCESS_NONE, + ParserClient::ABSTRACTION_NONE, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + + Edge* returnEdge = node->findEdgeOfType(Edge::EDGE_RETURN_TYPE_OF); + TS_ASSERT(returnEdge); + TS_ASSERT_EQUALS(returnEdge->getTo()->getFullName(), "void"); + + Edge* paramEdge = node->findEdgeOfType(Edge::EDGE_PARAMETER_TYPE_OF); + TS_ASSERT(paramEdge); + TS_ASSERT_EQUALS(paramEdge->getTo()->getFullName(), "bool"); + + TS_ASSERT(node->getComponent()); + TS_ASSERT_EQUALS(node->getComponent()->getSignature(), "isMethod(bool)"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 9)); + TS_ASSERT(isValidLocation(locations[1], 4)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_method_static() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(1), + ParseFunction(typeUsage("void"), "isMethod", parameters("bool"), true), + ParserClient::ACCESS_NONE, + ParserClient::ABSTRACTION_NONE, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + TS_ASSERT(node->getComponent()); + } + + void test_storage_saves_method_as_member() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(1), + ParseFunction(typeUsage("void"), "Class::isMethod", parameters("bool")), + ParserClient::ACCESS_PROTECTED, + ParserClient::ABSTRACTION_VIRTUAL, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getName(), "isMethod"); + TS_ASSERT_EQUALS(node->getFullName(), "Class::isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PROTECTED + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Class"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + } + + void test_storage_saves_namespace() + { + TestStorage storage; + Id id = storage.onNamespaceParsed(validLocation(1), "utility", validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "utility"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_NAMESPACE); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_enum() + { + TestStorage storage; + Id id = storage.onEnumParsed(validLocation(17), "Category", ParserClient::ACCESS_NONE, validLocation(23)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Category"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_ENUM); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 17)); + TS_ASSERT(isValidLocation(locations[1], 23)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_enum_as_member() + { + TestStorage storage; + Id id = + storage.onEnumParsed(validLocation(1), "Class::Category", ParserClient::ACCESS_PRIVATE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Class::Category"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_ENUM); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PRIVATE + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Class"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + } + + void test_storage_saves_enum_field() + { + TestStorage storage; + Id id = storage.onEnumFieldParsed(validLocation(1), "VALUE"); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "VALUE"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 1)); + } + + 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); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_INHERITANCE); + + TS_ASSERT(edge->getComponent()); + TS_ASSERT_EQUALS(edge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PUBLIC); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "ClassB"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "ClassA"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 5)); + } + + void test_storage_saves_call() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("void"), "func", parameters("bool")), validLocation() + ); + Id id = storage.onCallParsed( + validLocation(9), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + ParseFunction(typeUsage("void"), "func", parameters("bool")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_CALL); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "func"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 9)); + } + + void test_storage_saves_call_in_global_variable_declaration() + { + TestStorage storage; + storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false)); + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + + Id id = storage.onCallParsed( + validLocation(7), + ParseVariable(typeUsage("bool"), "global", false), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_CALL); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "global"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "isTrue"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_field_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onFieldParsed( + validLocation(), ParseVariable(typeUsage("bool"), "Foo::m_field", false), ParserClient::ACCESS_PRIVATE + ); + + Id id = storage.onFieldUsageParsed( + validLocation(7), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + "Foo::m_field" + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "Foo::m_field"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_global_variable_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false)); + + Id id = storage.onGlobalVariableUsageParsed( + validLocation(7), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + "global" + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "global"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_type_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onStructParsed(validLocation(), "Struct", ParserClient::ACCESS_NONE, validLocation()); + + Id id = storage.onTypeUsageParsed( + typeUsage("Struct"), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_TYPE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "Struct"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 0)); + } + +private: + class TestStorage + : public Storage + { + public: + Node* getNodeWithId(Id id) const + { + return dynamic_cast(getTokenWithId(id)); + } + + Edge* getEdgeWithId(Id id) const + { + return dynamic_cast(getTokenWithId(id)); + } + + std::vector getLocationsForId(Id id) const + { + return getTokenLocationsForId(id); + } + }; + + ParseLocation validLocation(Id locationId = 0) const + { + return ParseLocation("file.cpp", 1, locationId, 1, locationId); + } + + bool isValidLocation(TokenLocation* location, Id locationId) const + { + return + location->getFilePath() == "file.cpp" && + location->getLineNumber() == 1 && + location->getColumnNumber() == locationId; + } + + ParseTypeUsage typeUsage(const std::string& typeName) const + { + return ParseTypeUsage(validLocation(), DataType(typeName)); + } + + std::vector parameters(const std::string& param) const + { + std::vector params; + params.push_back(typeUsage(param)); + return params; + } +}; diff --git a/src/test/TextAccessTestSuite.h b/src/test/TextAccessTestSuite.h index 1205f424..1e9eb539 100644 --- a/src/test/TextAccessTestSuite.h +++ b/src/test/TextAccessTestSuite.h @@ -1,8 +1,5 @@ #include "cxxtest/TestSuite.h" -#include -#include - #include "utility/text/TextAccess.h" class TextAccessTestSuite : public CxxTest::TestSuite