Skip to content

Commit fea86ac

Browse files
author
seel.xu
committed
[Feature]: add astro parse base code
1 parent 7c4fb86 commit fea86ac

File tree

14 files changed

+541
-2
lines changed

14 files changed

+541
-2
lines changed

.bazelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ common --announce_rc
22

33
build --cxxopt="-std=c++17"
44
build --cxxopt="-gz" --cxxopt="-gdwarf-4"
5-
build --cxxopt="-Wall" --cxxopt="-Wextra" --cxxopt="-Werror"
5+
build --cxxopt="-Wall" --cxxopt="-Wextra" --cxxopt="-Werror" --cxxopt="-Wno-error=unused-command-line-argument" --cxxopt="-Wno-unused-command-line-argument"
66
build --cxxopt="-Wno-cast-function-type-mismatch"
77
build --cxxopt="-Wno-unused-function" --cxxopt="-Wno-unused-parameter" # protobuf require
88
build --cxxopt="-Wno-deprecated-declarations" # cuda require

.clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ IncludeCategories:
1717
Priority: 2
1818
- Regex: '^"([a-zA-Z_]*)(\.h")$'
1919
Priority: 3
20-
- Regex: '^"(gtest|gflags|glog|google|boost)/'
20+
- Regex: '^"(gtest|gflags|glog|google|boost|clang|nlohmann)/'
2121
Priority: 5
2222
- Regex: '^"(proto)/'
2323
Priority: 7

astroparse/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cc_binary(
2+
name = "astroparse",
3+
srcs = [
4+
"astroparse.cc",
5+
],
6+
deps = [
7+
"//parse",
8+
"@com_github_gflags_gflags//:gflags",
9+
],
10+
)

astroparse/astroparse.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <clang/Tooling/CommonOptionsParser.h>
2+
#include <clang/Tooling/Tooling.h>
3+
#include <llvm/Support/CommandLine.h>
4+
5+
#include "gflags/gflags.h"
6+
7+
#include "parse/ast_fronten_action.h"
8+
9+
static llvm::cl::OptionCategory ToolCategory("ast-parser options");
10+
11+
namespace {
12+
using clang::tooling::ASTFrontendActionImpl;
13+
using clang::tooling::ClangTool;
14+
using clang::tooling::CommonOptionsParser;
15+
using clang::tooling::newFrontendActionFactory;
16+
17+
DEFINE_string(file, "", "File to parse");
18+
DEFINE_string(output, "", "Output file");
19+
} // namespace
20+
21+
int32_t main(int32_t argc, const char** argv) {
22+
auto expected_parser = CommonOptionsParser::create(argc, argv, ToolCategory);
23+
if (!expected_parser) {
24+
llvm::errs() << "Error: " << llvm::toString(expected_parser.takeError()) << "\n";
25+
return 1;
26+
}
27+
CommonOptionsParser& optionsParser = expected_parser.get();
28+
ClangTool tool(optionsParser.getCompilations(), optionsParser.getSourcePathList());
29+
int32_t result = tool.run(newFrontendActionFactory<ASTFrontendActionImpl>().get());
30+
31+
return result;
32+
}

parse/BUILD.bazel

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
cc_library(
2+
name = "parse",
3+
deps = [
4+
":ast_visitor",
5+
":ast_consumer",
6+
":ast_fronten_action",
7+
],
8+
visibility = [
9+
"//visibility:public",
10+
],
11+
)
12+
13+
cc_library(
14+
name = "util",
15+
srcs = [
16+
"util.cc",
17+
],
18+
hdrs = [
19+
"util.h",
20+
"function_info.h",
21+
],
22+
deps = [
23+
"@nlohmann_json//:json",
24+
"@llvm//:clang_libs",
25+
"@com_google_googletest//:gtest_main",
26+
],
27+
)
28+
29+
cc_library(
30+
name = "ast_visitor",
31+
srcs = [
32+
"ast_visitor.cc",
33+
],
34+
hdrs = [
35+
"ast_visitor.h",
36+
],
37+
deps = [
38+
":util",
39+
],
40+
)
41+
42+
cc_library(
43+
name = "ast_consumer",
44+
srcs = [
45+
"ast_consumer.cc",
46+
],
47+
hdrs = [
48+
"ast_consumer.h",
49+
],
50+
deps = [
51+
":ast_visitor",
52+
],
53+
)
54+
55+
cc_library(
56+
name = "ast_fronten_action",
57+
srcs = [
58+
"ast_fronten_action.cc",
59+
],
60+
hdrs = [
61+
"ast_fronten_action.h",
62+
],
63+
deps = [
64+
":ast_visitor",
65+
":ast_consumer",
66+
],
67+
)

