Inspired by Bastian Rieck's wonderful blogs, Baby Steps With LibClang: Walking an Abstract Syntax Tree and Baby Steps With LibClang: Counting Function Extents
Two blog's corresponding rust code
For a C++ file traverse_ast.cpp
like
template <typename T>
bool f(T x) {
return x % 2;
}
To get output like
FunctionTemplate (f)
TemplateTypeParameter (T)
ParmDecl (x)
TypeRef (T)
CompoundStmt ()
ReturnStmt ()
BinaryOperator ()
DeclRefExpr (x)
IntegerLiteral ()
You can use something like
use std::path::Path;
use clang_rs_binding::index::{Cursor, Payload, ChildVisitResult};
fn visitor(cursor: &Cursor, _parent: &Cursor, payload: Payload) -> i32 {
if cursor.is_from_main_file() {
return ChildVisitResult::CONTINUE;
}
let cursor_kind_spelling = cursor.kind_spelling();
let cursor_spelling = cursor.spelling();
println!("{} ({})", cursor_kind_spelling, cursor_spelling);
cursor.visit_children(visitor, payload);
ChildVisitResult::CONTINUE
}
fn generate_ast<P: AsRef<Path>>(filename: P) -> impl AsRef<Path> {
let ast_filename = Path::new("traverse_ast.ast");
std::process::Command::new("clang++")
.arg("-emit-ast").arg(filename.as_ref()).status().unwrap();
ast_filename
}
fn main() {
let traverse_ast_dir = Path::new("tests/artifacts/traverse_ast");
let ast_filename = generate_ast(traverse_ast_dir.join("traverse_ast.cpp"));
clang_rs_binding::clang::Clang::default()
.create_index_with_display_diagnostics()
.create_translation_unit(&ast_filename)
.create_cursor()
.visit_children(visitor, std::ptr::null());
}