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:
@@ -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
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "data/parser/Parser.h"
|
||||
|
||||
Parser::Parser(std::shared_ptr<ParserClient> client)
|
||||
: m_client(client)
|
||||
{
|
||||
}
|
||||
|
||||
Parser::~Parser()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "data/parser/ParserClient.h"
|
||||
|
||||
ParserClient::ParserClient()
|
||||
{
|
||||
}
|
||||
|
||||
ParserClient::~ParserClient()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef CLANG_MAIN_H
|
||||
#define CLANG_MAIN_H
|
||||
|
||||
int clang_main(int argc, char **argv);
|
||||
|
||||
#endif // CLANG_MAIN_H
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user