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 <Eberhard Graether> (4 minutes ago)
* 3db7d93 - added missing files <Eberhard Graether> (4 days ago)
* 6d09f4e - applied review <Eberhard Graether> (4 days ago)
* d9d3e64 - fixed CMake files <Eberhard Graether> (4 days ago)
* f22a771 - only one Storage class <Eberhard Graether> (4 days ago)
* 6ee9553 - added tests <Eberhard Graether> (4 days ago)
* 0a525e8 - fixed includes <Eberhard Graether> (4 days ago)
* ca3fbb8 - added StorageManager as ParserClient <Eberhard Graether> (4 days ago)
* fa185a5 - renamed ParseLocation to ParseObject <Eberhard Graether> (4 days ago)
* 8b89808 - pass location with ParseLocation object <Eberhard Graether> (4 days ago)
* 548ae3c - renamed clang AST classes <Eberhard Graether> (4 days ago)
* d3b2caf - cleaned includes <Eberhard Graether> (4 days ago)
* f7fdf33 - removed using namespace stmts <Eberhard Graether> (4 days ago)
* 5378ef6 - using ParserClient <Eberhard Graether> (4 days ago)
* b9ce2f6 - working with test file <Eberhard Graether> (4 days ago)
* 5585abc - added CxxParser and ParserClient <Eberhard Graether> (4 days ago)
This commit is contained in:
Eberhard Graether
2014-05-06 14:50:51 +02:00
parent 6b82ea6860
commit 82c88ebd97
35 changed files with 436 additions and 156 deletions
+25
View File
@@ -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
+10
View File
@@ -0,0 +1,10 @@
#include "data/parser/Parser.h"
Parser::Parser(std::shared_ptr<ParserClient> client)
: m_client(client)
{
}
Parser::~Parser()
{
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef PARSER_H
#define PARSER_H
#include <memory>
#include <string>
#include <vector>
#include "data/parser/ParserClient.h"
class Parser
{
public:
Parser(std::shared_ptr<ParserClient> client);
virtual ~Parser();
virtual void parseFiles(const std::vector<std::string>& filePaths) = 0;
protected:
std::shared_ptr<ParserClient> m_client;
};
#endif // PARSER_H
+9
View File
@@ -0,0 +1,9 @@
#include "data/parser/ParserClient.h"
ParserClient::ParserClient()
{
}
ParserClient::~ParserClient()
{
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef PARSER_CLIENT_H
#define PARSER_CLIENT_H
#include <string>
#include "data/parser/ParseObject.h"
class ParserClient
{
public:
ParserClient();
virtual ~ParserClient();
virtual void addClass(const ParseObject& object) = 0;
};
#endif // PARSER_CLIENT_H
-58
View File
@@ -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<FindNamedClassVisitor> {
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;
}
-6
View File
@@ -1,6 +0,0 @@
#ifndef CLANG_MAIN_H
#define CLANG_MAIN_H
int clang_main(int argc, char **argv);
#endif // CLANG_MAIN_H
+15
View File
@@ -0,0 +1,15 @@
#include "data/parser/cxx/ASTAction.h"
ASTAction::ASTAction(std::shared_ptr<ParserClient> client)
: m_client(client)
{
}
ASTAction::~ASTAction()
{
}
clang::ASTConsumer* ASTAction::CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile)
{
return new ASTConsumer(&compiler.getASTContext(), m_client);
}
+21
View File
@@ -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<ParserClient> client);
virtual ~ASTAction();
virtual clang::ASTConsumer* CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile);
private:
std::shared_ptr<ParserClient> m_client;
};
#endif // AST_ACTION_H
@@ -0,0 +1,15 @@
#include "data/parser/cxx/ASTActionFactory.h"
ASTActionFactory::ASTActionFactory(std::shared_ptr<ParserClient> client)
: m_client(client)
{
}
ASTActionFactory::~ASTActionFactory()
{
}
clang::FrontendAction* ASTActionFactory::create()
{
return new ASTAction(m_client);
}
@@ -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<ParserClient> client);
virtual ~ASTActionFactory();
virtual clang::FrontendAction* create();
private:
std::shared_ptr<ParserClient> m_client;
};
#endif // AST_ACTION_FACTORY
+15
View File
@@ -0,0 +1,15 @@
#include "data/parser/cxx/ASTConsumer.h"
ASTConsumer::ASTConsumer(clang::ASTContext* context, std::shared_ptr<ParserClient> client)
: m_visitor(context, client)
{
}
ASTConsumer::~ASTConsumer()
{
}
void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context)
{
m_visitor.TraverseDecl(context.getTranslationUnitDecl());
}
+21
View File
@@ -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<ParserClient> client);
virtual ~ASTConsumer();
virtual void HandleTranslationUnit(clang::ASTContext& context);
private:
ASTVisitor m_visitor;
};
#endif // AST_CONSUMER_H
+30
View File
@@ -0,0 +1,30 @@
#include "data/parser/cxx/ASTVisitor.h"
ASTVisitor::ASTVisitor(clang::ASTContext* context, std::shared_ptr<ParserClient> 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;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef AST_VISITOR_H
#define AST_VISITOR_H
#include <memory>
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "data/parser/ParserClient.h"
class ASTVisitor: public clang::RecursiveASTVisitor<ASTVisitor>
{
public:
ASTVisitor(clang::ASTContext* context, std::shared_ptr<ParserClient> client);
virtual ~ASTVisitor();
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration);
private:
clang::ASTContext* m_context;
std::shared_ptr<ParserClient> m_client;
};
#endif // AST_VISITOR_H
+35
View File
@@ -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<ParserClient> client)
: Parser(client)
{
}
CxxParser::~CxxParser()
{
}
void CxxParser::parseFiles(const std::vector<std::string>& filePaths)
{
const char* argv[] = { "app", "--" };
int argc = 2;
std::shared_ptr<clang::tooling::FixedCompilationDatabase> 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);
}
+15
View File
@@ -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<ParserClient> client);
~CxxParser();
virtual void parseFiles(const std::vector<std::string>& filePaths);
};
#endif // CXX_PARSER_H