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.
This commit is contained in:
@@ -15,6 +15,7 @@ void init()
|
||||
std::shared_ptr<ConsoleLogger> consoleLogger = std::make_shared<ConsoleLogger>();
|
||||
consoleLogger->setLogLevel(Logger::LOG_WARNINGS | Logger::LOG_ERRORS);
|
||||
LogManager::getInstance()->addLogger(consoleLogger);
|
||||
|
||||
std::shared_ptr<FileLogger> fileLogger = std::make_shared<FileLogger>();
|
||||
fileLogger->setLogLevel(Logger::LOG_ALL);
|
||||
LogManager::getInstance()->addLogger(fileLogger);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<clang::ASTConsumer> ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile)
|
||||
{
|
||||
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileManager));
|
||||
return std::unique_ptr<clang::ASTConsumer>(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<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileManager));
|
||||
llvm::make_unique<PreprocessorCallbacks>(compiler.getSourceManager(), m_client, m_fileRegister));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ASTAction::EndSourceFileAction()
|
||||
{
|
||||
m_fileRegister->markParsingIncludeFilesParsed();
|
||||
}
|
||||
|
||||
@@ -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<clang::ASTConsumer> 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
#include <clang/AST/ParentMap.h>
|
||||
#include <clang/Lex/Lexer.h>
|
||||
|
||||
#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<std::string> rarchy = utility::getDeclNameHierarchy(declaration);
|
||||
if (isLocatedInMainFile(declaration))
|
||||
if (isLocatedInUnparsedProjectFile(declaration))
|
||||
{
|
||||
std::vector<std::string> 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<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
std::vector<std::string> 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<std::string> 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;
|
||||
}
|
||||
|
||||
@@ -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<ASTVisitor>
|
||||
, 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
|
||||
|
||||
@@ -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<clang::DiagnosticOptions> 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> textAccess)
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> options = new clang::DiagnosticOptions();
|
||||
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false);
|
||||
|
||||
ASTActionFactory actionFactory(m_client, m_fileManager);
|
||||
FileRegister fileRegister(m_fileManager, std::vector<std::string>());
|
||||
|
||||
ASTActionFactory actionFactory(m_client, &fileRegister);
|
||||
runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args);
|
||||
}
|
||||
|
||||
@@ -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> textAccess);
|
||||
|
||||
private:
|
||||
FileManager* m_fileManager;
|
||||
const FileManager* m_fileManager;
|
||||
};
|
||||
|
||||
#endif // CXX_PARSER_H
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
std::set<std::string> 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<std::string> m_sourcePaths;
|
||||
|
||||
@@ -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<std::string>& 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<std::string>& FileRegister::getSourceFilePaths() const
|
||||
{
|
||||
return m_sourceFilePaths;
|
||||
}
|
||||
|
||||
bool FileRegister::includeFileIsParsing(const std::string& filePath) const
|
||||
{
|
||||
std::map<std::string, ParseState>::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<std::string, ParseState>::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<std::string, ParseState>&& p : m_includeFilePaths)
|
||||
{
|
||||
if (p.second == STATE_PARSING)
|
||||
{
|
||||
p.second = STATE_PARSED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef FILE_REGISTER_H
|
||||
#define FILE_REGISTER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class FileManager;
|
||||
|
||||
class FileRegister
|
||||
{
|
||||
public:
|
||||
FileRegister(const FileManager* fileManager, const std::vector<std::string>& filePaths);
|
||||
|
||||
const FileManager* getFileManager() const;
|
||||
|
||||
const std::vector<std::string>& 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<std::string> m_sourceFilePaths;
|
||||
std::map<std::string, ParseState> m_includeFilePaths;
|
||||
};
|
||||
|
||||
#endif // FILE_REGISTER_H
|
||||
@@ -15,7 +15,7 @@ std::vector<std::string> 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<std::string> 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<FileInfo> 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<std::string>& extensions)
|
||||
bool FileSystem::hasExtension(const std::string& filepath, const std::vector<std::string>& 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;
|
||||
}
|
||||
|
||||
@@ -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<std::string>& extensions);
|
||||
|
||||
private:
|
||||
static bool isValidExtension(const std::string& filepath, const std::vector<std::string>& extensions);
|
||||
static bool equivalent(const std::string& pathA, const std::string& pathB);
|
||||
};
|
||||
|
||||
#endif // FILE_SYSTEM_H
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user