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:
@@ -1,37 +1,11 @@
|
||||
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 8:2 8:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 9:3 9:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 12:13 12:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 14:10 14:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 18:15 18:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 21:13 21:17>
|
||||
Storage.cpp INFO: class: B <input.cc 24:7 24:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 25:4 25:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 28:15 28:21>
|
||||
Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 30:3 30:5>
|
||||
Storage.cpp INFO: function: main <input.cc 34:5 34:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 36:2 36:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 36:4 36:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 38:9 38:21>
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "main":
|
||||
474 main
|
||||
^^^^
|
||||
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "main":
|
||||
474 main
|
||||
^^^^
|
||||
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "A::A":
|
||||
237 A::A
|
||||
^^^^
|
||||
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Storage.cpp INFO: file: input.cc < 0:0 0:0>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
@@ -48,12 +22,40 @@ Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
|
||||
Storage.cpp INFO: file: input.cc < 0:0 0:0>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 8:2 8:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 9:3 9:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 12:13 12:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 14:10 14:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 18:15 18:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 21:13 21:17>
|
||||
Storage.cpp INFO: class: B <input.cc 24:7 24:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 25:4 25:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 28:15 28:21>
|
||||
Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 30:3 30:5>
|
||||
Storage.cpp INFO: function: _main_ <input.cc 34:5 34:10>
|
||||
Storage.cpp INFO: type usage: _main_ -> B <input.cc 36:2 36:2>
|
||||
Storage.cpp INFO: call: _main_ -> B::B <input.cc 36:4 36:4>
|
||||
Storage.cpp INFO: call: _main_ -> A::getCount <input.cc 38:9 38:21>
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "_main_":
|
||||
755 _main_
|
||||
^^^^^^
|
||||
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "_main_":
|
||||
755 _main_
|
||||
^^^^^^
|
||||
|
||||
SearchMatch.cpp INFO:
|
||||
1 matches for "A::A":
|
||||
237 A::A
|
||||
^^^^
|
||||
|
||||
Settings.cpp WARNING: File for Settings not found.
|
||||
ConfigManager.cpp ERROR: value Bool is not present in config.
|
||||
ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
@@ -69,7 +71,6 @@ 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.
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:1 1:1>
|
||||
@@ -125,6 +126,16 @@ Storage.cpp INFO: call: main -> isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: function: isTrue <file.h 1:0 1:0>
|
||||
Storage.cpp INFO: function: main <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: call: main -> isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: file: file.h < 0:0 0:0>
|
||||
Storage.cpp INFO: file: file.h < 0:0 0:0>
|
||||
Storage.cpp INFO: file: file.cpp < 0:0 0:0>
|
||||
Storage.cpp INFO: include: file.h <file.cpp 1:7 1:7>
|
||||
Storage.cpp INFO: file: f.h < 0:0 0:0>
|
||||
Storage.cpp INFO: file: file.h < 0:0 0:0>
|
||||
Storage.cpp INFO: file: file.cpp < 0:0 0:0>
|
||||
Storage.cpp INFO: include: f.h <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: include: file.h <file.cpp 1:0 1:0>
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
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
|
||||
|
||||
@@ -49,6 +49,7 @@ QFont QtGraphNode::getFontForNodeType(Node::NodeType type)
|
||||
case Node::NODE_ENUM:
|
||||
case Node::NODE_TYPEDEF:
|
||||
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
case Node::NODE_FILE:
|
||||
font.setPixelSize(14);
|
||||
break;
|
||||
|
||||
@@ -321,6 +322,7 @@ void QtGraphNode::setStyle()
|
||||
case Node::NODE_ENUM:
|
||||
case Node::NODE_TYPEDEF:
|
||||
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
case Node::NODE_FILE:
|
||||
if (m_isActive)
|
||||
{
|
||||
font.setWeight(QFont::Bold);
|
||||
|
||||
@@ -17,6 +17,8 @@ add_files(
|
||||
data/parser/cxx/CxxDiagnosticConsumer.h
|
||||
data/parser/cxx/CxxParser.cpp
|
||||
data/parser/cxx/CxxParser.h
|
||||
data/parser/cxx/PreprocessorCallbacks.cpp
|
||||
data/parser/cxx/PreprocessorCallbacks.h
|
||||
data/parser/cxx/utilityCxx.cpp
|
||||
data/parser/cxx/utilityCxx.h
|
||||
)
|
||||
|
||||
+19
-10
@@ -84,33 +84,42 @@ void Project::parseCode()
|
||||
{
|
||||
std::vector<std::string> includePaths;
|
||||
includePaths.push_back(sourcePath);
|
||||
|
||||
// TODO: move this creation to another place (after projectsettings have been loaded)
|
||||
if (!m_fileManager)
|
||||
{
|
||||
std::vector<std::string> sourcePaths;
|
||||
sourcePaths.push_back(sourcePath);
|
||||
|
||||
std::vector<std::string> sourceExtensions;
|
||||
sourceExtensions.push_back(".cpp");
|
||||
sourceExtensions.push_back(".cc");
|
||||
|
||||
std::vector<std::string> includeExtensions;
|
||||
includeExtensions.push_back(".h");
|
||||
includeExtensions.push_back(".hpp");
|
||||
m_fileManager = std::make_shared<FileManager>(sourcePaths, includePaths, sourceExtensions, includeExtensions); // todo: move this creation to another place (after projectsettings have been loaded)
|
||||
|
||||
m_fileManager = std::make_shared<FileManager>(sourcePaths, includePaths, sourceExtensions, includeExtensions);
|
||||
}
|
||||
|
||||
m_fileManager->fetchFilePaths();
|
||||
std::vector<std::string> addedFilePaths = m_fileManager->getAddedFilePaths();
|
||||
std::vector<std::string> updatedFilePaths = m_fileManager->getUpdatedFilePaths();
|
||||
std::vector<std::string> removedFilePaths = m_fileManager->getRemovedFilePaths();
|
||||
std::set<std::string> addedFilePaths = m_fileManager->getAddedFilePaths();
|
||||
std::set<std::string> updatedFilePaths = m_fileManager->getUpdatedFilePaths();
|
||||
std::set<std::string> removedFilePaths = m_fileManager->getRemovedFilePaths();
|
||||
|
||||
std::set<std::string> dependingFilePaths;
|
||||
dependingFilePaths = m_storage->getDependingFilePathsAndRemoveFileNodes(updatedFilePaths);
|
||||
updatedFilePaths.insert(dependingFilePaths.begin(), dependingFilePaths.end());
|
||||
|
||||
dependingFilePaths = m_storage->getDependingFilePathsAndRemoveFileNodes(removedFilePaths);
|
||||
updatedFilePaths.insert(dependingFilePaths.begin(), dependingFilePaths.end());
|
||||
|
||||
m_storage->clearFileData(addedFilePaths);
|
||||
m_storage->clearFileData(updatedFilePaths);
|
||||
m_storage->clearFileData(removedFilePaths);
|
||||
|
||||
std::vector<std::string> filesToParse = addedFilePaths;
|
||||
for (std::string updatedFilePath: updatedFilePaths)
|
||||
{
|
||||
filesToParse.push_back(updatedFilePath);
|
||||
}
|
||||
std::vector<std::string> filesToParse;
|
||||
filesToParse.insert(filesToParse.end(), addedFilePaths.begin(), addedFilePaths.end());
|
||||
filesToParse.insert(filesToParse.end(), updatedFilePaths.begin(), updatedFilePaths.end());
|
||||
|
||||
if (filesToParse.size() == 0)
|
||||
{
|
||||
|
||||
@@ -96,8 +96,7 @@ CodeView* CodeController::getView()
|
||||
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTokenIds(
|
||||
const std::vector<Id>& ids, Id declarationId
|
||||
) const {
|
||||
std::vector<Id> locationIds = m_graphAccess->getLocationIdsForTokenIds(ids);
|
||||
TokenLocationCollection collection = m_locationAccess->getTokenLocationsForLocationIds(locationIds);
|
||||
TokenLocationCollection collection = m_locationAccess->getTokenLocationsForTokenIds(ids);
|
||||
|
||||
std::vector<CodeView::CodeSnippetParams> snippets;
|
||||
|
||||
|
||||
@@ -467,6 +467,7 @@ GraphController::Margins GraphController::getMarginsForDummyNode(DummyNode& node
|
||||
case Node::NODE_ENUM:
|
||||
case Node::NODE_TYPEDEF:
|
||||
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
case Node::NODE_FILE:
|
||||
if (node.subNodes.size())
|
||||
{
|
||||
margins.left = margins.right = 15;
|
||||
|
||||
+118
-25
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/file/FileSystem.h"
|
||||
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
@@ -41,7 +42,7 @@ void Storage::clear()
|
||||
m_errorLocationCollection.clear();
|
||||
}
|
||||
|
||||
void Storage::clearFileData(const std::vector<std::string>& filePaths)
|
||||
void Storage::clearFileData(const std::set<std::string>& filePaths)
|
||||
{
|
||||
for (const std::string& filePath : filePaths)
|
||||
{
|
||||
@@ -98,6 +99,36 @@ void Storage::clearFileData(const std::vector<std::string>& filePaths)
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::string> Storage::getDependingFilePathsAndRemoveFileNodes(const std::set<std::string>& filePaths)
|
||||
{
|
||||
std::set<std::string> dependingFilePaths;
|
||||
|
||||
for (const std::string& filePath : filePaths)
|
||||
{
|
||||
SearchNode* searchNode = m_tokenIndex.getNode(filePath);
|
||||
if (!searchNode || searchNode->getTokenIds().size() != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Node* fileNode = m_graph.getNodeById(searchNode->getFirstTokenId());
|
||||
if (!fileNode->isType(Node::NODE_FILE))
|
||||
{
|
||||
LOG_ERROR("Node is not of type file.");
|
||||
continue;
|
||||
}
|
||||
|
||||
addDependingFilePathsAndRemoveFileNodesRecursive(fileNode, &dependingFilePaths);
|
||||
}
|
||||
|
||||
for (const std::string& path : filePaths)
|
||||
{
|
||||
dependingFilePaths.erase(path);
|
||||
}
|
||||
|
||||
return dependingFilePaths;
|
||||
}
|
||||
|
||||
void Storage::logGraph() const
|
||||
{
|
||||
LOG_INFO_STREAM(<< '\n' << m_graph);
|
||||
@@ -605,6 +636,27 @@ Id Storage::onTemplateFunctionSpecializationParsed(
|
||||
return specializedFunctionNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onFileParsed(const std::string& filePath)
|
||||
{
|
||||
log("file", filePath, ParseLocation());
|
||||
|
||||
Node* fileNode = addNodeHierarchy(Node::NODE_FILE, std::vector<std::string>(1, FileSystem::absoluteFilePath(filePath)));
|
||||
return fileNode->getId();
|
||||
}
|
||||
|
||||
Id Storage::onFileIncludeParsed(const ParseLocation& location, const std::string& filePath, const std::string& includedPath)
|
||||
{
|
||||
log("include", includedPath, location);
|
||||
|
||||
Node* fileNode = addNodeHierarchy(Node::NODE_FILE, std::vector<std::string>(1, FileSystem::absoluteFilePath(filePath)));
|
||||
Node* includedFileNode = addNodeHierarchy(Node::NODE_FILE, std::vector<std::string>(1, FileSystem::absoluteFilePath(includedPath)));
|
||||
|
||||
Edge* edge = m_graph.createEdge(Edge::EDGE_INCLUDE, fileNode, includedFileNode);
|
||||
addTokenLocation(edge, location);
|
||||
|
||||
return edge->getId();
|
||||
}
|
||||
|
||||
Id Storage::getIdForNodeWithName(const std::string& fullName) const
|
||||
{
|
||||
SearchNode* node = m_tokenIndex.getNode(fullName);
|
||||
@@ -823,24 +875,6 @@ std::vector<Id> Storage::getActiveTokenIdsForLocationId(Id locationId) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
std::vector<Id> ret;
|
||||
|
||||
for (Id tokenId : tokenIds)
|
||||
{
|
||||
Token* token = m_graph.getTokenById(tokenId);
|
||||
if (!token)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.insert(ret.end(), token->getLocationIds().begin(), token->getLocationIds().end());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getTokenIdsForQuery(std::string query) const
|
||||
{
|
||||
QueryTree tree(query);
|
||||
@@ -854,17 +888,43 @@ std::vector<Id> Storage::getTokenIdsForQuery(std::string query) const
|
||||
return outGraph.getTokenIds();
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
|
||||
TokenLocationCollection Storage::getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
for (Id locationId: locationIds)
|
||||
for (Id tokenId : tokenIds)
|
||||
{
|
||||
TokenLocation* location = m_locationCollection.findTokenLocationById(locationId);
|
||||
if (location->getOtherTokenLocation())
|
||||
Token* token = m_graph.getTokenById(tokenId);
|
||||
if (!token)
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(location);
|
||||
ret.addTokenLocationAsPlainCopy(location->getOtherTokenLocation());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token->isNode() && dynamic_cast<Node*>(token)->isType(Node::NODE_FILE))
|
||||
{
|
||||
TokenLocationFile* locationFile =
|
||||
m_locationCollection.findTokenLocationFileByPath(dynamic_cast<Node*>(token)->getFullName());
|
||||
if (locationFile)
|
||||
{
|
||||
locationFile->forEachTokenLocation(
|
||||
[&ret](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(tokenLocation);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Id locationId: token->getLocationIds())
|
||||
{
|
||||
TokenLocation* location = m_locationCollection.findTokenLocationById(locationId);
|
||||
if (location->getOtherTokenLocation())
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(location);
|
||||
ret.addTokenLocationAsPlainCopy(location->getOtherTokenLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1177,6 +1237,39 @@ bool Storage::getQuerySearchResults(const std::string& query, const std::string&
|
||||
return true;
|
||||
}
|
||||
|
||||
void Storage::addDependingFilePathsAndRemoveFileNodesRecursive(Node* fileNode, std::set<std::string>* filePaths)
|
||||
{
|
||||
bool inserted = filePaths->insert(fileNode->getFullName()).second;
|
||||
if (!inserted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
Edge* edge = fileNode->findEdgeOfType(Edge::EDGE_INCLUDE);
|
||||
if (!edge)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Node* dependantNode = nullptr;
|
||||
if (edge->getTo() == fileNode)
|
||||
{
|
||||
dependantNode = edge->getFrom();
|
||||
}
|
||||
|
||||
m_graph.removeEdge(edge);
|
||||
|
||||
if (dependantNode)
|
||||
{
|
||||
addDependingFilePathsAndRemoveFileNodesRecursive(dependantNode, filePaths);
|
||||
}
|
||||
}
|
||||
|
||||
removeNodeIfUnreferenced(fileNode);
|
||||
}
|
||||
|
||||
void Storage::removeNodeIfUnreferenced(Node* node)
|
||||
{
|
||||
Id tokenId = node->getId();
|
||||
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
virtual ~Storage();
|
||||
|
||||
void clear();
|
||||
void clearFileData(const std::vector<std::string>& filePaths);
|
||||
void clearFileData(const std::set<std::string>& filePaths);
|
||||
std::set<std::string> getDependingFilePathsAndRemoveFileNodes(const std::set<std::string>& filePaths);
|
||||
|
||||
void logGraph() const;
|
||||
void logLocations() const;
|
||||
@@ -100,6 +101,10 @@ public:
|
||||
virtual Id onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction);
|
||||
|
||||
virtual Id onFileParsed(const std::string& filePath);
|
||||
virtual Id onFileIncludeParsed(
|
||||
const ParseLocation& location, const std::string& filePath, const std::string& includedPath);
|
||||
|
||||
// GraphAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& fullName) const;
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
@@ -110,12 +115,11 @@ public:
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
@@ -143,6 +147,7 @@ private:
|
||||
|
||||
bool getQuerySearchResults(const std::string& query, const std::string& word, SearchResults* results) const;
|
||||
|
||||
void addDependingFilePathsAndRemoveFileNodesRecursive(Node* fileNode, std::set<std::string>* filePaths);
|
||||
void removeNodeIfUnreferenced(Node* node);
|
||||
|
||||
void log(std::string type, std::string str, const ParseLocation& location) const;
|
||||
|
||||
@@ -23,7 +23,6 @@ public:
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const = 0;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const = 0;
|
||||
};
|
||||
|
||||
@@ -89,16 +89,6 @@ std::vector<Id> GraphAccessProxy::getActiveTokenIdsForLocationId(Id locationId)
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
std::vector<Id> GraphAccessProxy::getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getLocationIdsForTokenIds(tokenIds);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
std::vector<Id> GraphAccessProxy::getTokenIdsForQuery(std::string query) const
|
||||
{
|
||||
if (hasSubject())
|
||||
|
||||
@@ -22,7 +22,6 @@ public:
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
virtual std::vector<Id> getActiveTokenIdsForLocationId(Id locationId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class LocationAccess
|
||||
{
|
||||
public:
|
||||
virtual ~LocationAccess();
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const = 0;
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const = 0;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
|
||||
@@ -29,11 +29,11 @@ void LocationAccessProxy::setSubject(LocationAccess* subject)
|
||||
m_subject = subject;
|
||||
}
|
||||
|
||||
TokenLocationCollection LocationAccessProxy::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
|
||||
TokenLocationCollection LocationAccessProxy::getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenLocationsForLocationIds(locationIds);
|
||||
return m_subject->getTokenLocationsForTokenIds(tokenIds);
|
||||
}
|
||||
|
||||
return TokenLocationCollection();
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
void setSubject(LocationAccess* subject);
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
|
||||
@@ -141,6 +141,8 @@ std::string Edge::getTypeString(EdgeType type) const
|
||||
return "template default argument";
|
||||
case EDGE_TEMPLATE_SPECIALIZATION_OF:
|
||||
return "template specialization";
|
||||
case EDGE_INCLUDE:
|
||||
return "include";
|
||||
case EDGE_AGGREGATION:
|
||||
return "aggregation";
|
||||
}
|
||||
@@ -270,6 +272,13 @@ bool Edge::checkType() const
|
||||
}
|
||||
return true;
|
||||
|
||||
case EDGE_INCLUDE:
|
||||
if (!m_from->isType(Node::NODE_FILE) || !m_to->isType(Node::NODE_FILE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
case EDGE_AGGREGATION:
|
||||
if (!m_from->isType(typeMask | variableMask | functionMask) || !m_to->isType(typeMask | variableMask | functionMask))
|
||||
{
|
||||
|
||||
@@ -32,7 +32,9 @@ public:
|
||||
EDGE_TEMPLATE_DEFAULT_ARGUMENT_OF = 0x1000,
|
||||
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x2000,
|
||||
|
||||
EDGE_AGGREGATION = 0x4000
|
||||
EDGE_INCLUDE = 0x4000,
|
||||
|
||||
EDGE_AGGREGATION = 0x8000
|
||||
};
|
||||
|
||||
Edge(EdgeType type, Node* from, Node* to);
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "utility/file/FileSystem.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
#include "data/graph/token_component/TokenComponentAbstraction.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentName.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
#include "data/graph/token_component/TokenComponentSignature.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
Node::Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent)
|
||||
: m_type(type)
|
||||
@@ -50,7 +52,14 @@ bool Node::isType(NodeTypeMask mask) const
|
||||
|
||||
std::string Node::getName() const
|
||||
{
|
||||
return m_nameComponent->getName();
|
||||
if (isType(NODE_FILE))
|
||||
{
|
||||
return FileSystem::fileName(m_nameComponent->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_nameComponent->getName();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Node::getFullName() const
|
||||
@@ -342,6 +351,8 @@ std::string Node::getTypeString(NodeType type) const
|
||||
return "typedef";
|
||||
case NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
return "template parameter type";
|
||||
case NODE_FILE:
|
||||
return "file";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -37,7 +37,9 @@ public:
|
||||
NODE_ENUM = 0x800,
|
||||
NODE_ENUM_CONSTANT = 0x1000,
|
||||
NODE_TYPEDEF = 0x2000,
|
||||
NODE_TEMPLATE_PARAMETER_TYPE = 0x4000
|
||||
NODE_TEMPLATE_PARAMETER_TYPE = 0x4000,
|
||||
|
||||
NODE_FILE = 0x8000
|
||||
};
|
||||
|
||||
Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent);
|
||||
|
||||
@@ -174,6 +174,10 @@ void GraphFilterConductor::filterCommandNode(const QueryCommand* node, const Fil
|
||||
GraphFilterCommandInheritance(false).apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_FILE:
|
||||
GraphFilterCommandNodeType(Node::NODE_FILE).apply(in, out);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR_STREAM(<< "QueryCommand not supported: " << node->getType());
|
||||
GraphFilter().apply(in, out);
|
||||
|
||||
@@ -116,6 +116,10 @@ public:
|
||||
const ParseFunction function) = 0;
|
||||
virtual Id onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction) = 0;
|
||||
|
||||
virtual Id onFileParsed(const std::string& filePath) = 0;
|
||||
virtual Id onFileIncludeParsed(
|
||||
const ParseLocation& location, const std::string& filePath, const std::string& includedPath) = 0;
|
||||
};
|
||||
|
||||
#endif // PARSER_CLIENT_H
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "data/parser/cxx/ASTAction.h"
|
||||
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
|
||||
#include "data/parser/cxx/PreprocessorCallbacks.h"
|
||||
|
||||
ASTAction::ASTAction(ParserClient* client, FileManager* fileManager)
|
||||
: m_client(client)
|
||||
, m_fileManager(fileManager)
|
||||
@@ -14,3 +18,14 @@ std::unique_ptr<clang::ASTConsumer> ASTAction::CreateASTConsumer(clang::Compiler
|
||||
{
|
||||
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileManager));
|
||||
}
|
||||
|
||||
bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath)
|
||||
{
|
||||
m_client->onFileParsed(filePath.str());
|
||||
|
||||
clang::Preprocessor& preprocessor = compiler.getPreprocessor();
|
||||
preprocessor.addPPCallbacks(
|
||||
llvm::make_unique<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileManager));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
|
||||
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile);
|
||||
|
||||
virtual bool BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath);
|
||||
|
||||
private:
|
||||
ParserClient* m_client;
|
||||
FileManager* m_fileManager;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "data/parser/cxx/PreprocessorCallbacks.h"
|
||||
|
||||
#include "utility/file/FileManager.h"
|
||||
#include "data/parser/ParserClient.h"
|
||||
#include "data/parser/ParseLocation.h"
|
||||
|
||||
PreprocessorCallbacks::PreprocessorCallbacks(
|
||||
clang::SourceManager& sourceManager, ParserClient* client, FileManager* fileManager
|
||||
)
|
||||
: m_sourceManager(sourceManager)
|
||||
, m_client(client)
|
||||
, m_fileManager(fileManager)
|
||||
{
|
||||
}
|
||||
|
||||
void PreprocessorCallbacks::InclusionDirective(
|
||||
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
|
||||
clang::CharSourceRange fileNameRange, const clang::FileEntry* fileEntry, llvm::StringRef searchPath,
|
||||
llvm::StringRef relativePath, const clang::Module* imported
|
||||
){
|
||||
const clang::FileEntry* baseFileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(hashLocation));
|
||||
if (fileEntry && baseFileEntry)
|
||||
{
|
||||
std::string baseFilePath = baseFileEntry->getName();
|
||||
std::string filePath = fileEntry->getName();
|
||||
|
||||
if (m_fileManager->hasFilePath(baseFilePath) && m_fileManager->hasFilePath(filePath))
|
||||
{
|
||||
m_client->onFileIncludeParsed(
|
||||
getParseLocation(fileNameRange.getAsRange()), baseFileEntry->getName(), fileEntry->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::SourceRange& sourceRange) const
|
||||
{
|
||||
if (sourceRange.isInvalid())
|
||||
{
|
||||
return ParseLocation();
|
||||
}
|
||||
|
||||
const clang::PresumedLoc& presumedBegin = m_sourceManager.getPresumedLoc(sourceRange.getBegin(), false);
|
||||
const clang::PresumedLoc& presumedEnd = m_sourceManager.getPresumedLoc(sourceRange.getEnd(), false);
|
||||
|
||||
return ParseLocation(
|
||||
presumedBegin.getFilename(),
|
||||
presumedBegin.getLine(),
|
||||
presumedBegin.getColumn(),
|
||||
presumedEnd.getLine(),
|
||||
presumedEnd.getColumn() - 1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef PREPROCESSOR_CALLBACKS_H
|
||||
#define PREPROCESSOR_CALLBACKS_H
|
||||
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
||||
class FileManager;
|
||||
class ParserClient;
|
||||
|
||||
struct ParseLocation;
|
||||
|
||||
class PreprocessorCallbacks
|
||||
: public clang::PPCallbacks
|
||||
{
|
||||
public:
|
||||
explicit PreprocessorCallbacks(clang::SourceManager& sourceManager, ParserClient* client, FileManager* fileManager);
|
||||
|
||||
virtual void InclusionDirective(
|
||||
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
|
||||
clang::CharSourceRange fileNameRange, const clang::FileEntry* fileEntry, llvm::StringRef searchPath,
|
||||
llvm::StringRef relativePath, const clang::Module* imported);
|
||||
|
||||
private:
|
||||
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
|
||||
|
||||
const clang::SourceManager& m_sourceManager;
|
||||
ParserClient* m_client;
|
||||
FileManager* m_fileManager;
|
||||
};
|
||||
|
||||
#endif // PREPROCESSOR_CALLBACKS_H
|
||||
@@ -48,6 +48,8 @@ std::map<std::string, QueryCommand::CommandType> QueryCommand::getCommandTypeMap
|
||||
commandMap.emplace("derived", COMMAND_SUB_CLASS);
|
||||
commandMap.emplace("subclass", COMMAND_SUB_CLASS);
|
||||
|
||||
commandMap.emplace("file", COMMAND_FILE);
|
||||
|
||||
return commandMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ public:
|
||||
COMMAND_USAGE,
|
||||
|
||||
COMMAND_SUPER_CLASS,
|
||||
COMMAND_SUB_CLASS
|
||||
COMMAND_SUB_CLASS,
|
||||
|
||||
COMMAND_FILE
|
||||
};
|
||||
|
||||
static std::map<std::string, CommandType> getCommandTypeMap();
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <set>
|
||||
|
||||
#include "utility/file/FileSystem.h"
|
||||
#include "ProjectSettings.h"
|
||||
|
||||
FileManager::FileManager(
|
||||
std::vector<std::string> sourcePaths,
|
||||
@@ -37,10 +36,9 @@ void FileManager::fetchFilePaths()
|
||||
m_updatedFiles.clear();
|
||||
m_removedFiles.clear();
|
||||
|
||||
std::set<std::string> removedFileNames;
|
||||
for (std::map<std::string, FileInfo>::iterator it = m_files.begin(); it != m_files.end(); it++)
|
||||
{
|
||||
removedFileNames.insert(it->first);
|
||||
m_removedFiles.insert(it->first);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::vector<std::string>, std::vector<std::string>>> pathsExtensionsPairs;
|
||||
@@ -49,51 +47,52 @@ void FileManager::fetchFilePaths()
|
||||
|
||||
for (size_t i = 0; i < pathsExtensionsPairs.size(); i++)
|
||||
{
|
||||
std::vector<FileInfo> fileInfos = FileSystem::getFileInfosFromDirectoryPaths(pathsExtensionsPairs[i].first, pathsExtensionsPairs[i].second);
|
||||
std::vector<FileInfo> fileInfos =
|
||||
FileSystem::getFileInfosFromDirectoryPaths(pathsExtensionsPairs[i].first, pathsExtensionsPairs[i].second);
|
||||
|
||||
for (FileInfo fileInfo: fileInfos)
|
||||
{
|
||||
const std::string& filePath = fileInfo.path;
|
||||
std::map<std::string, FileInfo>::iterator it = m_files.find(filePath);
|
||||
if (it != m_files.end())
|
||||
{
|
||||
removedFileNames.erase(filePath);
|
||||
m_removedFiles.erase(filePath);
|
||||
if (fileInfo.lastWriteTime > it->second.lastWriteTime)
|
||||
{
|
||||
it->second.lastWriteTime = fileInfo.lastWriteTime;
|
||||
m_updatedFiles.push_back(filePath);
|
||||
m_updatedFiles.insert(fileInfo.path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_files.insert(std::pair<std::string, FileInfo>(filePath, fileInfo));
|
||||
m_addedFiles.push_back(filePath);
|
||||
m_addedFiles.insert(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<std::string>::iterator it = removedFileNames.begin(); it != removedFileNames.end(); it++)
|
||||
for (const std::string filePath : m_removedFiles)
|
||||
{
|
||||
m_files.erase(it->data());
|
||||
m_removedFiles.push_back(it->data());
|
||||
m_files.erase(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> FileManager::getAddedFilePaths() const
|
||||
std::set<std::string> FileManager::getAddedFilePaths() const
|
||||
{
|
||||
return m_addedFiles;
|
||||
}
|
||||
|
||||
std::vector<std::string> FileManager::getUpdatedFilePaths() const
|
||||
std::set<std::string> FileManager::getUpdatedFilePaths() const
|
||||
{
|
||||
return m_updatedFiles;
|
||||
}
|
||||
|
||||
std::vector<std::string> FileManager::getRemovedFilePaths() const
|
||||
std::set<std::string> FileManager::getRemovedFilePaths() const
|
||||
{
|
||||
return m_removedFiles;
|
||||
}
|
||||
|
||||
bool FileManager::hasFilePath(const std::string& filePath) const
|
||||
{
|
||||
return (m_files.find(filePath) != m_files.end());
|
||||
return (m_files.find(FileSystem::absoluteFilePath(filePath)) != m_files.end());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef FILE_MANAGER_H
|
||||
#define FILE_MANAGER_H
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "FileInfo.h"
|
||||
@@ -19,9 +19,10 @@ public:
|
||||
|
||||
void reset();
|
||||
void fetchFilePaths();
|
||||
std::vector<std::string> getAddedFilePaths() const;
|
||||
std::vector<std::string> getUpdatedFilePaths() const;
|
||||
std::vector<std::string> getRemovedFilePaths() const;
|
||||
|
||||
std::set<std::string> getAddedFilePaths() const;
|
||||
std::set<std::string> getUpdatedFilePaths() const;
|
||||
std::set<std::string> getRemovedFilePaths() const;
|
||||
|
||||
virtual bool hasFilePath(const std::string& filePath) const;
|
||||
|
||||
@@ -32,9 +33,9 @@ private:
|
||||
std::vector<std::string> m_includeExtensions;
|
||||
|
||||
std::map<std::string, FileInfo> m_files;
|
||||
std::vector<std::string> m_addedFiles;
|
||||
std::vector<std::string> m_updatedFiles;
|
||||
std::vector<std::string> m_removedFiles;
|
||||
std::set<std::string> m_addedFiles;
|
||||
std::set<std::string> m_updatedFiles;
|
||||
std::set<std::string> m_removedFiles;
|
||||
};
|
||||
|
||||
#endif // FILE_MANAGER_H
|
||||
|
||||
@@ -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