parse/ast_consumer.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "parse/ast_consumer.h"
2+
3+
#include <fstream>
4+
#include <iomanip>
5+
#include <iostream>
6+
#include <string>
7+
#include <vector>
8+
9+
#include "parse/util.h"
10+
11+
namespace clang {
12+
namespace tooling {
13+
namespace {
14+
using nlohmann::json;
15+
} // namespace
16+
17+
ASTConsumerImpl::ASTConsumerImpl(const ASTContext* context) : visitor_(context) {
18+
}
19+
20+
void ASTConsumerImpl::HandleTranslationUnit(ASTContext& Context) {
21+
visitor_.TraverseDecl(Context.getTranslationUnitDecl());
22+
json j;
23+
j["classes"] = visitor_.classes();
24+
j["functions"] = visitor_.functions();
25+
std::ofstream o("ast_output.json");
26+
if (o.is_open()) {
27+
o << std::setw(4) << j << std::endl;
28+
o.close();
29+
llvm::outs() << "AST output written to ast_output.json\n";
30+
} else {
31+
llvm::errs() << "Error: Unable to open output file for writing.\n";
32+
}
33+
}
34+
35+
} // namespace tooling
36+
} // namespace clang

parse/ast_consumer.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <clang/AST/ASTConsumer.h>
4+
5+
#include "parse/ast_visitor.h"
6+
7+
namespace clang {
8+
namespace tooling {
9+
10+
class ASTConsumerImpl : public ASTConsumer {
11+
public:
12+
explicit ASTConsumerImpl(const ASTContext* context);
13+
14+
public:
15+
void HandleTranslationUnit(ASTContext& Context) override;
16+
17+
private:
18+
ASTVisitor visitor_;
19+
};
20+
21+
} // namespace tooling
22+
} // namespace clang

parse/ast_fronten_action.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "parse/ast_fronten_action.h"
2+
3+
#include "parse/ast_consumer.h"
4+
5+
namespace clang {
6+
namespace tooling {
7+
8+
std::unique_ptr<ASTConsumer> ASTFrontendActionImpl::CreateASTConsumer(CompilerInstance& CI,
9+
StringRef) {
10+
return std::make_unique<ASTConsumerImpl>(&CI.getASTContext());
11+
}
12+
13+
} // namespace tooling
14+
} // namespace clang

parse/ast_fronten_action.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <clang/Frontend/FrontendActions.h>
4+
5+
#include "parse/ast_visitor.h"
6+
7+
namespace clang {
8+
namespace tooling {
9+
10+
class ASTFrontendActionImpl : public ASTFrontendAction {
11+
public:
12+
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& CI, StringRef InFile) override;
13+
};
14+
15+
} // namespace tooling
16+
} // namespace clang

