From 8ce17dec8d0cd893a325e93afaad49d05f755474 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Tue, 10 Apr 2018 15:36:37 +0200 Subject: [PATCH] logic: improved cxx indexer performance by completely skipping traversal of non-indexed files --- src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp | 121 +++++++++++++++++- src/lib_cxx/data/parser/cxx/CxxAstVisitor.h | 13 ++ .../cxx/CxxAstVisitorComponentIndexer.cpp | 82 +----------- .../cxx/CxxAstVisitorComponentIndexer.h | 13 -- 4 files changed, 134 insertions(+), 95 deletions(-) diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp index 18670acf..a397948a 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.cpp @@ -15,8 +15,9 @@ #include "data/parser/cxx/CxxAstVisitorComponentIndexer.h" #include "data/parser/cxx/utilityClang.h" #include "data/parser/ParserClient.h" - #include "data/parser/ParseLocation.h" +#include "utility/file/FileRegister.h" + #include "utility/utilityString.h" CxxAstVisitor::CxxAstVisitor( @@ -188,11 +189,41 @@ bool CxxAstVisitor::checkIgnoresTypeLoc(const clang::TypeLoc& tl) const #define DEF_TRAVERSE_TYPE(__TYPE__, CODE_BEFORE, CODE_AFTER) \ DEF_TRAVERSE_CUSTOM_TYPE(__TYPE__, __TYPE__, CODE_BEFORE, CODE_AFTER) -DEF_TRAVERSE_TYPE_PTR(Decl, { ret = m_interruptCounter.getCount() == 0; }, {}) +bool CxxAstVisitor::TraverseDecl(clang::Decl* decl) +{ + for (auto it = m_components.begin(); it != m_components.end(); it++) + { + (*it)->beginTraverseDecl(decl); + } + bool ret = m_interruptCounter.getCount() == 0; -DEF_TRAVERSE_TYPE_PTR(Stmt, {}, {}) + bool traverse = true; + if (decl) + { + clang::SourceLocation loc = m_astContext->getSourceManager().getExpansionLoc(decl->getLocation()); -DEF_TRAVERSE_CUSTOM_TYPE(Type, QualType, {}, {}) + if (loc.isInvalid()) + { + loc = decl->getLocation(); + } + + if (loc.isValid()) + { + traverse = isLocatedInProjectFile(loc); + } + } + + if (traverse) + { + Base::TraverseDecl(decl); + } + + for (auto it = m_components.rbegin(); it != m_components.rend(); it++) + { + (*it)->endTraverseDecl(decl); + } + return ret; +} // same as Base::TraverseQualifiedTypeLoc(..) but we need to make sure to call this.TraverseTypeLoc(..) bool CxxAstVisitor::TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc tl) @@ -202,6 +233,10 @@ bool CxxAstVisitor::TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc tl) DEF_TRAVERSE_TYPE(TypeLoc, {}, {}) +DEF_TRAVERSE_CUSTOM_TYPE(Type, QualType, {}, {}) + +DEF_TRAVERSE_TYPE_PTR(Stmt, {}, {}) + // same as Base::TraverseCXXRecordDecl(..) but we need to integrate the setter for the context info. // additionally: skip implicit CXXRecordDecls (this does not skip template specializations). bool CxxAstVisitor::TraverseCXXRecordDecl(clang::CXXRecordDecl *d) @@ -753,3 +788,81 @@ ParseLocation CxxAstVisitor::getParseLocation(const clang::SourceRange& sourceRa } return parseLocation; } + +bool CxxAstVisitor::isLocatedInUnparsedProjectFile(clang::SourceLocation loc) +{ + const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + + clang::FileID fileId; + if (loc.isValid()) + { + if (sourceManager.isWrittenInMainFile(loc)) + { + return true; + } + + fileId = sourceManager.getFileID(loc); + } + + if (fileId.isValid()) + { + auto it = m_inUnparsedProjectFileMap.find(fileId); + if (it != m_inUnparsedProjectFileMap.end()) + { + return it->second; + } + + bool ret = false; + const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); + if (fileEntry != nullptr && fileEntry->isValid()) + { + FilePath filePath = getCanonicalFilePathCache()->getCanonicalFilePath(fileEntry); + + if (m_fileRegister->hasFilePath(filePath)) + { + ret = !(m_fileRegister->fileIsIndexed(filePath)); + } + } + + m_inUnparsedProjectFileMap[fileId] = ret; + return ret; + } + + return false; +} + +bool CxxAstVisitor::isLocatedInProjectFile(clang::SourceLocation loc) +{ + const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + + clang::FileID fileId; + if (loc.isValid()) + { + if (sourceManager.isWrittenInMainFile(loc)) + { + return true; + } + + fileId = sourceManager.getFileID(loc); + } + + if (fileId.isValid()) + { + auto it = m_inProjectFileMap.find(fileId); + if (it != m_inProjectFileMap.end()) + { + return it->second; + } + + const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); + if (fileEntry != nullptr && fileEntry->isValid()) + { + FilePath filePath = getCanonicalFilePathCache()->getCanonicalFilePath(fileEntry); + const bool ret = m_fileRegister->hasFilePath(filePath); + m_inProjectFileMap[fileId] = ret; + return ret; + } + } + + return false; +} diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.h b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.h index 32b45311..61287b10 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitor.h +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitor.h @@ -145,6 +145,8 @@ public: ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const; ParseLocation getParseLocation(const clang::SourceLocation& loc) const; ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; + bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc); + bool isLocatedInProjectFile(clang::SourceLocation loc); private: typedef clang::RecursiveASTVisitor Base; @@ -166,6 +168,17 @@ private: std::shared_ptr m_declNameCache; std::shared_ptr m_typeNameCache; + + struct FileIdHash + { + size_t operator()(clang::FileID fileID) const + { + return fileID.getHashValue(); + } + }; + + std::unordered_map m_inUnparsedProjectFileMap; + std::unordered_map m_inProjectFileMap; }; template <> diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.cpp b/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.cpp index 2d699ddc..0908a0f9 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.cpp +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.cpp @@ -802,8 +802,8 @@ bool CxxAstVisitorComponentIndexer::shouldVisitDecl(const clang::Decl* decl) } bool declIsImplicit = utility::isImplicit(decl); - if ((declIsImplicit && isLocatedInProjectFile(loc)) || - (!declIsImplicit && isLocatedInUnparsedProjectFile(loc))) + if ((declIsImplicit && getAstVisitor()->isLocatedInProjectFile(loc)) || + (!declIsImplicit && getAstVisitor()->isLocatedInUnparsedProjectFile(loc))) { return true; } @@ -825,84 +825,10 @@ bool CxxAstVisitorComponentIndexer::shouldVisitReference(const clang::SourceLoca loc = referenceLocation; } - if ((declIsImplicit && isLocatedInProjectFile(loc)) || - (!declIsImplicit && isLocatedInUnparsedProjectFile(loc))) + if ((declIsImplicit && getAstVisitor()->isLocatedInProjectFile(loc)) || + (!declIsImplicit && getAstVisitor()->isLocatedInUnparsedProjectFile(loc))) { return true; } return false; } - -bool CxxAstVisitorComponentIndexer::isLocatedInUnparsedProjectFile(clang::SourceLocation loc) -{ - const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); - - clang::FileID fileId; - if (loc.isValid()) - { - if (sourceManager.isWrittenInMainFile(loc)) - { - return true; - } - - fileId = sourceManager.getFileID(loc); - } - - if (fileId.isValid()) - { - auto it = m_inUnparsedProjectFileMap.find(fileId); - if (it != m_inUnparsedProjectFileMap.end()) - { - return it->second; - } - - bool ret = false; - const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); - if (fileEntry != nullptr && fileEntry->isValid()) - { - FilePath filePath = getAstVisitor()->getCanonicalFilePathCache()->getCanonicalFilePath(fileEntry); - - if (m_fileRegister->hasFilePath(filePath)) - { - ret = !(m_fileRegister->fileIsIndexed(filePath)); - } - } - - m_inUnparsedProjectFileMap[fileId] = ret; - return ret; - } - - return false; -} - -bool CxxAstVisitorComponentIndexer::isLocatedInProjectFile(clang::SourceLocation loc) -{ - const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); - - clang::FileID fileId; - - if (loc.isValid()) - { - fileId = sourceManager.getFileID(loc); - } - - if (fileId.isValid()) - { - auto it = m_inProjectFileMap.find(fileId); - if (it != m_inProjectFileMap.end()) - { - return it->second; - } - - const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); - if (fileEntry != nullptr && fileEntry->isValid()) - { - FilePath filePath = getAstVisitor()->getCanonicalFilePathCache()->getCanonicalFilePath(fileEntry); - const bool ret = m_fileRegister->hasFilePath(filePath); - m_inProjectFileMap[fileId] = ret; - return ret; - } - } - - return false; -} diff --git a/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.h b/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.h index 01e52b22..897799cf 100644 --- a/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.h +++ b/src/lib_cxx/data/parser/cxx/CxxAstVisitorComponentIndexer.h @@ -47,14 +47,6 @@ public: virtual void visitConstructorInitializer(clang::CXXCtorInitializer* init) override; private: - struct FileIdHash - { - size_t operator()(clang::FileID fileID) const - { - return fileID.getHashValue(); - } - }; - void recordTemplateMemberSpecialization( const clang::MemberSpecializationInfo* memberSpecializationInfo, const NameHierarchy& context, @@ -71,15 +63,10 @@ private: bool shouldVisitDecl(const clang::Decl* decl); bool shouldVisitReference(const clang::SourceLocation& referenceLocation, const clang::Decl* contextDecl); - bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc); - bool isLocatedInProjectFile(clang::SourceLocation loc); clang::ASTContext* m_astContext; std::shared_ptr m_client; std::shared_ptr m_fileRegister; - - std::unordered_map m_inUnparsedProjectFileMap; - std::unordered_map m_inProjectFileMap; }; #endif // CXX_AST_VISITOR_COMPONENT_INDEXER_H