logic: File Manager

* added FileManager that keeps track of the files analyzed by the project. It therefore checks if files get added, updated or deleted from the source- and include folders.
* refactored ASTVisitor::hasValidLocation() and implemented one version that search for the location in the currently parsed file and one that searches in all the project's source files.
* quickfix: switched order in FileManager so that header files are parsed first.
* created folder for helper classes used in tests.
* added test code for FileManager
* adjusted test code for Parser Tests.
This commit is contained in:
malte_langkabel
2015-02-09 14:52:31 +01:00
parent 4da51180ca
commit 8bc11c9d9c
43 changed files with 536 additions and 124 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
#include "data/parser/cxx/ASTAction.h"
ASTAction::ASTAction(ParserClient* client)
ASTAction::ASTAction(ParserClient* client, FileManager* fileManager)
: m_client(client)
, m_fileManager(fileManager)
{
}
@@ -11,5 +12,5 @@ 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));
return std::unique_ptr<clang::ASTConsumer>(new ASTConsumer(&compiler.getASTContext(), m_client, m_fileManager));
}
+3 -1
View File
@@ -5,17 +5,19 @@
#include "clang/Frontend/FrontendAction.h"
#include "data/parser/cxx/ASTConsumer.h"
#include "utility/file/FileManager.h"
class ASTAction : public clang::ASTFrontendAction
{
public:
explicit ASTAction(ParserClient* client);
explicit ASTAction(ParserClient* client, FileManager* fileManager);
virtual ~ASTAction();
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile);
private:
ParserClient* m_client;
FileManager* m_fileManager;
};
#endif // AST_ACTION_H
+3 -2
View File
@@ -1,7 +1,8 @@
#include "data/parser/cxx/ASTActionFactory.h"
ASTActionFactory::ASTActionFactory(ParserClient* client)
ASTActionFactory::ASTActionFactory(ParserClient* client, FileManager* fileManager)
: m_client(client)
, m_fileManager(fileManager)
{
}
@@ -11,5 +12,5 @@ ASTActionFactory::~ASTActionFactory()
clang::FrontendAction* ASTActionFactory::create()
{
return new ASTAction(m_client);
return new ASTAction(m_client, m_fileManager);
}
+3 -1
View File
@@ -4,17 +4,19 @@
#include "clang/Tooling/Tooling.h"
#include "data/parser/cxx/ASTAction.h"
#include "utility/file/FileManager.h"
class ASTActionFactory : public clang::tooling::FrontendActionFactory
{
public:
explicit ASTActionFactory(ParserClient* client);
explicit ASTActionFactory(ParserClient* client, FileManager* fileManager);
virtual ~ASTActionFactory();
virtual clang::FrontendAction* create();
private:
ParserClient* m_client;
FileManager* m_fileManager;
};
#endif // AST_ACTION_FACTORY
+2 -2
View File
@@ -2,8 +2,8 @@
#include "data/parser/ParserClient.h"
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client)
: m_visitor(context, client)
ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client, FileManager* fileManager)
: m_visitor(context, client, fileManager)
{
}
+2 -1
View File
@@ -5,11 +5,12 @@
#include "clang/AST/ASTContext.h"
#include "data/parser/cxx/ASTVisitor.h"
#include "utility/file/FileManager.h"
class ASTConsumer : public clang::ASTConsumer
{
public:
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client);
explicit ASTConsumer(clang::ASTContext* context, ParserClient* client, FileManager* fileManager);
virtual ~ASTConsumer();
virtual void HandleTranslationUnit(clang::ASTContext& context);
+58 -36
View File
@@ -10,12 +10,14 @@
#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)
ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client, FileManager* fileManager)
: m_context(context)
, m_client(client)
, m_fileManager(fileManager)
{
}
@@ -30,7 +32,7 @@ bool ASTVisitor::VisitStmt(const clang::Stmt* statement)
bool ASTVisitor::VisitTypedefDecl(clang::TypedefDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onTypedefParsed(
getParseLocationForNamedDecl(declaration),
@@ -45,7 +47,7 @@ bool ASTVisitor::VisitTypedefDecl(clang::TypedefDecl* declaration)
bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
if (declaration->isClass())
{
@@ -94,7 +96,7 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
return true;
}
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
clang::AccessSpecifier access = declaration->getAccess();
@@ -126,7 +128,7 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
bool ASTVisitor::VisitFieldDecl(clang::FieldDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onFieldParsed(
getParseLocationForNamedDecl(declaration),
@@ -146,7 +148,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
return true;
}
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onFunctionParsed(
getParseLocationForNamedDecl(declaration),
@@ -166,7 +168,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
ParserClient::AbstractionType abstraction = ParserClient::ABSTRACTION_NONE;
if (declaration->isPure())
@@ -198,7 +200,7 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
for (clang::CXXConstructorDecl::init_const_iterator it = declaration->init_begin(); it != declaration->init_end(); it++)
{
@@ -232,7 +234,7 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onNamespaceParsed(
declaration->isAnonymousNamespace() ? ParseLocation() : getParseLocationForNamedDecl(declaration),
@@ -245,7 +247,7 @@ bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onEnumParsed(
getParseLocationForNamedDecl(declaration),
@@ -259,7 +261,7 @@ bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
bool ASTVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
m_client->onEnumFieldParsed(
getParseLocation(declaration->getSourceRange()),
@@ -283,14 +285,15 @@ bool ASTVisitor::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl *declarat
bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
{
if (hasValidLocation(declaration))
std::vector<std::string> rarchy = utility::getDeclNameHierarchy(declaration);
if (isLocatedInMainFile(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 (hasValidLocation(namedDecl))
if (isLocatedInMainFile(namedDecl))
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
@@ -303,27 +306,34 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
// 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
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin();
it != declaration->specializations().end(); it++
)
if (isLocatedInSourceFile(declaration))
{
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
m_client->onTemplateRecordSpecializationParsed(
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
);
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
for (int i = 0; i < argList.size(); i++)
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin();
it != declaration->specializations().end(); it++
)
{
std::vector<std::string> argumentNameHierarchy = utility::templateArgumentToDataType(argList.get(i)).getTypeNameHierarchy();
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
m_client->onTemplateRecordSpecializationParsed(
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
);
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
for (int i = 0; i < argList.size(); i++)
{
m_client->onTemplateRecordArgumentTypeParsed(ParseLocation(), argumentNameHierarchy, specializedRecordNameHierarchy); // TODO: What about the ParseLocation
std::vector<std::string> argumentNameHierarchy = utility::templateArgumentToDataType(argList.get(i)).getTypeNameHierarchy();
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
{
m_client->onTemplateRecordArgumentTypeParsed(
ParseLocation(), // TODO: Find a valid ParseLocation here!
argumentNameHierarchy,
specializedRecordNameHierarchy
);
}
}
}
}
@@ -332,7 +342,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(declaration);
@@ -346,7 +356,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
for (size_t i = 0; i < parameterList->size(); i++)
{
clang::NamedDecl* namedDecl = parameterList->getParam(i);
if (hasValidLocation(namedDecl))
if (isLocatedInMainFile(namedDecl))
{
m_client->onTemplateRecordParameterTypeParsed(
getParseLocationForNamedDecl(namedDecl),
@@ -373,7 +383,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration)
{
if (hasValidLocation(declaration))
if (isLocatedInMainFile(declaration))
{
const ParseFunction templateFunction = getParseFunction(declaration->getTemplatedDecl());
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
@@ -393,7 +403,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
{
clang::NamedDecl* namedDecl = parameterList->getParam(i);
if (hasValidLocation(namedDecl))
if (isLocatedInMainFile(namedDecl))
{
std::string templateParameterTypeName = namedDecl->getNameAsString();
@@ -604,12 +614,24 @@ void ASTVisitor::VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDec
);
}
bool ASTVisitor::hasValidLocation(const clang::Decl* declaration) const
bool ASTVisitor::isLocatedInMainFile(const clang::Decl* declaration) const
{
const clang::SourceLocation& location = declaration->getLocStart();
return location.isValid() && m_context->getSourceManager().isWrittenInMainFile(location);
}
bool ASTVisitor::isLocatedInSourceFile(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 false;
}
ParserClient::AccessType ASTVisitor::convertAccessType(clang::AccessSpecifier access) const
{
switch (access)
+5 -2
View File
@@ -6,13 +6,14 @@
#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);
ASTVisitor(clang::ASTContext* context, ParserClient* client, FileManager* fileManager);
virtual ~ASTVisitor();
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
@@ -56,7 +57,8 @@ public:
virtual void VisitVarDeclInDeclBody(clang::FunctionDecl* decl, clang::VarDecl* varDecl); // type usages
private:
bool hasValidLocation(const clang::Decl* declaration) const;
bool isLocatedInMainFile(const clang::Decl* declaration) const;
bool isLocatedInSourceFile(const clang::Decl* declaration) const;
ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const;
ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const;
@@ -74,6 +76,7 @@ private:
clang::ASTContext* m_context;
ParserClient* m_client;
FileManager* m_fileManager;
};
#endif // AST_VISITOR_H
+4 -3
View File
@@ -49,8 +49,9 @@ static bool runToolOnCodeWithArgs(
}
CxxParser::CxxParser(ParserClient* client)
CxxParser::CxxParser(ParserClient* client, FileManager* fileManager)
: Parser(client)
, m_fileManager(fileManager)
{
}
@@ -117,7 +118,7 @@ void CxxParser::parseFiles(
CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client);
tool.setDiagnosticConsumer(&reporter);
ASTActionFactory actionFactory(m_client);
ASTActionFactory actionFactory(m_client, m_fileManager);
tool.run(&actionFactory);
}
@@ -129,6 +130,6 @@ 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);
ASTActionFactory actionFactory(m_client, m_fileManager);
runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args);
}
+5 -1
View File
@@ -2,11 +2,12 @@
#define CXX_PARSER_H
#include "data/parser/Parser.h"
#include "utility/file/FileManager.h"
class CxxParser: public Parser
{
public:
CxxParser(ParserClient* client);
CxxParser(ParserClient* client, FileManager* fileManager);
~CxxParser();
virtual void parseFiles(
@@ -14,6 +15,9 @@ public:
const std::vector<std::string>& systemHeaderSearchPaths,
const std::vector<std::string>& headerSearchPaths);
virtual void parseFile(std::shared_ptr<TextAccess> textAccess);
private:
FileManager* m_fileManager;
};
#endif // CXX_PARSER_H