From 7014c8ac4cd4d00c2ce749e7c06ab3b05bcb008c Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Mon, 9 Mar 2015 01:32:51 +0100 Subject: [PATCH] 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. --- src/app/main.cpp | 1 + src/lib/CMakeLists.txt | 2 + src/lib/data/parser/cxx/ASTAction.cpp | 13 ++- src/lib/data/parser/cxx/ASTAction.h | 8 +- src/lib/data/parser/cxx/ASTActionFactory.cpp | 6 +- src/lib/data/parser/cxx/ASTActionFactory.h | 6 +- src/lib/data/parser/cxx/ASTConsumer.cpp | 4 +- src/lib/data/parser/cxx/ASTConsumer.h | 10 +- src/lib/data/parser/cxx/ASTVisitor.cpp | 107 ++++++++++-------- src/lib/data/parser/cxx/ASTVisitor.h | 12 +- src/lib/data/parser/cxx/CxxParser.cpp | 21 ++-- src/lib/data/parser/cxx/CxxParser.h | 4 +- .../data/parser/cxx/PreprocessorCallbacks.cpp | 27 ++++- .../data/parser/cxx/PreprocessorCallbacks.h | 8 +- src/lib/utility/file/FileManager.cpp | 10 ++ src/lib/utility/file/FileManager.h | 2 + src/lib/utility/file/FileRegister.cpp | 66 +++++++++++ src/lib/utility/file/FileRegister.h | 38 +++++++ src/lib/utility/file/FileSystem.cpp | 38 +++---- src/lib/utility/file/FileSystem.h | 9 +- src/test/helper/TestFileManager.cpp | 10 ++ src/test/helper/TestFileManager.h | 3 + 22 files changed, 290 insertions(+), 115 deletions(-) create mode 100644 src/lib/utility/file/FileRegister.cpp create mode 100644 src/lib/utility/file/FileRegister.h diff --git a/src/app/main.cpp b/src/app/main.cpp index a29c35c9..70edb8d7 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -15,6 +15,7 @@ void init() std::shared_ptr consoleLogger = std::make_shared(); consoleLogger->setLogLevel(Logger::LOG_WARNINGS | Logger::LOG_ERRORS); LogManager::getInstance()->addLogger(consoleLogger); + std::shared_ptr fileLogger = std::make_shared(); fileLogger->setLogLevel(Logger::LOG_ALL); LogManager::getInstance()->addLogger(fileLogger); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 784c86f7..cebfecfb 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -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 diff --git a/src/lib/data/parser/cxx/ASTAction.cpp b/src/lib/data/parser/cxx/ASTAction.cpp index 97b28bb0..f87f4dd9 100644 --- a/src/lib/data/parser/cxx/ASTAction.cpp +++ b/src/lib/data/parser/cxx/ASTAction.cpp @@ -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 ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile) { - return std::unique_ptr(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileManager)); + return std::unique_ptr(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(compiler.getSourceManager(), m_client, m_fileManager)); + llvm::make_unique(compiler.getSourceManager(), m_client, m_fileRegister)); return true; } + +void ASTAction::EndSourceFileAction() +{ + m_fileRegister->markParsingIncludeFilesParsed(); +} diff --git a/src/lib/data/parser/cxx/ASTAction.h b/src/lib/data/parser/cxx/ASTAction.h index 8fc4a333..704542ae 100644 --- a/src/lib/data/parser/cxx/ASTAction.h +++ b/src/lib/data/parser/cxx/ASTAction.h @@ -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 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 diff --git a/src/lib/data/parser/cxx/ASTActionFactory.cpp b/src/lib/data/parser/cxx/ASTActionFactory.cpp index 32c9b158..957641f2 100644 --- a/src/lib/data/parser/cxx/ASTActionFactory.cpp +++ b/src/lib/data/parser/cxx/ASTActionFactory.cpp @@ -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); } diff --git a/src/lib/data/parser/cxx/ASTActionFactory.h b/src/lib/data/parser/cxx/ASTActionFactory.h index 82614498..aa120071 100644 --- a/src/lib/data/parser/cxx/ASTActionFactory.h +++ b/src/lib/data/parser/cxx/ASTActionFactory.h @@ -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 diff --git a/src/lib/data/parser/cxx/ASTConsumer.cpp b/src/lib/data/parser/cxx/ASTConsumer.cpp index eafe7c26..cea87be9 100644 --- a/src/lib/data/parser/cxx/ASTConsumer.cpp +++ b/src/lib/data/parser/cxx/ASTConsumer.cpp @@ -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) { } diff --git a/src/lib/data/parser/cxx/ASTConsumer.h b/src/lib/data/parser/cxx/ASTConsumer.h index e930e18a..593420e8 100644 --- a/src/lib/data/parser/cxx/ASTConsumer.h +++ b/src/lib/data/parser/cxx/ASTConsumer.h @@ -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); diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index 537c97ca..d02591e1 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -3,6 +3,11 @@ #include #include +#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 rarchy = utility::getDeclNameHierarchy(declaration); - if (isLocatedInMainFile(declaration)) + if (isLocatedInUnparsedProjectFile(declaration)) { std::vector 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 specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration); std::vector 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 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; } diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index a25df801..6ba11c0c 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -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 , 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 diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index c64d5c91..684fcf46 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -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 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) llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false); - ASTActionFactory actionFactory(m_client, m_fileManager); + FileRegister fileRegister(m_fileManager, std::vector()); + + ASTActionFactory actionFactory(m_client, &fileRegister); runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args); } diff --git a/src/lib/data/parser/cxx/CxxParser.h b/src/lib/data/parser/cxx/CxxParser.h index 931a2284..edd06d15 100644 --- a/src/lib/data/parser/cxx/CxxParser.h +++ b/src/lib/data/parser/cxx/CxxParser.h @@ -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); private: - FileManager* m_fileManager; + const FileManager* m_fileManager; }; #endif // CXX_PARSER_H diff --git a/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp b/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp index 9a4bf7bc..481831bc 100644 --- a/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp +++ b/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp @@ -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); } } } diff --git a/src/lib/data/parser/cxx/PreprocessorCallbacks.h b/src/lib/data/parser/cxx/PreprocessorCallbacks.h index e266224d..4e0aed61 100644 --- a/src/lib/data/parser/cxx/PreprocessorCallbacks.h +++ b/src/lib/data/parser/cxx/PreprocessorCallbacks.h @@ -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 diff --git a/src/lib/utility/file/FileManager.cpp b/src/lib/utility/file/FileManager.cpp index 32161202..f58917df 100644 --- a/src/lib/utility/file/FileManager.cpp +++ b/src/lib/utility/file/FileManager.cpp @@ -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); +} diff --git a/src/lib/utility/file/FileManager.h b/src/lib/utility/file/FileManager.h index fd899f54..9cf9da3c 100644 --- a/src/lib/utility/file/FileManager.h +++ b/src/lib/utility/file/FileManager.h @@ -25,6 +25,8 @@ public: std::set 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 m_sourcePaths; diff --git a/src/lib/utility/file/FileRegister.cpp b/src/lib/utility/file/FileRegister.cpp new file mode 100644 index 00000000..0cc79cbf --- /dev/null +++ b/src/lib/utility/file/FileRegister.cpp @@ -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& 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& FileRegister::getSourceFilePaths() const +{ + return m_sourceFilePaths; +} + +bool FileRegister::includeFileIsParsing(const std::string& filePath) const +{ + std::map::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::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&& p : m_includeFilePaths) + { + if (p.second == STATE_PARSING) + { + p.second = STATE_PARSED; + } + } +} diff --git a/src/lib/utility/file/FileRegister.h b/src/lib/utility/file/FileRegister.h new file mode 100644 index 00000000..723f7471 --- /dev/null +++ b/src/lib/utility/file/FileRegister.h @@ -0,0 +1,38 @@ +#ifndef FILE_REGISTER_H +#define FILE_REGISTER_H + +#include +#include +#include + +class FileManager; + +class FileRegister +{ +public: + FileRegister(const FileManager* fileManager, const std::vector& filePaths); + + const FileManager* getFileManager() const; + + const std::vector& 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 m_sourceFilePaths; + std::map m_includeFilePaths; +}; + +#endif // FILE_REGISTER_H diff --git a/src/lib/utility/file/FileSystem.cpp b/src/lib/utility/file/FileSystem.cpp index fcc3f49a..2f9e01e7 100644 --- a/src/lib/utility/file/FileSystem.cpp +++ b/src/lib/utility/file/FileSystem.cpp @@ -15,7 +15,7 @@ std::vector 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 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 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& extensions) +bool FileSystem::hasExtension(const std::string& filepath, const std::vector& 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; +} diff --git a/src/lib/utility/file/FileSystem.h b/src/lib/utility/file/FileSystem.h index f3c4935e..ca8ea268 100644 --- a/src/lib/utility/file/FileSystem.h +++ b/src/lib/utility/file/FileSystem.h @@ -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& extensions); -private: - static bool isValidExtension(const std::string& filepath, const std::vector& extensions); + static bool equivalent(const std::string& pathA, const std::string& pathB); }; #endif // FILE_SYSTEM_H diff --git a/src/test/helper/TestFileManager.cpp b/src/test/helper/TestFileManager.cpp index 2673d44b..1ff7d9e4 100644 --- a/src/test/helper/TestFileManager.cpp +++ b/src/test/helper/TestFileManager.cpp @@ -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; +} diff --git a/src/test/helper/TestFileManager.h b/src/test/helper/TestFileManager.h index 194cc4f9..02f9fc18 100644 --- a/src/test/helper/TestFileManager.h +++ b/src/test/helper/TestFileManager.h @@ -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