logic: improved cxx indexer performance by completely skipping traversal of non-indexed files

This commit is contained in:
mlangkabel
2018-04-10 15:36:37 +02:00
parent 2c8cc114eb
commit 8ce17dec8d
4 changed files with 134 additions and 95 deletions
+117 -4
View File
@@ -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;
}
@@ -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<CxxAstVisitor> Base;
@@ -166,6 +168,17 @@ private:
std::shared_ptr<DeclNameCache> m_declNameCache;
std::shared_ptr<TypeNameCache> m_typeNameCache;
struct FileIdHash
{
size_t operator()(clang::FileID fileID) const
{
return fileID.getHashValue();
}
};
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
};
template <>
@@ -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;
}
@@ -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<ParserClient> m_client;
std::shared_ptr<FileRegister> m_fileRegister;
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inUnparsedProjectFileMap;
std::unordered_map<const clang::FileID, bool, FileIdHash> m_inProjectFileMap;
};
#endif // CXX_AST_VISITOR_COMPONENT_INDEXER_H