data: parsing file dependencies
This change adds the node NODE_FILE to the graph and the edge EDGE_INCLUDE, which determine the dependencies between files by parsing the include preprocessor directive. File nodes can be searched and displayed in the GraphView as file dependency graph. The filter "file" allows for selecting all files. The file depency information is used on project refresh do determine which files need to get reparsed.
This commit is contained in:
@@ -1709,6 +1709,10 @@ public:
|
||||
TS_ASSERT_EQUALS(client.calls.size(), 2);
|
||||
TS_ASSERT_EQUALS(client.usages.size(), 3);
|
||||
TS_ASSERT_EQUALS(client.typeUses.size(), 8);
|
||||
|
||||
TS_ASSERT_EQUALS(client.files.size(), 2);
|
||||
TS_ASSERT_EQUALS(client.includes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client.includes[0], client.files[1] + " -> " + client.files[0]);
|
||||
}
|
||||
|
||||
void test_cxx_parser_catches_error()
|
||||
@@ -1954,6 +1958,19 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onFileParsed(const std::string& filePath)
|
||||
{
|
||||
files.push_back(filePath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onFileIncludeParsed(
|
||||
const ParseLocation& location, const std::string& filePath, const std::string& includedPath)
|
||||
{
|
||||
includes.push_back(filePath + " -> " + includedPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> errors;
|
||||
|
||||
std::vector<std::string> typedefs;
|
||||
@@ -1977,6 +1994,9 @@ private:
|
||||
std::vector<std::string> templateDefaultArgumentTypes;
|
||||
std::vector<std::string> templateSpecializations;
|
||||
|
||||
std::vector<std::string> files;
|
||||
std::vector<std::string> includes;
|
||||
|
||||
private:
|
||||
void addTypeUse(const ParseTypeUsage& use)
|
||||
{
|
||||
|
||||
@@ -20,13 +20,9 @@ public:
|
||||
|
||||
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
|
||||
|
||||
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
|
||||
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
|
||||
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
|
||||
|
||||
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(updatedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(removedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getAddedFilePaths().size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getUpdatedFilePaths().size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getRemovedFilePaths().size(), 0);
|
||||
}
|
||||
|
||||
void test_file_manager_has_added_file_paths_after_first_fetch()
|
||||
@@ -45,11 +41,7 @@ public:
|
||||
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
|
||||
fm.fetchFilePaths();
|
||||
|
||||
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
|
||||
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
|
||||
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
|
||||
|
||||
TS_ASSERT_EQUALS(addedFilePaths.size(), 4);
|
||||
TS_ASSERT_EQUALS(fm.getAddedFilePaths().size(), 4);
|
||||
}
|
||||
|
||||
void test_file_manager_has_no_added_file_paths_after_second_fetch()
|
||||
@@ -69,11 +61,7 @@ public:
|
||||
fm.fetchFilePaths();
|
||||
fm.fetchFilePaths();
|
||||
|
||||
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
|
||||
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
|
||||
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
|
||||
|
||||
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getAddedFilePaths().size(), 0);
|
||||
}
|
||||
|
||||
void test_file_manager_has_updated_file_paths_after_second_fetch()
|
||||
@@ -99,12 +87,8 @@ public:
|
||||
|
||||
fm.fetchFilePaths();
|
||||
|
||||
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
|
||||
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
|
||||
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
|
||||
|
||||
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(updatedFilePaths.size(), 1);
|
||||
TS_ASSERT_EQUALS(removedFilePaths.size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getAddedFilePaths().size(), 0);
|
||||
TS_ASSERT_EQUALS(fm.getUpdatedFilePaths().size(), 1);
|
||||
TS_ASSERT_EQUALS(fm.getRemovedFilePaths().size(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,18 +11,18 @@ public:
|
||||
void test_token_query()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("\"main\""),
|
||||
printedFilteredTestGraph("\"_main_\""),
|
||||
|
||||
"1 nodes: function:main\n"
|
||||
"1 nodes: function:_main_\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
|
||||
void test_token_query_with_id()
|
||||
{
|
||||
std::set<Id> ids = getIdsForNodeWithName("main");
|
||||
std::set<Id> ids = getIdsForNodeWithName("_main_");
|
||||
std::stringstream ss;
|
||||
ss << "\"main";
|
||||
ss << "\"_main_";
|
||||
for (Id id : ids)
|
||||
{
|
||||
ss << ',' << id;
|
||||
@@ -30,16 +30,16 @@ public:
|
||||
ss << '"';
|
||||
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(ss.str()), // "main,<id>"
|
||||
printedFilteredTestGraph(ss.str()), // "_main_,<id>"
|
||||
|
||||
"1 nodes: function:main\n"
|
||||
"1 nodes: function:_main_\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
|
||||
void test_token_query_with_id_and_wrong_name_uses_id()
|
||||
{
|
||||
std::set<Id> ids = getIdsForNodeWithName("main");
|
||||
std::set<Id> ids = getIdsForNodeWithName("_main_");
|
||||
std::stringstream ss;
|
||||
ss << "\"hello";
|
||||
for (Id id : ids)
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(ss.str()), // "hello,<id>"
|
||||
|
||||
"1 nodes: function:main\n"
|
||||
"1 nodes: function:_main_\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -97,13 +97,12 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("!'method'"),
|
||||
|
||||
"7 nodes: "
|
||||
"class:A field:A::count undefined_type:int undefined_type:void class:B function:main "
|
||||
"undefined_function:B::B\n"
|
||||
"14 edges: "
|
||||
"child:A->A::count aggregation:A->int aggregation:A->void type_use:A::count->int inheritance:B->A "
|
||||
"aggregation:B->void aggregation:A->B aggregation:B->int return_type:main->int type_usage:main->B "
|
||||
"child:B->B::B call:main->B::B aggregation:main->B aggregation:main->A\n"
|
||||
"8 nodes: "
|
||||
"file:/Users/ebsi/Documents/masterproject/bin/test/input.cc class:A field:A::count undefined_type:int "
|
||||
"undefined_type:void class:B function:_main_ undefined_function:B::B\n"
|
||||
"14 edges: child:A->A::count aggregation:A->int aggregation:A->void type_use:A::count->int inheritance:B->A "
|
||||
"aggregation:B->void aggregation:A->B aggregation:B->int return_type:_main_->int type_usage:_main_->B "
|
||||
"child:B->B::B call:_main_->B::B aggregation:_main_->B aggregation:_main_->A\n"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -219,7 +218,7 @@ private:
|
||||
" }\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"int _main_()\n"
|
||||
"{\n"
|
||||
" B b;\n"
|
||||
"\n"
|
||||
|
||||
@@ -573,7 +573,9 @@ public:
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 3);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, m_filePath));
|
||||
std::set<std::string> files;
|
||||
files.insert(m_filePath);
|
||||
storage.clearFileData(files);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 0);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 0);
|
||||
@@ -602,7 +604,9 @@ public:
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 6);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, "file.cpp"));
|
||||
std::set<std::string> files;
|
||||
files.insert("file.cpp");
|
||||
storage.clearFileData(files);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 3);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 2);
|
||||
@@ -631,7 +635,9 @@ public:
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
|
||||
|
||||
storage.clearFileData(std::vector<std::string>(1, "file.h"));
|
||||
std::set<std::string> files;
|
||||
files.insert("file.h");
|
||||
storage.clearFileData(files);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 4);
|
||||
TS_ASSERT_EQUALS(storage.graph().getEdgeCount(), 3);
|
||||
@@ -660,9 +666,9 @@ public:
|
||||
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
|
||||
|
||||
std::vector<std::string> filePaths;
|
||||
filePaths.push_back("file.cpp");
|
||||
filePaths.push_back("file.h");
|
||||
std::set<std::string> filePaths;
|
||||
filePaths.insert("file.cpp");
|
||||
filePaths.insert("file.h");
|
||||
storage.clearFileData(filePaths);
|
||||
|
||||
TS_ASSERT_EQUALS(storage.graph().getNodeCount(), 0);
|
||||
@@ -671,6 +677,65 @@ public:
|
||||
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 0);
|
||||
}
|
||||
|
||||
void test_storage_saves_file_nodes()
|
||||
{
|
||||
TestStorage storage;
|
||||
|
||||
Id id = storage.onFileParsed("file.h");
|
||||
Node* node = storage.getNodeWithId(id);
|
||||
|
||||
TS_ASSERT(node);
|
||||
TS_ASSERT_EQUALS(node->getName(), "file.h");
|
||||
TS_ASSERT_EQUALS(node->getType(), Node::NODE_FILE);
|
||||
}
|
||||
|
||||
void test_storage_saves_include_edge()
|
||||
{
|
||||
TestStorage storage;
|
||||
|
||||
storage.onFileParsed("file.h");
|
||||
storage.onFileParsed("file.cpp");
|
||||
Id id = storage.onFileIncludeParsed(validLocation(7), "file.cpp", "file.h");
|
||||
|
||||
Edge* edge = storage.getEdgeWithId(id);
|
||||
TS_ASSERT(edge);
|
||||
TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_INCLUDE);
|
||||
|
||||
TS_ASSERT_EQUALS(edge->getFrom()->getName(), "file.cpp");
|
||||
TS_ASSERT_EQUALS(edge->getTo()->getName(), "file.h");
|
||||
|
||||
std::vector<TokenLocation*> locations = storage.getLocationsForId(id);
|
||||
TS_ASSERT_EQUALS(locations.size(), 1);
|
||||
TS_ASSERT(isValidLocation(locations[0], 7));
|
||||
}
|
||||
|
||||
void test_storage_finds_and_removes_depending_file_nodes()
|
||||
{
|
||||
TestStorage storage;
|
||||
|
||||
Id id1 = storage.onFileParsed("f.h");
|
||||
Id id2 = storage.onFileParsed("file.h");
|
||||
Id id3 = storage.onFileParsed("file.cpp");
|
||||
Id id4 = storage.onFileIncludeParsed(validLocation(), "file.h", "f.h");
|
||||
Id id5 = storage.onFileIncludeParsed(validLocation(), "file.cpp", "file.h");
|
||||
|
||||
std::string name1 = storage.getNodeWithId(id2)->getFullName();
|
||||
std::string name2 = storage.getNodeWithId(id3)->getFullName();
|
||||
|
||||
std::set<std::string> filePaths;
|
||||
filePaths.insert(name1);
|
||||
std::set<std::string> dependingFilePaths = storage.getDependingFilePathsAndRemoveFileNodes(filePaths);
|
||||
|
||||
TS_ASSERT_EQUALS(dependingFilePaths.size(), 1);
|
||||
TS_ASSERT_EQUALS(*dependingFilePaths.begin(), name2);
|
||||
|
||||
TS_ASSERT(storage.getNodeWithId(id1));
|
||||
TS_ASSERT(!storage.getNodeWithId(id2));
|
||||
TS_ASSERT(!storage.getNodeWithId(id3));
|
||||
TS_ASSERT(!storage.getEdgeWithId(id4));
|
||||
TS_ASSERT(!storage.getEdgeWithId(id5));
|
||||
}
|
||||
|
||||
private:
|
||||
class TestStorage
|
||||
: public Storage
|
||||
|
||||
Reference in New Issue
Block a user