data: ClangTool gets invoked for cpp files only, headers are parsed on-the-fly

This change adds the class FileRegister, that splits cpp and h files for the Parser and keeps track which headers have
been parsed yet. TranslationUnits get only created for cpp files now, and headers are parsed on the fly. This reduces
parse time by around half.
This commit is contained in:
Eberhard Graether
2015-03-09 01:32:51 +01:00
parent abddf57004
commit 7014c8ac4c
22 changed files with 290 additions and 115 deletions
+1
View File
@@ -15,6 +15,7 @@ void init()
std::shared_ptr<ConsoleLogger> consoleLogger = std::make_shared<ConsoleLogger>();
consoleLogger->setLogLevel(Logger::LOG_WARNINGS | Logger::LOG_ERRORS);
LogManager::getInstance()->addLogger(consoleLogger);
std::shared_ptr<FileLogger> fileLogger = std::make_shared<FileLogger>();
fileLogger->setLogLevel(Logger::LOG_ALL);
LogManager::getInstance()->addLogger(fileLogger);
+2
View File
@@ -192,6 +192,8 @@ add_files(
utility/file/FileInfo.h
utility/file/FileManager.cpp
utility/file/FileManager.h
utility/file/FileRegister.cpp
utility/file/FileRegister.h
utility/file/FileSystem.cpp
utility/file/FileSystem.h
+9 -4
View File
@@ -4,9 +4,9 @@
#include "data/parser/cxx/PreprocessorCallbacks.h"
ASTAction::ASTAction(ParserClient* client, FileManager* fileManager)
ASTAction::ASTAction(ParserClient* client, FileRegister* fileRegister)
: m_client(client)
, m_fileManager(fileManager)
, m_fileRegister(fileRegister)
{
}
@@ -16,7 +16,7 @@ ASTAction::~ASTAction()
std::unique_ptr<clang::ASTConsumer> ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile)
{
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileManager));
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileRegister));
}
bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath)
@@ -25,7 +25,12 @@ bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::S
clang::Preprocessor& preprocessor = compiler.getPreprocessor();
preprocessor.addPPCallbacks(
llvm::make_unique<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileManager));
llvm::make_unique<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileRegister));
return true;
}
void ASTAction::EndSourceFileAction()
{
m_fileRegister->markParsingIncludeFilesParsed();
}
+5 -3
View File
@@ -5,21 +5,23 @@
#include "clang/Frontend/FrontendAction.h"
#include "data/parser/cxx/ASTConsumer.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
class ASTAction : public clang::ASTFrontendAction
{
public:
explicit ASTAction(ParserClient* client, FileManager* fileManager);
explicit ASTAction(ParserClient* client, FileRegister* fileRegister);
virtual ~ASTAction();
protected:
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile);
virtual bool BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath);
virtual void EndSourceFileAction();
private:
ParserClient* m_client;
FileManager* m_fileManager;
FileRegister* m_fileRegister;
};
#endif // AST_ACTION_H
+3 -3
View File
@@ -1,8 +1,8 @@
#include "data/parser/cxx/ASTActionFactory.h"
ASTActionFactory::ASTActionFactory(ParserClient* client, FileManager* fileManager)
ASTActionFactory::ASTActionFactory(ParserClient* client, FileRegister* fileRegister)
: m_client(client)
, m_fileManager(fileManager)
, m_fileRegister(fileRegister)
{
}
@@ -12,5 +12,5 @@ ASTActionFactory::~ASTActionFactory()
clang::FrontendAction* ASTActionFactory::create()
{
return new ASTAction(m_client, m_fileManager);
return new ASTAction(m_client, m_fileRegister);
}
+3 -3
View File
@@ -4,19 +4,19 @@
#include "clang/Tooling/Tooling.h"
#include "data/parser/cxx/ASTAction.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
class ASTActionFactory : public clang::tooling::FrontendActionFactory
{
public:
explicit ASTActionFactory(ParserClient* client, FileManager* fileManager);
explicit ASTActionFactory(ParserClient* client, FileRegister* fileRegister);
virtual ~ASTActionFactory();
virtual clang::FrontendAction* create();
private:
ParserClient* m_client;
FileManager* m_fileManager;
FileRegister* m_fileRegister;
};
#endif // AST_ACTION_FACTORY
+2 -2
View File
@@ -2,8 +2,8 @@
#include "data/parser/ParserClient.h"
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client, FileManager* fileManager)
: m_visitor(context, client, fileManager)
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister)
: m_visitor(context, client, fileRegister)
{
}
+6 -4
View File
@@ -4,13 +4,15 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "data/parser/cxx/ASTVisitor.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
class ASTConsumer : public clang::ASTConsumer
#include "data/parser/cxx/ASTVisitor.h"
class ASTConsumer
: public clang::ASTConsumer
{
public:
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client, FileManager* fileManager);
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
virtual ~ASTConsumer();
virtual void HandleTranslationUnit(clang::ASTContext& context);
+59 -48
View File
@@ -3,6 +3,11 @@
#include <clang/AST/ParentMap.h>
#include <clang/Lex/Lexer.h>
#include "utility/file/FileManager.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
#include "utility/utilityString.h"
#include "data/parser/cxx/ASTBodyVisitor.h"
#include "data/parser/cxx/utilityCxx.h"
#include "data/parser/ParseFunction.h"
@@ -10,14 +15,11 @@
#include "data/parser/ParseTypeUsage.h"
#include "data/parser/ParseVariable.h"
#include "data/type/DataType.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
#include "utility/utilityString.h"
ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client, FileManager* fileManager)
ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister)
: m_context(context)
, m_client(client)
, m_fileManager(fileManager)
, m_fileRegister(fileRegister)
{
}
@@ -32,7 +34,7 @@ bool ASTVisitor::VisitStmt(const clang::Stmt* statement)
bool ASTVisitor::VisitTypedefDecl(clang::TypedefDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onTypedefParsed(
getParseLocationForNamedDecl(declaration),
@@ -47,7 +49,7 @@ bool ASTVisitor::VisitTypedefDecl(clang::TypedefDecl* declaration)
bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
if (declaration->isClass())
{
@@ -96,7 +98,7 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
return true;
}
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
clang::AccessSpecifier access = declaration->getAccess();
@@ -128,7 +130,7 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
bool ASTVisitor::VisitFieldDecl(clang::FieldDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onFieldParsed(
getParseLocationForNamedDecl(declaration),
@@ -148,7 +150,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
return true;
}
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onFunctionParsed(
getParseLocationForNamedDecl(declaration),
@@ -168,7 +170,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
ParserClient::AbstractionType abstraction = ParserClient::ABSTRACTION_NONE;
if (declaration->isPure())
@@ -208,7 +210,7 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
for (clang::CXXConstructorDecl::init_const_iterator it = declaration->init_begin(); it != declaration->init_end(); it++)
{
@@ -242,7 +244,7 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onNamespaceParsed(
declaration->isAnonymousNamespace() ? ParseLocation() : getParseLocationForNamedDecl(declaration),
@@ -255,7 +257,7 @@ bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onEnumParsed(
getParseLocationForNamedDecl(declaration),
@@ -269,7 +271,7 @@ bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
bool ASTVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onEnumConstantParsed(
getParseLocation(declaration->getSourceRange()),
@@ -281,7 +283,7 @@ bool ASTVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* declaration)
bool ASTVisitor::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *declaration)
{
if (declaration->hasDefaultArgument())
if (isLocatedInUnparsedProjectFile(declaration) && declaration->hasDefaultArgument())
{
m_client->onTemplateDefaultArgumentTypeParsed(
getParseTypeUsage(declaration->getDefaultArgumentInfo()->getTypeLoc(), declaration->getDefaultArgument()),
@@ -294,27 +296,24 @@ bool ASTVisitor::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *declarat
bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
{
std::vector<std::string> rarchy = utility::getDeclNameHierarchy(declaration);
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
std::vector<std::string> templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
clang::NamedDecl* namedDecl = parameterList->getParam(i);
if (isLocatedInMainFile(namedDecl))
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
utility::getDeclNameHierarchy(namedDecl),
templateRecordNameHierarchy
);
}
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
utility::getDeclNameHierarchy(namedDecl),
templateRecordNameHierarchy
);
}
}
// for implicit template specializations we do not need a valid location of the original template class definition (since that file could be included)
// handles explicit specializations and implicit specializations but no explicit partial specializations
if (isLocatedInSourceFile(declaration))
if (isLocatedInProjectFile(declaration)) // TODO: evaluate if explicit specializations have to be parsed in every source file
{
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin();
it != declaration->specializations().end(); it++
@@ -354,7 +353,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(declaration);
@@ -368,26 +367,27 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
for (size_t i = 0; i < parameterList->size(); i++)
{
clang::NamedDecl* namedDecl = parameterList->getParam(i);
if (isLocatedInMainFile(namedDecl))
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
utility::getDeclNameHierarchy(namedDecl),
specializedRecordNameHierarchy
);
}
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
utility::getDeclNameHierarchy(namedDecl),
specializedRecordNameHierarchy
);
}
const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten();
for (size_t i = 0; i < argumentInfoList->NumTemplateArgs; i++)
{
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
const clang::TemplateArgument& argument = argumentLoc.getArgument();
if (argument.getKind() == clang::TemplateArgument::Type)
{
const clang::QualType argumentType = argument.getAsType();
m_client->onTemplateArgumentParsed(
getParseLocation(argumentLoc.getSourceRange()),
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
specializedRecordNameHierarchy);
m_client->onTemplateArgumentParsed(
getParseLocation(argumentLoc.getSourceRange()),
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
specializedRecordNameHierarchy);
}
}
}
return true;
@@ -396,14 +396,14 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration)
{
const ParseFunction templateFunction = getParseFunction(declaration);
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
clang::NamedDecl* namedDecl = parameterList->getParam(i);
if (isLocatedInMainFile(namedDecl))
if (isLocatedInUnparsedProjectFile(namedDecl))
{
std::vector<std::string> templateParameterTypeNameHierarchy = utility::getDeclNameHierarchy(namedDecl);
@@ -415,7 +415,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
}
}
}
if (isLocatedInSourceFile(declaration))
if (isLocatedInProjectFile(declaration))
{
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
{
@@ -426,7 +426,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
clang::FunctionTemplateSpecializationInfo* info = specializedFunctionDecl->getTemplateSpecializationInfo();
if (info->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization)
{
if (isLocatedInMainFile(declaration))
if (isLocatedInUnparsedProjectFile(declaration))
{
m_client->onTemplateFunctionSpecializationParsed(
specializedFunctionLocation,
@@ -672,20 +672,31 @@ void ASTVisitor::VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDec
);
}
bool ASTVisitor::isLocatedInMainFile(const clang::Decl* declaration) const
bool ASTVisitor::isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const
{
const clang::SourceLocation& location = declaration->getLocStart();
return location.isValid() && m_context->getSourceManager().isWrittenInMainFile(location);
if (!location.isValid())
{
return false;
}
if (m_context->getSourceManager().isWrittenInMainFile(location))
{
return true;
}
return m_fileRegister->includeFileIsParsing(m_context->getSourceManager().getFilename(location));
}
bool ASTVisitor::isLocatedInSourceFile(const clang::Decl* declaration) const
bool ASTVisitor::isLocatedInProjectFile(const clang::Decl* declaration) const
{
const clang::SourceLocation& location = declaration->getLocStart();
if (location.isValid())
{
const clang::SourceManager& sourceManager = m_context->getSourceManager();
std::string filePath = FileSystem::absoluteFilePath(sourceManager.getFilename(location));
return m_fileManager->hasFilePath(filePath);
return m_fileRegister->getFileManager()->hasFilePath(filePath);
}
return false;
}
+7 -5
View File
@@ -4,16 +4,17 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "utility/file/FileRegister.h"
#include "data/parser/cxx/ASTBodyVisitorClient.h"
#include "data/parser/ParserClient.h"
#include "utility/file/FileManager.h"
class ASTVisitor
: public clang::RecursiveASTVisitor<ASTVisitor>
, public ASTBodyVisitorClient
{
public:
ASTVisitor(clang::ASTContext* context, ParserClient* client, FileManager* fileManager);
ASTVisitor(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister);
virtual ~ASTVisitor();
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
@@ -57,8 +58,9 @@ public:
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages
private:
bool isLocatedInMainFile(const clang::Decl* declaration) const;
bool isLocatedInSourceFile(const clang::Decl* declaration) const;
bool isLocatedInUnparsedProjectFile(const clang::Decl* declaration) const;
bool isLocatedInProjectFile(const clang::Decl* declaration) const;
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
@@ -77,7 +79,7 @@ private:
clang::ASTContext* m_context;
ParserClient* m_client;
FileManager* m_fileManager;
FileRegister* m_fileRegister;
};
#endif // AST_VISITOR_H
+12 -9
View File
@@ -1,5 +1,6 @@
#include "data/parser/cxx/CxxParser.h"
#include "utility/file/FileRegister.h"
#include "utility/logging/logging.h"
#include "utility/text/TextAccess.h"
@@ -34,13 +35,11 @@ namespace
clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get());
llvm::SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,
Code.toNullTerminatedStringRef(CodeStorage));
Invocation.mapVirtualFile(FileNameRef, Code.toNullTerminatedStringRef(CodeStorage));
for (auto &FilenameWithContent : VirtualMappedFiles)
{
Invocation.mapVirtualFile(FilenameWithContent.first,
FilenameWithContent.second);
Invocation.mapVirtualFile(FilenameWithContent.first, FilenameWithContent.second);
}
Invocation.setDiagnosticConsumer(DiagConsumer);
@@ -49,7 +48,7 @@ namespace
}
}
CxxParser::CxxParser(ParserClient* client, FileManager* fileManager)
CxxParser::CxxParser(ParserClient* client, const FileManager* fileManager)
: Parser(client)
, m_fileManager(fileManager)
{
@@ -112,13 +111,15 @@ void CxxParser::parseFiles(
return;
}
clang::tooling::ClangTool tool(*compilationDatabase, filePaths);
FileRegister fileRegister(m_fileManager, filePaths);
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client);
tool.setDiagnosticConsumer(&reporter);
ASTActionFactory actionFactory(m_client, m_fileManager);
ASTActionFactory actionFactory(m_client, &fileRegister);
clang::tooling::ClangTool tool(*compilationDatabase, fileRegister.getSourceFilePaths());
tool.setDiagnosticConsumer(&reporter);
tool.run(&actionFactory);
}
@@ -130,6 +131,8 @@ void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false);
ASTActionFactory actionFactory(m_client, m_fileManager);
FileRegister fileRegister(m_fileManager, std::vector<std::string>());
ASTActionFactory actionFactory(m_client, &fileRegister);
runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args);
}
+2 -2
View File
@@ -7,7 +7,7 @@
class CxxParser: public Parser
{
public:
CxxParser(ParserClient* client, FileManager* fileManager);
CxxParser(ParserClient* client, const FileManager* fileManager);
~CxxParser();
virtual void parseFiles(
@@ -17,7 +17,7 @@ public:
virtual void parseFile(std::shared_ptr<TextAccess> textAccess);
private:
FileManager* m_fileManager;
const FileManager* m_fileManager;
};
#endif // CXX_PARSER_H
@@ -1,18 +1,35 @@
#include "data/parser/cxx/PreprocessorCallbacks.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileRegister.h"
#include "data/parser/ParserClient.h"
#include "data/parser/ParseLocation.h"
PreprocessorCallbacks::PreprocessorCallbacks(
clang::SourceManager& sourceManager, ParserClient* client, FileManager* fileManager
clang::SourceManager& sourceManager, ParserClient* client, FileRegister* fileRegister
)
: m_sourceManager(sourceManager)
, m_client(client)
, m_fileManager(fileManager)
, m_fileRegister(fileRegister)
{
}
void PreprocessorCallbacks::FileChanged(
clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID)
{
if (reason != EnterFile)
{
return;
}
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(location));
if (fileEntry && m_fileRegister->getFileManager()->hasFilePath(fileEntry->getName()))
{
m_fileRegister->markIncludeFileParsing(fileEntry->getName());
}
}
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,
@@ -24,10 +41,10 @@ void PreprocessorCallbacks::InclusionDirective(
std::string baseFilePath = baseFileEntry->getName();
std::string filePath = fileEntry->getName();
if (m_fileManager->hasFilePath(baseFilePath) && m_fileManager->hasFilePath(filePath))
if (m_fileRegister->getFileManager()->hasFilePath(baseFilePath) &&
m_fileRegister->getFileManager()->hasFilePath(filePath))
{
m_client->onFileIncludeParsed(
getParseLocation(fileNameRange.getAsRange()), baseFileEntry->getName(), fileEntry->getName());
m_client->onFileIncludeParsed(getParseLocation(fileNameRange.getAsRange()), baseFilePath, filePath);
}
}
}
@@ -4,7 +4,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/PPCallbacks.h"
class FileManager;
class FileRegister;
class ParserClient;
struct ParseLocation;
@@ -13,7 +13,9 @@ class PreprocessorCallbacks
: public clang::PPCallbacks
{
public:
explicit PreprocessorCallbacks(clang::SourceManager& sourceManager, ParserClient* client, FileManager* fileManager);
explicit PreprocessorCallbacks(clang::SourceManager& sourceManager, ParserClient* client, FileRegister* fileRegister);
virtual void FileChanged(clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID);
virtual void InclusionDirective(
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
@@ -25,7 +27,7 @@ private:
const clang::SourceManager& m_sourceManager;
ParserClient* m_client;
FileManager* m_fileManager;
FileRegister* m_fileRegister;
};
#endif // PREPROCESSOR_CALLBACKS_H
+10
View File
@@ -96,3 +96,13 @@ bool FileManager::hasFilePath(const std::string& filePath) const
{
return (m_files.find(FileSystem::absoluteFilePath(filePath)) != m_files.end());
}
bool FileManager::hasSourceExtension(const std::string& filePath) const
{
return FileSystem::hasExtension(filePath, m_sourceExtensions);
}
bool FileManager::hasIncludeExtension(const std::string& filePath) const
{
return FileSystem::hasExtension(filePath, m_includeExtensions);
}
+2
View File
@@ -25,6 +25,8 @@ public:
std::set<std::string> getRemovedFilePaths() const;
virtual bool hasFilePath(const std::string& filePath) const;
virtual bool hasSourceExtension(const std::string& filePath) const;
virtual bool hasIncludeExtension(const std::string& filePath) const;
private:
std::vector<std::string> m_sourcePaths;
+66
View File
@@ -0,0 +1,66 @@
#include "utility/file/FileRegister.h"
#include "utility/file/FileManager.h"
#include "utility/file/FileSystem.h"
FileRegister::FileRegister(const FileManager* fileManager, const std::vector<std::string>& filePaths)
: m_fileManager(fileManager)
{
for (const std::string& path : filePaths)
{
if (m_fileManager->hasSourceExtension(path))
{
m_sourceFilePaths.push_back(path);
}
else
{
m_includeFilePaths.emplace(path, STATE_UNPARSED);
}
}
}
const FileManager* FileRegister::getFileManager() const
{
return m_fileManager;
}
const std::vector<std::string>& FileRegister::getSourceFilePaths() const
{
return m_sourceFilePaths;
}
bool FileRegister::includeFileIsParsing(const std::string& filePath) const
{
std::map<std::string, ParseState>::const_iterator it = m_includeFilePaths.find(FileSystem::absoluteFilePath(filePath));
if (it == m_includeFilePaths.end())
{
return false;
}
return it->second == STATE_PARSING;
}
void FileRegister::markIncludeFileParsing(const std::string& filePath)
{
std::map<std::string, ParseState>::iterator it = m_includeFilePaths.find(FileSystem::absoluteFilePath(filePath));
if (it == m_includeFilePaths.end())
{
return;
}
if (it->second != STATE_PARSED)
{
it->second = STATE_PARSING;
}
}
void FileRegister::markParsingIncludeFilesParsed()
{
for (std::pair<std::string, ParseState>&& p : m_includeFilePaths)
{
if (p.second == STATE_PARSING)
{
p.second = STATE_PARSED;
}
}
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef FILE_REGISTER_H
#define FILE_REGISTER_H
#include <map>
#include <string>
#include <vector>
class FileManager;
class FileRegister
{
public:
FileRegister(const FileManager* fileManager, const std::vector<std::string>& filePaths);
const FileManager* getFileManager() const;
const std::vector<std::string>& getSourceFilePaths() const;
bool includeFileIsParsing(const std::string& filePath) const;
void markIncludeFileParsing(const std::string& filePath);
void markParsingIncludeFilesParsed();
private:
enum ParseState
{
STATE_UNPARSED,
STATE_PARSING,
STATE_PARSED
};
const FileManager* m_fileManager;
std::vector<std::string> m_sourceFilePaths;
std::map<std::string, ParseState> m_includeFilePaths;
};
#endif // FILE_REGISTER_H
+19 -19
View File
@@ -15,7 +15,7 @@ std::vector<std::string> FileSystem::getFileNamesFromDirectory(
boost::filesystem::recursive_directory_iterator endit;
while (it != endit)
{
if (boost::filesystem::is_regular_file(*it) && isValidExtension(it->path().string(), extensions))
if (boost::filesystem::is_regular_file(*it) && hasExtension(it->path().string(), extensions))
{
files.push_back(it->path().generic_string());
}
@@ -38,7 +38,7 @@ std::vector<std::string> FileSystem::getFileNamesFromDirectoryUpdatedAfter(
boost::filesystem::recursive_directory_iterator endit;
while (it != endit)
{
if (boost::filesystem::is_regular_file(*it) && isValidExtension(it->path().string(), extensions))
if (boost::filesystem::is_regular_file(*it) && hasExtension(it->path().string(), extensions))
{
std::time_t t = boost::filesystem::last_write_time(*it);
boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t);
@@ -65,7 +65,7 @@ std::vector<FileInfo> FileSystem::getFileInfosFromDirectoryPaths(
boost::filesystem::recursive_directory_iterator endit;
while (it != endit)
{
if (boost::filesystem::is_regular_file(*it) && isValidExtension(it->path().string(), fileExtensions))
if (boost::filesystem::is_regular_file(*it) && hasExtension(it->path().string(), fileExtensions))
{
std::time_t t = boost::filesystem::last_write_time(*it);
boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t);
@@ -93,6 +93,11 @@ std::string FileSystem::fileName(const std::string& path)
return boost::filesystem::path(path).filename().generic_string();
}
std::string FileSystem::absoluteFilePath(const std::string& path)
{
return boost::filesystem::absolute(boost::filesystem::path(path)).generic_string();
}
std::string FileSystem::extension(const std::string& path)
{
return boost::filesystem::path(path).extension().generic_string();
@@ -103,22 +108,7 @@ std::string FileSystem::filePathWithoutExtension(const std::string& path)
return boost::filesystem::path(path).replace_extension().generic_string();
}
std::string FileSystem::absoluteFilePath(const std::string& path)
{
return boost::filesystem::absolute(boost::filesystem::path(path)).generic_string();
}
bool FileSystem::equivalent(const std::string& pathA, const std::string& pathB)
{
if (exists(pathA) && exists(pathB))
{
return boost::filesystem::equivalent(boost::filesystem::path(pathA), boost::filesystem::path(pathB));
}
return boost::filesystem::path(pathA).compare(boost::filesystem::path(pathB)) == 0;
}
bool FileSystem::isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions)
bool FileSystem::hasExtension(const std::string& filepath, const std::vector<std::string>& extensions)
{
boost::filesystem::path path(filepath);
@@ -131,3 +121,13 @@ bool FileSystem::isValidExtension(const std::string& filepath, const std::vector
}
return false;
}
bool FileSystem::equivalent(const std::string& pathA, const std::string& pathB)
{
if (exists(pathA) && exists(pathB))
{
return boost::filesystem::equivalent(boost::filesystem::path(pathA), boost::filesystem::path(pathB));
}
return boost::filesystem::path(pathA).compare(boost::filesystem::path(pathB)) == 0;
}
+4 -5
View File
@@ -21,14 +21,13 @@ public:
static bool exists(const std::string& path);
static std::string fileName(const std::string& path);
static std::string extension(const std::string& path);
static std::string filePathWithoutExtension(const std::string& path);
static std::string absoluteFilePath(const std::string& path);
static bool equivalent(const std::string& pathA, const std::string& pathB);
static std::string extension(const std::string& path);
static std::string filePathWithoutExtension(const std::string& path);
static bool hasExtension(const std::string& filepath, const std::vector<std::string>& extensions);
private:
static bool isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions);
static bool equivalent(const std::string& pathA, const std::string& pathB);
};
#endif // FILE_SYSTEM_H
+10
View File
@@ -14,3 +14,13 @@ bool TestFileManager::hasFilePath(const std::string& filePath) const
{
return true;
}
bool TestFileManager::hasSourceExtension(const std::string& filePath) const
{
return true;
}
bool TestFileManager::hasIncludeExtension(const std::string& filePath) const
{
return true;
}
+3
View File
@@ -7,7 +7,10 @@ class TestFileManager: public FileManager
{
public:
TestFileManager();
virtual bool hasFilePath(const std::string& filePath) const;
virtual bool hasSourceExtension(const std::string& filePath) const;
virtual bool hasIncludeExtension(const std::string& filePath) const;
};
#endif // TEST_FILE_MANAGER_H