From 82c88ebd97a11d861c8e132e470d0ef01f292f40 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Tue, 6 May 2014 14:50:51 +0200 Subject: [PATCH] data: Added CxxParser, currently only detecting classes This change adds CxxParser a class for parsing cxx files. It holds basic functionality to detect classes using the clang libTooling classes. CxxParser is derived from a common Parser interface, which can later be used for other language parsers. The Parser forwards detected elements to a ParserClient interface, which is implemented by the Storage class. The detected classes only get logged so far. review id = 6 * bd3c63a - (HEAD, origin/class, class) applied second review (4 minutes ago) * 3db7d93 - added missing files (4 days ago) * 6d09f4e - applied review (4 days ago) * d9d3e64 - fixed CMake files (4 days ago) * f22a771 - only one Storage class (4 days ago) * 6ee9553 - added tests (4 days ago) * 0a525e8 - fixed includes (4 days ago) * ca3fbb8 - added StorageManager as ParserClient (4 days ago) * fa185a5 - renamed ParseLocation to ParseObject (4 days ago) * 8b89808 - pass location with ParseLocation object (4 days ago) * 548ae3c - renamed clang AST classes (4 days ago) * d3b2caf - cleaned includes (4 days ago) * f7fdf33 - removed using namespace stmts (4 days ago) * 5378ef6 - using ParserClient (4 days ago) * b9ce2f6 - working with test file (4 days ago) * 5585abc - added CxxParser and ParserClient (4 days ago) --- bin/data/test_code.cpp | 12 ++++ bin/data/test_header.h | 1 + src/app/main.cpp | 4 -- src/lib/Application.cpp | 2 + src/lib/CMakeLists.txt | 26 ++++++--- src/lib/Project.cpp | 22 +++++++- src/lib/Project.h | 16 +++--- src/lib/data/Element.h | 1 - src/lib/data/GraphStorage.cpp | 9 --- src/lib/data/GraphStorage.h | 17 ------ src/lib/data/Parser.cpp | 5 -- src/lib/data/Parser.h | 10 ---- src/lib/data/Storage.cpp | 21 +++++++ src/lib/data/Storage.h | 25 +++++++++ src/lib/data/TextLocationStorage.cpp | 9 --- src/lib/data/TextLocationStorage.h | 19 ------- src/lib/data/parser/ParseObject.h | 25 +++++++++ src/lib/data/parser/Parser.cpp | 10 ++++ src/lib/data/parser/Parser.h | 22 ++++++++ src/lib/data/parser/ParserClient.cpp | 9 +++ src/lib/data/parser/ParserClient.h | 17 ++++++ src/lib/data/parser/clang.cpp | 58 -------------------- src/lib/data/parser/clang.h | 6 -- src/lib/data/parser/cxx/ASTAction.cpp | 15 +++++ src/lib/data/parser/cxx/ASTAction.h | 21 +++++++ src/lib/data/parser/cxx/ASTActionFactory.cpp | 15 +++++ src/lib/data/parser/cxx/ASTActionFactory.h | 20 +++++++ src/lib/data/parser/cxx/ASTConsumer.cpp | 15 +++++ src/lib/data/parser/cxx/ASTConsumer.h | 21 +++++++ src/lib/data/parser/cxx/ASTVisitor.cpp | 30 ++++++++++ src/lib/data/parser/cxx/ASTVisitor.h | 24 ++++++++ src/lib/data/parser/cxx/CxxParser.cpp | 35 ++++++++++++ src/lib/data/parser/cxx/CxxParser.h | 15 +++++ src/test/CMakeLists.txt | 1 + src/test/CxxParserTestSuite.h | 34 ++++++++++++ 35 files changed, 436 insertions(+), 156 deletions(-) create mode 100644 bin/data/test_code.cpp create mode 100644 bin/data/test_header.h delete mode 100644 src/lib/data/GraphStorage.cpp delete mode 100644 src/lib/data/GraphStorage.h delete mode 100644 src/lib/data/Parser.cpp delete mode 100644 src/lib/data/Parser.h create mode 100644 src/lib/data/Storage.cpp create mode 100644 src/lib/data/Storage.h delete mode 100644 src/lib/data/TextLocationStorage.cpp delete mode 100644 src/lib/data/TextLocationStorage.h create mode 100644 src/lib/data/parser/ParseObject.h create mode 100644 src/lib/data/parser/Parser.cpp create mode 100644 src/lib/data/parser/Parser.h create mode 100644 src/lib/data/parser/ParserClient.cpp create mode 100644 src/lib/data/parser/ParserClient.h delete mode 100644 src/lib/data/parser/clang.cpp delete mode 100644 src/lib/data/parser/clang.h create mode 100644 src/lib/data/parser/cxx/ASTAction.cpp create mode 100644 src/lib/data/parser/cxx/ASTAction.h create mode 100644 src/lib/data/parser/cxx/ASTActionFactory.cpp create mode 100644 src/lib/data/parser/cxx/ASTActionFactory.h create mode 100644 src/lib/data/parser/cxx/ASTConsumer.cpp create mode 100644 src/lib/data/parser/cxx/ASTConsumer.h create mode 100644 src/lib/data/parser/cxx/ASTVisitor.cpp create mode 100644 src/lib/data/parser/cxx/ASTVisitor.h create mode 100644 src/lib/data/parser/cxx/CxxParser.cpp create mode 100644 src/lib/data/parser/cxx/CxxParser.h create mode 100644 src/test/CxxParserTestSuite.h diff --git a/bin/data/test_code.cpp b/bin/data/test_code.cpp new file mode 100644 index 00000000..c6e9659d --- /dev/null +++ b/bin/data/test_code.cpp @@ -0,0 +1,12 @@ +#include "test_header.h" + +namespace X +{ + class A; +} + +class B +{ +public: + class C; +}; diff --git a/bin/data/test_header.h b/bin/data/test_header.h new file mode 100644 index 00000000..0de35584 --- /dev/null +++ b/bin/data/test_header.h @@ -0,0 +1 @@ +class H; diff --git a/src/app/main.cpp b/src/app/main.cpp index 1a8d94d8..75100ef0 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -7,12 +7,8 @@ #include "includes.h" #include "qt/QtElementFactory.h" -#include "data/parser/clang.h" - int main(int argv, char **args) { - clang_main(argv, args); - QApplication qtApp(argv, args); std::shared_ptr elementFactory = std::make_shared(); diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 48121818..2da725d0 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -29,4 +29,6 @@ Application::~Application() void Application::loadProject() { m_project = Project::create(m_codeAccess, m_graphAccess); + + m_project->parseCode(); } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 14e382c1..4a363112 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,8 +1,16 @@ add_files( CLANG_FILES - data/parser/clang.cpp - data/parser/clang.h + data/parser/cxx/ASTAction.cpp + data/parser/cxx/ASTAction.h + data/parser/cxx/ASTActionFactory.cpp + data/parser/cxx/ASTActionFactory.h + data/parser/cxx/ASTConsumer.cpp + data/parser/cxx/ASTConsumer.h + data/parser/cxx/ASTVisitor.cpp + data/parser/cxx/ASTVisitor.h + data/parser/cxx/CxxParser.cpp + data/parser/cxx/CxxParser.h ) add_files( @@ -32,6 +40,12 @@ add_files( data/access/GraphAccess.cpp data/access/GraphAccess.h + data/parser/ParseObject.h + data/parser/Parser.cpp + data/parser/Parser.h + data/parser/ParserClient.cpp + data/parser/ParserClient.h + data/Edge.cpp data/Edge.h data/Element.cpp @@ -40,22 +54,18 @@ add_files( data/ElementIndex.h data/Graph.cpp data/Graph.h - data/GraphStorage.cpp - data/GraphStorage.h data/Node.cpp data/Node.h - data/Parser.cpp - data/Parser.h data/SearchIndex.cpp data/SearchIndex.h + data/Storage.cpp + data/Storage.h data/TextLocation.cpp data/TextLocation.h data/TextLocationFile.cpp data/TextLocationFile.h data/TextLocationLine.cpp data/TextLocationLine.h - data/TextLocationStorage.cpp - data/TextLocationStorage.h gui/GuiElement.cpp gui/GuiElement.h diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index 4735b5c5..3f2bf7dd 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -1,12 +1,21 @@ #include "Project.h" +#include +#include + +#include "data/parser/cxx/CxxParser.h" + std::shared_ptr Project::create( - const std::shared_ptr& codeAccess, - const std::shared_ptr& graphAccess) + std::shared_ptr codeAccess, + std::shared_ptr graphAccess +) { std::shared_ptr ptr(new Project()); ptr->m_codeAccess = codeAccess; ptr->m_graphAccess = graphAccess; + + ptr->m_storage = std::make_shared(); + return ptr; } @@ -22,3 +31,12 @@ const ProjectSettings& Project::getProjectSettings() const { return m_settings; } + +void Project::parseCode() +{ + std::vector filePaths; + filePaths.push_back("data/test_code.cpp"); + + CxxParser parser(m_storage); + parser.parseFiles(filePaths); +} diff --git a/src/lib/Project.h b/src/lib/Project.h index c6d429c3..9fc56e22 100644 --- a/src/lib/Project.h +++ b/src/lib/Project.h @@ -5,34 +5,34 @@ #include "data/access/CodeAccess.h" #include "data/access/GraphAccess.h" -#include "data/GraphStorage.h" -#include "data/Parser.h" +#include "data/Storage.h" #include "ProjectSettings.h" class Project { public: static std::shared_ptr create( - const std::shared_ptr& codeAccess, - const std::shared_ptr& graphAccess); + std::shared_ptr codeAccess, + std::shared_ptr graphAccess + ); ~Project(); const ProjectSettings& getProjectSettings() const; + void parseCode(); + private: Project(); Project(const Project&); + Project operator=(const Project&); ProjectSettings m_settings; - std::shared_ptr m_parser; - - std::shared_ptr m_graphStorage; + std::shared_ptr m_storage; std::shared_ptr m_codeAccess; std::shared_ptr m_graphAccess; }; - #endif // PROJECT_H diff --git a/src/lib/data/Element.h b/src/lib/data/Element.h index 542dd950..a80b9b15 100644 --- a/src/lib/data/Element.h +++ b/src/lib/data/Element.h @@ -5,5 +5,4 @@ class Element { }; - #endif // ELEMENT_H diff --git a/src/lib/data/GraphStorage.cpp b/src/lib/data/GraphStorage.cpp deleted file mode 100644 index ce95dce4..00000000 --- a/src/lib/data/GraphStorage.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "data/GraphStorage.h" - -GraphStorage::GraphStorage() -{ -} - -GraphStorage::~GraphStorage() -{ -} diff --git a/src/lib/data/GraphStorage.h b/src/lib/data/GraphStorage.h deleted file mode 100644 index b84b1aa0..00000000 --- a/src/lib/data/GraphStorage.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef GRAPH_STORAGE_H -#define GRAPH_STORAGE_H - -#include "data/Graph.h" - -class GraphStorage -{ -public: - GraphStorage(); - ~GraphStorage(); - -private: - Graph m_graph; -}; - - -#endif // GRAPH_STORAGE_H diff --git a/src/lib/data/Parser.cpp b/src/lib/data/Parser.cpp deleted file mode 100644 index d6bc1a04..00000000 --- a/src/lib/data/Parser.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "data/Parser.h" - -Parser::~Parser() -{ -} diff --git a/src/lib/data/Parser.h b/src/lib/data/Parser.h deleted file mode 100644 index 9c5bd1b2..00000000 --- a/src/lib/data/Parser.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H - -class Parser -{ - virtual ~Parser(); -}; - - -#endif // PARSER_H diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp new file mode 100644 index 00000000..3c8f0ad6 --- /dev/null +++ b/src/lib/data/Storage.cpp @@ -0,0 +1,21 @@ +#include "data/Storage.h" + +#include + +#include "utility/logging/logging.h" + +Storage::Storage() +{ +} + +Storage::~Storage() +{ +} + +void Storage::addClass(const ParseObject& object) +{ + std::stringstream info; + info << "class " << object.name + << " <" << object.fileName << " " << object.lineNumber << ":" << object.columnNumber << ">"; + LOG_INFO(info.str()); +} diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h new file mode 100644 index 00000000..0f85ab27 --- /dev/null +++ b/src/lib/data/Storage.h @@ -0,0 +1,25 @@ +#ifndef STORAGE_H +#define STORAGE_H + +#include +#include + +#include "data/Graph.h" +#include "data/parser/ParserClient.h" +#include "data/TextLocationFile.h" + +class Storage: public ParserClient +{ +public: + Storage(); + ~Storage(); + + virtual void addClass(const ParseObject& object); + +private: + Graph m_graph; + + std::vector > m_textLocationFiles; +}; + +#endif // STORAGE_H diff --git a/src/lib/data/TextLocationStorage.cpp b/src/lib/data/TextLocationStorage.cpp deleted file mode 100644 index 792abdbb..00000000 --- a/src/lib/data/TextLocationStorage.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "data/TextLocationStorage.h" - -TextLocationStorage::TextLocationStorage() -{ -} - -TextLocationStorage::~TextLocationStorage() -{ -} diff --git a/src/lib/data/TextLocationStorage.h b/src/lib/data/TextLocationStorage.h deleted file mode 100644 index 135e0e50..00000000 --- a/src/lib/data/TextLocationStorage.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TEXT_LOCATION_STORAGE_H -#define TEXT_LOCATION_STORAGE_H - -#include - -#include "data/TextLocationFile.h" - -class TextLocationStorage -{ -public: - TextLocationStorage(); - ~TextLocationStorage(); - -private: - std::vector > m_textLocationFiles; -}; - - -#endif // TEXT_LOCATION_STORAGE_H diff --git a/src/lib/data/parser/ParseObject.h b/src/lib/data/parser/ParseObject.h new file mode 100644 index 00000000..c481e089 --- /dev/null +++ b/src/lib/data/parser/ParseObject.h @@ -0,0 +1,25 @@ +#ifndef PARSE_OBJECT_H +#define PARSE_OBJECT_H + +struct ParseObject +{ + ParseObject( + const std::string& name, + const std::string& fileName, + unsigned int lineNumber, + unsigned int columnNumber + ) + : name(name) + , fileName(fileName) + , lineNumber(lineNumber) + , columnNumber(columnNumber) + { + } + + const std::string name; + const std::string fileName; + const unsigned int lineNumber; + const unsigned int columnNumber; +}; + +#endif // PARSE_OBJECT_H diff --git a/src/lib/data/parser/Parser.cpp b/src/lib/data/parser/Parser.cpp new file mode 100644 index 00000000..64e9b83a --- /dev/null +++ b/src/lib/data/parser/Parser.cpp @@ -0,0 +1,10 @@ +#include "data/parser/Parser.h" + +Parser::Parser(std::shared_ptr client) + : m_client(client) +{ +} + +Parser::~Parser() +{ +} diff --git a/src/lib/data/parser/Parser.h b/src/lib/data/parser/Parser.h new file mode 100644 index 00000000..8f0ab342 --- /dev/null +++ b/src/lib/data/parser/Parser.h @@ -0,0 +1,22 @@ +#ifndef PARSER_H +#define PARSER_H + +#include +#include +#include + +#include "data/parser/ParserClient.h" + +class Parser +{ +public: + Parser(std::shared_ptr client); + virtual ~Parser(); + + virtual void parseFiles(const std::vector& filePaths) = 0; + +protected: + std::shared_ptr m_client; +}; + +#endif // PARSER_H diff --git a/src/lib/data/parser/ParserClient.cpp b/src/lib/data/parser/ParserClient.cpp new file mode 100644 index 00000000..9bebea4c --- /dev/null +++ b/src/lib/data/parser/ParserClient.cpp @@ -0,0 +1,9 @@ +#include "data/parser/ParserClient.h" + +ParserClient::ParserClient() +{ +} + +ParserClient::~ParserClient() +{ +} diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h new file mode 100644 index 00000000..9f089cfe --- /dev/null +++ b/src/lib/data/parser/ParserClient.h @@ -0,0 +1,17 @@ +#ifndef PARSER_CLIENT_H +#define PARSER_CLIENT_H + +#include + +#include "data/parser/ParseObject.h" + +class ParserClient +{ +public: + ParserClient(); + virtual ~ParserClient(); + + virtual void addClass(const ParseObject& object) = 0; +}; + +#endif // PARSER_CLIENT_H diff --git a/src/lib/data/parser/clang.cpp b/src/lib/data/parser/clang.cpp deleted file mode 100644 index 88968a41..00000000 --- a/src/lib/data/parser/clang.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "clang.h" - -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Tooling/Tooling.h" - -using namespace clang; - -class FindNamedClassVisitor - : public RecursiveASTVisitor { -public: - explicit FindNamedClassVisitor(ASTContext *Context) - : Context(Context) {} - - bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { - if (Declaration->getQualifiedNameAsString() == "n::m::C") { - FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getLocStart()); - if (FullLocation.isValid()) - llvm::outs() << "Found declaration at " - << FullLocation.getSpellingLineNumber() << ":" - << FullLocation.getSpellingColumnNumber() << "\n"; - } - return true; - } - -private: - ASTContext *Context; -}; - -class FindNamedClassConsumer : public clang::ASTConsumer { -public: - explicit FindNamedClassConsumer(ASTContext *Context) - : Visitor(Context) {} - - virtual void HandleTranslationUnit(clang::ASTContext &Context) { - Visitor.TraverseDecl(Context.getTranslationUnitDecl()); - } -private: - FindNamedClassVisitor Visitor; -}; - -class FindNamedClassAction : public clang::ASTFrontendAction { -public: - virtual clang::ASTConsumer *CreateASTConsumer( - clang::CompilerInstance &Compiler, llvm::StringRef InFile) { - return new FindNamedClassConsumer(&Compiler.getASTContext()); - } -}; - -int clang_main(int argc, char **argv) { - if (argc > 1) { - clang::tooling::runToolOnCode(new FindNamedClassAction, argv[1]); - } - return 0; -} diff --git a/src/lib/data/parser/clang.h b/src/lib/data/parser/clang.h deleted file mode 100644 index 166b21bc..00000000 --- a/src/lib/data/parser/clang.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CLANG_MAIN_H -#define CLANG_MAIN_H - -int clang_main(int argc, char **argv); - -#endif // CLANG_MAIN_H diff --git a/src/lib/data/parser/cxx/ASTAction.cpp b/src/lib/data/parser/cxx/ASTAction.cpp new file mode 100644 index 00000000..ce971bbf --- /dev/null +++ b/src/lib/data/parser/cxx/ASTAction.cpp @@ -0,0 +1,15 @@ +#include "data/parser/cxx/ASTAction.h" + +ASTAction::ASTAction(std::shared_ptr client) + : m_client(client) +{ +} + +ASTAction::~ASTAction() +{ +} + +clang::ASTConsumer* ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile) +{ + return new ASTConsumer(&compiler.getASTContext(), m_client); +} diff --git a/src/lib/data/parser/cxx/ASTAction.h b/src/lib/data/parser/cxx/ASTAction.h new file mode 100644 index 00000000..578f001a --- /dev/null +++ b/src/lib/data/parser/cxx/ASTAction.h @@ -0,0 +1,21 @@ +#ifndef AST_ACTION_H +#define AST_ACTION_H + +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" + +#include "data/parser/cxx/ASTConsumer.h" + +class ASTAction : public clang::ASTFrontendAction +{ +public: + explicit ASTAction(std::shared_ptr client); + virtual ~ASTAction(); + + virtual clang::ASTConsumer* CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile); + +private: + std::shared_ptr m_client; +}; + +#endif // AST_ACTION_H diff --git a/src/lib/data/parser/cxx/ASTActionFactory.cpp b/src/lib/data/parser/cxx/ASTActionFactory.cpp new file mode 100644 index 00000000..0afabf7e --- /dev/null +++ b/src/lib/data/parser/cxx/ASTActionFactory.cpp @@ -0,0 +1,15 @@ +#include "data/parser/cxx/ASTActionFactory.h" + +ASTActionFactory::ASTActionFactory(std::shared_ptr client) + : m_client(client) +{ +} + +ASTActionFactory::~ASTActionFactory() +{ +} + +clang::FrontendAction* ASTActionFactory::create() +{ + return new ASTAction(m_client); +} diff --git a/src/lib/data/parser/cxx/ASTActionFactory.h b/src/lib/data/parser/cxx/ASTActionFactory.h new file mode 100644 index 00000000..2b279020 --- /dev/null +++ b/src/lib/data/parser/cxx/ASTActionFactory.h @@ -0,0 +1,20 @@ +#ifndef AST_ACTION_FACTORY +#define AST_ACTION_FACTORY + +#include "clang/Tooling/Tooling.h" + +#include "data/parser/cxx/ASTAction.h" + +class ASTActionFactory : public clang::tooling::FrontendActionFactory +{ +public: + explicit ASTActionFactory(std::shared_ptr client); + virtual ~ASTActionFactory(); + + virtual clang::FrontendAction* create(); + +private: + std::shared_ptr m_client; +}; + +#endif // AST_ACTION_FACTORY diff --git a/src/lib/data/parser/cxx/ASTConsumer.cpp b/src/lib/data/parser/cxx/ASTConsumer.cpp new file mode 100644 index 00000000..79316379 --- /dev/null +++ b/src/lib/data/parser/cxx/ASTConsumer.cpp @@ -0,0 +1,15 @@ +#include "data/parser/cxx/ASTConsumer.h" + +ASTConsumer::ASTConsumer(clang::ASTContext* context, std::shared_ptr client) + : m_visitor(context, client) +{ +} + +ASTConsumer::~ASTConsumer() +{ +} + +void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context) +{ + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); +} diff --git a/src/lib/data/parser/cxx/ASTConsumer.h b/src/lib/data/parser/cxx/ASTConsumer.h new file mode 100644 index 00000000..7a0cf0d7 --- /dev/null +++ b/src/lib/data/parser/cxx/ASTConsumer.h @@ -0,0 +1,21 @@ +#ifndef AST_CONSUMER_H +#define AST_CONSUMER_H + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" + +#include "data/parser/cxx/AstVisitor.h" + +class ASTConsumer : public clang::ASTConsumer +{ +public: + explicit ASTConsumer(clang::ASTContext* context, std::shared_ptr client); + virtual ~ASTConsumer(); + + virtual void HandleTranslationUnit(clang::ASTContext& context); + +private: + ASTVisitor m_visitor; +}; + +#endif // AST_CONSUMER_H diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp new file mode 100644 index 00000000..c2019715 --- /dev/null +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -0,0 +1,30 @@ +#include "data/parser/cxx/ASTVisitor.h" + +ASTVisitor::ASTVisitor(clang::ASTContext* context, std::shared_ptr client) + : m_context(context) + , m_client(client) +{ +} + +ASTVisitor::~ASTVisitor() +{ +} + +bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl *declaration) +{ + clang::FullSourceLoc location = m_context->getFullLoc(declaration->getLocStart()); + + if (location.isValid() && m_context->getSourceManager().isWrittenInMainFile(location)) + { + ParseObject parseObject( + declaration->getQualifiedNameAsString(), + m_context->getSourceManager().getFilename(location), + location.getSpellingLineNumber(), + location.getSpellingColumnNumber() + ); + + m_client->addClass(parseObject); + } + + return true; +} diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h new file mode 100644 index 00000000..3e22ff26 --- /dev/null +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -0,0 +1,24 @@ +#ifndef AST_VISITOR_H +#define AST_VISITOR_H + +#include + +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" + +#include "data/parser/ParserClient.h" + +class ASTVisitor: public clang::RecursiveASTVisitor +{ +public: + ASTVisitor(clang::ASTContext* context, std::shared_ptr client); + virtual ~ASTVisitor(); + + virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration); + +private: + clang::ASTContext* m_context; + std::shared_ptr m_client; +}; + +#endif // AST_VISITOR_H diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp new file mode 100644 index 00000000..f53a2f43 --- /dev/null +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -0,0 +1,35 @@ +#include "data/parser/cxx/CxxParser.h" + +#include "data/parser/cxx/ASTActionFactory.h" +#include "utility/logging/logging.h" + +CxxParser::CxxParser(std::shared_ptr client) + : Parser(client) +{ +} + +CxxParser::~CxxParser() +{ +} + +void CxxParser::parseFiles(const std::vector& filePaths) +{ + const char* argv[] = { "app", "--" }; + int argc = 2; + + std::shared_ptr compilationDatabase( + clang::tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv) + ); + + if (!compilationDatabase) + { + LOG_ERROR("Failed to load compilation database"); + return; + } + + clang::tooling::ClangTool tool(*compilationDatabase, filePaths); + + ASTActionFactory actionFactory(m_client); + + tool.run(&actionFactory); +} diff --git a/src/lib/data/parser/cxx/CxxParser.h b/src/lib/data/parser/cxx/CxxParser.h new file mode 100644 index 00000000..7dd8e7c5 --- /dev/null +++ b/src/lib/data/parser/cxx/CxxParser.h @@ -0,0 +1,15 @@ +#ifndef CXX_PARSER_H +#define CXX_PARSER_H + +#include "data/parser/Parser.h" + +class CxxParser: public Parser +{ +public: + CxxParser(std::shared_ptr client); + ~CxxParser(); + + virtual void parseFiles(const std::vector& filePaths); +}; + +#endif // CXX_PARSER_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 64ec5503..771ab91e 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -2,6 +2,7 @@ add_files( TEST_FILES ConfigManagerTestSuite.h + CxxParserTestSuite.h LogManagerTestSuite.h Vector2TestSuite.h ) diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h new file mode 100644 index 00000000..ce1fc34d --- /dev/null +++ b/src/test/CxxParserTestSuite.h @@ -0,0 +1,34 @@ +#include "cxxtest/TestSuite.h" + +#include "data/parser/cxx/CxxParser.h" +#include "data/parser/ParserClient.h" + +class TestParserClient: public ParserClient +{ +public: + virtual void addClass(const ParseObject& object) + { + classes.push_back(object.name); + } + + std::vector classes; +}; + +class CxxParserTestSuite: public CxxTest::TestSuite +{ +public: + void test_cxx_parser_finds_classes() + { + std::shared_ptr client = std::make_shared(); + + std::vector filePaths; + filePaths.push_back("data/test_code.cpp"); + + CxxParser parser(client); + parser.parseFiles(filePaths); + + TS_ASSERT_EQUALS(client->classes[0], "X::A"); + TS_ASSERT_EQUALS(client->classes[1], "B"); + TS_ASSERT_EQUALS(client->classes[2], "B::C"); + } +};