parse/ast_visitor.cc

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#include "parse/ast_visitor.h"
2+
3+
#include "parse/util.h"
4+
5+
namespace clang {
6+
namespace tooling {
7+
ASTVisitor::ASTVisitor(const ASTContext* context) : context_(context) {
8+
}
9+
10+
bool ASTVisitor::VisitCXXRecordDecl(const CXXRecordDecl* decl) {
11+
if (decl->isThisDeclarationADefinition() &&
12+
IsProjectFile(context_->getSourceManager(), decl->getLocation())) {
13+
ClassInfo cls;
14+
cls.name = decl->getNameAsString();
15+
cls.kind = decl->getKindName();
16+
cls.comment = GetComment(decl, *context_);
17+
cls.ns = GetEnclosingNamespace(decl);
18+
19+
SourceLocation loc = decl->getLocation();
20+
const SourceManager& src_manager = context_->getSourceManager();
21+
PresumedLoc presu_loc = src_manager.getPresumedLoc(loc);
22+
if (!presu_loc.isInvalid()) {
23+
cls.location.file = presu_loc.getFilename();
24+
cls.location.line = presu_loc.getLine();
25+
cls.location.column = presu_loc.getColumn();
26+
}
27+
28+
for (const auto& base : decl->bases()) {
29+
std::string baseType = base.getType().getAsString();
30+
cls.bases.emplace_back(baseType);
31+
}
32+
33+
for (auto field : decl->fields()) {
34+
FieldInfo f;
35+
f.name = field->getNameAsString();
36+
f.type = field->getType().getAsString();
37+
f.access = AccessSpecifierToString(field->getAccess());
38+
cls.fields.emplace_back(f);
39+
}
40+
41+
for (auto method : decl->methods()) {
42+
if (!method->isImplicit()) {
43+
MethodInfo m;
44+
m.name = method->getNameAsString();
45+
m.return_type = method->getReturnType().getAsString();
46+
m.is_const = method->isConst();
47+
m.is_static = method->isStatic();
48+
m.is_virtual = method->isVirtualAsWritten();
49+
m.access = AccessSpecifierToString(method->getAccess());
50+
m.comment = GetComment(method, *context_);
51+
52+
SourceLocation src_loc = method->getLocation();
53+
PresumedLoc presu_loc = src_manager.getPresumedLoc(src_loc);
54+
if (!presu_loc.isInvalid()) {
55+
m.location.file = presu_loc.getFilename();
56+
m.location.line = presu_loc.getLine();
57+
m.location.column = presu_loc.getColumn();
58+
}
59+
60+
for (auto param : method->parameters()) {
61+
ParameterInfo p;
62+
p.name = param->getNameAsString();
63+
p.type = param->getOriginalType().getAsString();
64+
m.parameters.emplace_back(p);
65+
}
66+
cls.methods.emplace_back(m);
67+
}
68+
}
69+
classes_.emplace_back(cls);
70+
}
71+
return true;
72+
}
73+
74+
bool ASTVisitor::VisitFunctionDecl(const FunctionDecl* func_decl) {
75+
if (isa<CXXMethodDecl>(func_decl)) {
76+
return true;
77+
}
78+
if (!func_decl->isThisDeclarationADefinition()) {
79+
return true;
80+
}
81+
const SourceManager& src_manager = context_->getSourceManager();
82+
if (!IsProjectFile(src_manager, func_decl->getLocation())) {
83+
return true;
84+
}
85+
86+
FunctionInfo func;
87+
func.name = func_decl->getNameAsString();
88+
func.return_type = func_decl->getReturnType().getAsString();
89+
func.is_inline = func_decl->isInlineSpecified();
90+
func.comment = GetComment(func_decl, *context_);
91+
func.ns = GetEnclosingNamespace(func_decl);
92+
93+
SourceLocation loc = func_decl->getLocation();
94+
PresumedLoc presu_loc = src_manager.getPresumedLoc(loc);
95+
if (!presu_loc.isInvalid()) {
96+
func.location.file = presu_loc.getFilename();
97+
func.location.line = presu_loc.getLine();
98+
func.location.column = presu_loc.getColumn();
99+
}
100+
101+
for (auto param : func_decl->parameters()) {
102+
ParameterInfo p;
103+
p.name = param->getNameAsString();
104+
p.type = param->getOriginalType().getAsString();
105+
func.parameters.emplace_back(p);
106+
}
107+
108+
functions_.emplace_back(func);
109+
return true;
110+
}
111+
112+
const std::vector<ClassInfo>& ASTVisitor::classes() const {
113+
return classes_;
114+
}
115+
116+
const std::vector<FunctionInfo>& ASTVisitor::functions() const {
117+
return functions_;
118+
}
119+
120+
} // namespace tooling
121+
} // namespace clang

0 commit comments

Comments
 (0)