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:
Eberhard Graether
2015-03-03 00:33:13 +01:00
parent 5370541a0f
commit 598041f896
32 changed files with 482 additions and 168 deletions
+4
View File
@@ -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
+15
View File
@@ -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;
}
+2
View File
@@ -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