logic: improved cxx indexer performance by completely skipping traversal of non-indexed files
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user