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