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
+2
View File
@@ -123,6 +123,7 @@ set_property(
"${CMAKE_SOURCE_DIR}/src/app"
"${CMAKE_SOURCE_DIR}/build/src/app"
"${CMAKE_SOURCE_DIR}/src/external"
${Boost_INCLUDE_DIRS}
)
# Use the Widgets module from Qt 5.
@@ -213,6 +214,7 @@ if (CXXTEST_FOUND)
"${CMAKE_SOURCE_DIR}/src/lib"
"${CXXTEST_INCLUDE_DIR}"
"${CMAKE_SOURCE_DIR}/src/external"
${Boost_INCLUDE_DIRS}
)
endif (CXXTEST_FOUND)
-1
View File
@@ -1,6 +1,5 @@
#include "header.h"
int main()
{
TemplateTestClass<int, int> t2;
@@ -0,0 +1 @@
update
+1 -1
View File
@@ -5,7 +5,7 @@
#include "qt/element/QtCodeFileList.h"
#include "qt/element/QtCodeSnippet.h"
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
QtCodeFile::QtCodeFile(const std::string& filePath, QtCodeFileList* parent)
: QWidget(parent)
+1 -1
View File
@@ -5,7 +5,7 @@
#include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeFile.h"
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
QtCodeFileList::QtCodeFileList(QWidget* parent)
: QScrollArea(parent)
+1 -1
View File
@@ -5,7 +5,7 @@
#include <QFile>
#include <QFontDatabase>
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
namespace utility
+1 -1
View File
@@ -4,7 +4,7 @@
#include "qt/element/QtCodeFileList.h"
#include "qt/view/QtViewWidgetWrapper.h"
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
#include "utility/text/TextAccess.h"
QtCodeView::QtCodeView(ViewLayout* viewLayout)
+3 -3
View File
@@ -46,7 +46,7 @@ void Application::loadProject(const std::string& projectSettingsFilePath)
m_project = Project::create(m_graphAccessProxy.get(), m_locationAccessProxy.get());
m_project->loadProjectSettings(projectSettingsFilePath);
m_project->parseCode(false);
m_project->parseCode();
}
void Application::loadSource(const std::string& sourceDirectoryPath)
@@ -55,12 +55,12 @@ void Application::loadSource(const std::string& sourceDirectoryPath)
m_project->clearProjectSettings();
m_project->setSourceDirectoryPath(sourceDirectoryPath);
m_project->parseCode(false);
m_project->parseCode();
}
void Application::reloadProject()
{
m_project->parseCode(true);
m_project->parseCode();
}
void Application::saveProject(const std::string& projectSettingsFilePath)
+7 -2
View File
@@ -184,6 +184,13 @@ add_files(
data/Storage.cpp
data/Storage.h
utility/file/FileInfo.cpp
utility/file/FileInfo.h
utility/file/FileManager.cpp
utility/file/FileManager.h
utility/file/FileSystem.cpp
utility/file/FileSystem.h
utility/logging/ConsoleLogger.cpp
utility/logging/ConsoleLogger.h
utility/logging/FileLogger.cpp
@@ -240,8 +247,6 @@ add_files(
utility/ConfigManager.cpp
utility/ConfigManager.h
utility/FileSystem.cpp
utility/FileSystem.h
utility/Property.h
utility/types.h
utility/utilityString.cpp
+58 -47
View File
@@ -11,9 +11,9 @@
#include "data/access/LocationAccessProxy.h"
#include "data/graph/Token.h"
#include "data/parser/cxx/CxxParser.h"
#include "utility/FileSystem.h"
#include "utility/messaging/type/MessageFinishedParsing.h"
#include "utility/logging/logging.h"
#include "utility/messaging/type/MessageFinishedParsing.h"
#include "utility/file/FileSystem.h"
std::shared_ptr<Project> Project::create(GraphAccessProxy* graphAccessProxy, LocationAccessProxy* locationAccessProxy)
{
@@ -77,60 +77,71 @@ void Project::clearStorage()
Token::resetNextId();
}
void Project::parseCode(bool refresh)
void Project::parseCode()
{
std::string sourcePath = ProjectSettings::getInstance()->getSourcePath();
if (sourcePath.size())
{
std::vector<std::string> extensions;
extensions.push_back(".cpp");
extensions.push_back(".cc");
extensions.push_back(".h");
extensions.push_back(".hpp");
// Add the SourcePath as HeaderSearchPath as well.
std::vector<std::string> headerSearchPaths = ProjectSettings::getInstance()->getHeaderSearchPaths();
headerSearchPaths.push_back(sourcePath);
std::vector<std::string> filePaths;
if (refresh)
std::vector<std::string> includePaths;
includePaths.push_back(sourcePath);
if (!m_fileManager)
{
filePaths = FileSystem::getFileNamesFromDirectoryUpdatedAfter(sourcePath, extensions, m_lastParseTimeString);
std::vector<std::string> sourcePaths;
sourcePaths.push_back(sourcePath);
std::vector<std::string> sourceExtensions;
sourceExtensions.push_back(".cpp");
sourceExtensions.push_back(".cc");
std::vector<std::string> includeExtensions;
includeExtensions.push_back(".h");
includeExtensions.push_back(".hpp");
m_fileManager = std::make_shared<FileManager>(sourcePaths, includePaths, sourceExtensions, includeExtensions); // todo: move this creation to another place (after projectsettings have been loaded)
}
m_fileManager->fetchFilePaths();
std::vector<std::string> addedFilePaths = m_fileManager->getAddedFilePaths();
std::vector<std::string> updatedFilePaths = m_fileManager->getUpdatedFilePaths();
std::vector<std::string> removedFilePaths = m_fileManager->getRemovedFilePaths();
m_storage->clearFileData(addedFilePaths);
m_storage->clearFileData(updatedFilePaths);
m_storage->clearFileData(removedFilePaths);
std::vector<std::string> filesToParse = addedFilePaths;
for (std::string updatedFilePath: updatedFilePaths)
{
filesToParse.push_back(updatedFilePath);
}
if (filesToParse.size() == 0)
{
MessageFinishedParsing(0, 0, m_storage->getErrorCount()).dispatch();
}
else
{
filePaths = FileSystem::getFileNamesFromDirectory(sourcePath, extensions);
// Add the SourcePaths as HeaderSearchPaths as well, so clang will also look here when searching include files.
std::vector<std::string> headerSearchPaths = ProjectSettings::getInstance()->getHeaderSearchPaths();
for (int i = 0; i < includePaths.size(); i++)
{
headerSearchPaths.push_back(includePaths[i]);
}
CxxParser parser(m_storage.get(), m_fileManager.get());
clock_t time = clock();
parser.parseFiles(
filesToParse,
ApplicationSettings::getInstance()->getHeaderSearchPaths(),
headerSearchPaths
);
time = clock() - time;
// m_storage->logGraph();
// m_storage->logLocations();
double parseTime = (double)(time) / CLOCKS_PER_SEC;
LOG_INFO_STREAM(<< "parse time: " << parseTime);
MessageFinishedParsing(filesToParse.size(), parseTime, m_storage->getErrorCount()).dispatch();
}
if (!filePaths.size())
{
MessageFinishedParsing(0, 0, m_storage->getErrorCount()).dispatch();
return;
}
m_lastParseTimeString = FileSystem::getTimeStringNow();
if (refresh)
{
m_storage->clearFileData(filePaths);
}
CxxParser parser(m_storage.get());
clock_t time = clock();
parser.parseFiles(
filePaths,
ApplicationSettings::getInstance()->getHeaderSearchPaths(),
headerSearchPaths
);
time = clock() - time;
// m_storage->logGraph();
// m_storage->logLocations();
double parseTime = (double)(time) / CLOCKS_PER_SEC;
LOG_INFO_STREAM(<< "parse time: " << parseTime);
MessageFinishedParsing(filePaths.size(), parseTime, m_storage->getErrorCount()).dispatch();
}
}
+3 -3
View File
@@ -4,6 +4,7 @@
#include <memory>
#include "data/Storage.h"
#include "utility/file/FileManager.h"
#include "ProjectSettings.h"
class GraphAccessProxy;
@@ -23,7 +24,7 @@ public:
bool setSourceDirectoryPath(const std::string& sourceDirectoryPath);
void clearStorage();
void parseCode(bool refresh);
void parseCode();
private:
Project(GraphAccessProxy* graphAccessProxy, LocationAccessProxy* locationAccessProxy);
@@ -36,8 +37,7 @@ private:
LocationAccessProxy* const m_locationAccessProxy;
std::shared_ptr<Storage> m_storage;
std::string m_lastParseTimeString;
std::shared_ptr<FileManager> m_fileManager;
};
#endif // PROJECT_H
+1 -1
View File
@@ -1,6 +1,6 @@
#include "Settings.h"
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
#include "utility/text/TextAccess.h"
#include "utility/utilityString.h"
+1 -1
View File
@@ -1,7 +1,7 @@
#include "component/view/CodeView.h"
#include "component/controller/CodeController.h"
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
CodeView::CodeSnippetParams::CodeSnippetParams()
: startLineNumber(0)
@@ -2,7 +2,7 @@
#include <algorithm>
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
#include "data/location/TokenLocation.h"
+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
+7
View File
@@ -0,0 +1,7 @@
#include "FileInfo.h"
FileInfo::FileInfo(std::string path, boost::posix_time::ptime lastWriteTime)
: path(path)
, lastWriteTime(lastWriteTime)
{
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef FILE_INFO_H
#define FILE_INFO_H
#include <string>
#include "boost/date_time.hpp"
struct FileInfo
{
FileInfo(std::string path, boost::posix_time::ptime lastWriteTime);
std::string path;
boost::posix_time::ptime lastWriteTime;
};
#endif // FILE_INFO_H
+99
View File
@@ -0,0 +1,99 @@
#include "utility/file/FileManager.h"
#include <functional>
#include <set>
#include "utility/file/FileSystem.h"
#include "ProjectSettings.h"
FileManager::FileManager(
std::vector<std::string> sourcePaths,
std::vector<std::string> includePaths,
std::vector<std::string> sourceExtensions,
std::vector<std::string> includeExtensions
)
: m_sourcePaths(sourcePaths)
, m_includePaths(includePaths)
, m_sourceExtensions(sourceExtensions)
, m_includeExtensions(includeExtensions)
{
}
FileManager::~FileManager()
{
}
void FileManager::reset()
{
m_files.clear();
m_addedFiles.clear();
m_updatedFiles.clear();
m_removedFiles.clear();
}
void FileManager::fetchFilePaths()
{
m_addedFiles.clear();
m_updatedFiles.clear();
m_removedFiles.clear();
std::set<std::string> removedFileNames;
for (std::map<std::string, FileInfo>::iterator it = m_files.begin(); it != m_files.end(); it++)
{
removedFileNames.insert(it->first);
}
std::vector<std::pair<std::vector<std::string>, std::vector<std::string>>> pathsExtensionsPairs;
pathsExtensionsPairs.push_back(std::make_pair(m_includePaths, m_includeExtensions));
pathsExtensionsPairs.push_back(std::make_pair(m_sourcePaths, m_sourceExtensions));
for (int i = 0; i < pathsExtensionsPairs.size(); i++)
{
std::vector<FileInfo> fileInfos = FileSystem::getFileInfosFromDirectoryPaths(pathsExtensionsPairs[i].first, pathsExtensionsPairs[i].second);
for (FileInfo fileInfo: fileInfos)
{
const std::string& filePath = fileInfo.path;
std::map<std::string, FileInfo>::iterator it = m_files.find(filePath);
if (it != m_files.end())
{
removedFileNames.erase(filePath);
if (fileInfo.lastWriteTime > it->second.lastWriteTime)
{
it->second.lastWriteTime = fileInfo.lastWriteTime;
m_updatedFiles.push_back(filePath);
}
}
else
{
m_files.insert(std::pair<std::string, FileInfo>(filePath, fileInfo));
m_addedFiles.push_back(filePath);
}
}
}
for (std::set<std::string>::iterator it = removedFileNames.begin(); it != removedFileNames.end(); it++)
{
m_files.erase(it->data());
m_removedFiles.push_back(it->data());
}
}
std::vector<std::string> FileManager::getAddedFilePaths() const
{
return m_addedFiles;
}
std::vector<std::string> FileManager::getUpdatedFilePaths() const
{
return m_updatedFiles;
}
std::vector<std::string> FileManager::getRemovedFilePaths() const
{
return m_removedFiles;
}
bool FileManager::hasFilePath(const std::string& filePath) const
{
return (m_files.find(filePath) != m_files.end());
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef FILE_MANAGER_H
#define FILE_MANAGER_H
#include <memory>
#include <vector>
#include "FileInfo.h"
class FileManager
{
public:
FileManager(
std::vector<std::string> sourcePaths,
std::vector<std::string> includePaths,
std::vector<std::string> sourceExtensions,
std::vector<std::string> includeExtensions
);
~FileManager();
void reset();
void fetchFilePaths();
std::vector<std::string> getAddedFilePaths() const;
std::vector<std::string> getUpdatedFilePaths() const;
std::vector<std::string> getRemovedFilePaths() const;
virtual bool hasFilePath(const std::string& filePath) const;
private:
std::vector<std::string> m_sourcePaths;
std::vector<std::string> m_includePaths;
std::vector<std::string> m_sourceExtensions;
std::vector<std::string> m_includeExtensions;
std::map<std::string, FileInfo> m_files;
std::vector<std::string> m_addedFiles;
std::vector<std::string> m_updatedFiles;
std::vector<std::string> m_removedFiles;
};
#endif // FILE_MANAGER_H
@@ -1,4 +1,4 @@
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
#include "boost/date_time.hpp"
#include "boost/filesystem.hpp"
@@ -53,6 +53,31 @@ std::vector<std::string> FileSystem::getFileNamesFromDirectoryUpdatedAfter(
return files;
}
std::vector<FileInfo> FileSystem::getFileInfosFromDirectoryPaths(
const std::vector<std::string>& directoryPaths, const std::vector<std::string>& fileExtensions)
{
std::vector<FileInfo> files;
for (const std::string& directoryPath: directoryPaths)
{
if (boost::filesystem::is_directory(directoryPath))
{
boost::filesystem::recursive_directory_iterator it(directoryPath);
boost::filesystem::recursive_directory_iterator endit;
while (it != endit)
{
if (boost::filesystem::is_regular_file(*it) && isValidExtension(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);
files.push_back(FileInfo(absoluteFilePath(it->path().generic_string()), lastWriteTime));
}
++it;
}
}
}
return files;
}
std::string FileSystem::getTimeStringNow()
{
return boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time());
@@ -4,6 +4,8 @@
#include <string>
#include <vector>
#include "utility/file/FileInfo.h"
class FileSystem
{
public:
@@ -12,6 +14,9 @@ public:
static std::vector<std::string> getFileNamesFromDirectoryUpdatedAfter(
const std::string& path, const std::vector<std::string>& extensions, const std::string& timeString);
static std::vector<FileInfo> getFileInfosFromDirectoryPaths(
const std::vector<std::string>& directoryPaths, const std::vector<std::string>& fileExtensions);
static std::string getTimeStringNow();
static bool exists(const std::string& path);
+6 -3
View File
@@ -1,16 +1,19 @@
add_files(
TEST_FILES
helper/TestFileManager.cpp
helper/TestFileManager.h
helper/TestStorage.cpp
helper/TestStorage.h
TestSuiteFixture.cpp
TestSuiteFixture.h
TestStorage.cpp
TestStorage.h
ConfigManagerTestSuite.h
CxxParserTestSuite.h
DataTypeTestSuite.h
DictionaryTestSuite.h
FileManagerTestSuite.h
FileSystemTestSuite.h
GraphTestSuite.h
GraphFilterTestSuite.h
+6 -2
View File
@@ -9,6 +9,8 @@
#include "utility/text/TextAccess.h"
#include "utility/utilityString.h"
#include "helper/TestFileManager.h"
class CxxParserTestSuite: public CxxTest::TestSuite
{
public:
@@ -1531,8 +1533,9 @@ public:
void test_cxx_parser_parses_multiple_files()
{
TestFileManager fm;
TestParserClient client;
CxxParser parser(&client);
CxxParser parser(&client, &fm);
std::vector<std::string> filePaths;
filePaths.push_back("data/CxxParserTestSuite/header.h");
@@ -1839,8 +1842,9 @@ private:
std::shared_ptr<TestParserClient> parseCode(std::string code) const
{
TestFileManager fm;
std::shared_ptr<TestParserClient> client = std::make_shared<TestParserClient>();
CxxParser parser(client.get());
CxxParser parser(client.get(), &fm);
parser.parseFile(TextAccess::createFromString(code));
return client;
}
+110
View File
@@ -0,0 +1,110 @@
#include "cxxtest/TestSuite.h"
#include "utility/file/FileManager.h"
class FileManagerTestSuite : public CxxTest::TestSuite
{
public:
void test_file_manager_is_created_empty()
{
std::vector<std::string> sourcePaths;
sourcePaths.push_back("./data/FileManagerTestSuite/src/");
std::vector<std::string> includePaths;
includePaths.push_back("./data/FileManagerTestSuite/include/");
std::vector<std::string> sourceExtensions;
sourceExtensions.push_back(".cpp");
sourceExtensions.push_back(".c");
std::vector<std::string> includeExtensions;
includeExtensions.push_back(".hpp");
includeExtensions.push_back(".h");
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
TS_ASSERT_EQUALS(updatedFilePaths.size(), 0);
TS_ASSERT_EQUALS(removedFilePaths.size(), 0);
}
void test_file_manager_has_added_file_paths_after_first_fetch()
{
std::vector<std::string> sourcePaths;
sourcePaths.push_back("./data/FileManagerTestSuite/src/");
std::vector<std::string> includePaths;
includePaths.push_back("./data/FileManagerTestSuite/include/");
std::vector<std::string> sourceExtensions;
sourceExtensions.push_back(".cpp");
sourceExtensions.push_back(".c");
std::vector<std::string> includeExtensions;
includeExtensions.push_back(".hpp");
includeExtensions.push_back(".h");
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
fm.fetchFilePaths();
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
TS_ASSERT_EQUALS(addedFilePaths.size(), 4);
}
void test_file_manager_has_no_added_file_paths_after_second_fetch()
{
std::vector<std::string> sourcePaths;
sourcePaths.push_back("./data/FileManagerTestSuite/src/");
std::vector<std::string> includePaths;
includePaths.push_back("./data/FileManagerTestSuite/include/");
std::vector<std::string> sourceExtensions;
sourceExtensions.push_back(".cpp");
sourceExtensions.push_back(".c");
std::vector<std::string> includeExtensions;
includeExtensions.push_back(".hpp");
includeExtensions.push_back(".h");
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
fm.fetchFilePaths();
fm.fetchFilePaths();
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
}
void test_file_manager_has_updated_file_paths_after_second_fetch()
{
std::vector<std::string> sourcePaths;
sourcePaths.push_back("./data/FileManagerTestSuite/src/");
std::vector<std::string> includePaths;
includePaths.push_back("./data/FileManagerTestSuite/include/");
std::vector<std::string> sourceExtensions;
sourceExtensions.push_back(".cpp");
sourceExtensions.push_back(".c");
std::vector<std::string> includeExtensions;
includeExtensions.push_back(".hpp");
includeExtensions.push_back(".h");
FileManager fm = FileManager(sourcePaths, includePaths, sourceExtensions, includeExtensions);
fm.fetchFilePaths();
std::fstream fileStream;
fileStream.open("./data/FileManagerTestSuite/include/c.h");
fileStream << "update";
fileStream.close();
fm.fetchFilePaths();
std::vector<std::string> addedFilePaths = fm.getAddedFilePaths();
std::vector<std::string> updatedFilePaths = fm.getUpdatedFilePaths();
std::vector<std::string> removedFilePaths = fm.getRemovedFilePaths();
TS_ASSERT_EQUALS(addedFilePaths.size(), 0);
TS_ASSERT_EQUALS(updatedFilePaths.size(), 1);
TS_ASSERT_EQUALS(removedFilePaths.size(), 0);
}
};
+17 -1
View File
@@ -5,7 +5,7 @@
#include <string>
#include <vector>
#include "utility/FileSystem.h"
#include "utility/file/FileSystem.h"
class FileSystemTestSuite : public CxxTest::TestSuite
{
@@ -71,6 +71,22 @@ public:
TS_ASSERT_EQUALS(sourceFiles[0], "data/FileSystemTestSuite/update.c");
}
void test_find_file_infos()
{
std::vector<std::string> extensions;
extensions.push_back(".h");
extensions.push_back(".hpp");
extensions.push_back(".cpp");
std::vector<std::string> directoryPaths;
directoryPaths.push_back("./data/FileSystemTestSuite");
std::vector<FileInfo> files =
FileSystem::getFileInfosFromDirectoryPaths(directoryPaths, extensions);
TS_ASSERT_EQUALS(files.size(), 5);
}
void test_filesystem_finds_existing_files()
{
TS_ASSERT(FileSystem::exists("data/FileSystemTestSuite"));
+2 -1
View File
@@ -2,7 +2,8 @@
#include "data/graph/filter/GraphFilterConductor.h"
#include "data/query/QueryTree.h"
#include "TestStorage.h"
#include "helper/TestStorage.h"
class GraphFilterConductorTestSuite : public CxxTest::TestSuite
{
+2 -1
View File
@@ -2,7 +2,8 @@
#include "data/graph/filter/GraphFilter.h"
#include "data/graph/filter/GraphFilterImplementations.h"
#include "TestStorage.h"
#include "helper/TestStorage.h"
class GraphFilterTestSuite : public CxxTest::TestSuite
{
+16
View File
@@ -0,0 +1,16 @@
#include "TestFileManager.h"
TestFileManager::TestFileManager()
: FileManager(
std::vector<std::string>(),
std::vector<std::string>(),
std::vector<std::string>(),
std::vector<std::string>()
)
{
}
bool TestFileManager::hasFilePath(const std::string& filePath) const
{
return true;
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef TEST_FILE_MANAGER_H
#define TEST_FILE_MANAGER_H
#include "utility/file/FileManager.h"
class TestFileManager: public FileManager
{
public:
TestFileManager();
virtual bool hasFilePath(const std::string& filePath) const;
};
#endif // TEST_FILE_MANAGER_H
@@ -2,11 +2,13 @@
#include "utility/text/TextAccess.h"
#include "data/parser/cxx/CxxParser.h"
#include "TestFileManager.h"
void TestStorage::parseCxxCode(std::string code)
{
clear();
CxxParser parser(this);
TestFileManager fm;
CxxParser parser(this, &fm);
parser.parseFile(TextAccess::createFromString(code));
}