diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-02 12:57:15 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-02 13:00:48 -0800 |
commit | 42b721def01aba5034c857780a4bced3c9995a2e (patch) | |
tree | fafd7e56fa6f700e8e116db0288e8baea7a5b5b8 | |
parent | c1aaa6a400d4a92ae442bfeaa188c5303810611b (diff) |
Enhance Clang AST dumping
This commit extends our existing Clang AST dumping to include more information,
such as a cursor's canonical, referenced, and declarations cursors if they
exist. It prints out most of the information that libclang gives us directly,
but not the information that we attempt to (re)construct on top of the libclang
APIs.
-rw-r--r-- | src/clang.rs | 153 |
1 files changed, 144 insertions, 9 deletions
diff --git a/src/clang.rs b/src/clang.rs index a40abfca..3b669cd5 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1273,21 +1273,156 @@ pub fn type_to_str(x: CXTypeKind) -> String { /// Dump the Clang AST to stdout for debugging purposes. pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult { - fn print_indent(depth: isize, s: &str) { + fn print_indent<S: AsRef<str>>(depth: isize, s: S) { for _ in 0..depth { - print!("\t"); + print!(" "); + } + println!("{}", s.as_ref()); + } + + fn print_cursor<S: AsRef<str>>(depth: isize, prefix: S, c: &Cursor) { + let prefix = prefix.as_ref(); + print_indent(depth, format!(" {}kind = {}", prefix, kind_to_str(c.kind()))); + print_indent(depth, format!(" {}spelling = \"{}\"", prefix, c.spelling())); + print_indent(depth, format!(" {}location = {}", prefix, c.location())); + print_indent(depth, format!(" {}is-definition? {}", prefix, c.is_definition())); + print_indent(depth, format!(" {}is-declaration? {}", prefix, c.is_declaration())); + print_indent(depth, format!(" {}is-anonymous? {}", prefix, c.is_anonymous())); + print_indent(depth, format!(" {}is-inlined-function? {}", prefix, c.is_inlined_function())); + + let templ_kind = c.template_kind(); + if templ_kind != CXCursor_NoDeclFound { + print_indent(depth, format!(" {}template-kind = {}", prefix, kind_to_str(templ_kind))); + } + if let Some(usr) = c.usr() { + print_indent(depth, format!(" {}usr = \"{}\"", prefix, usr)); + } + if let Ok(num) = c.num_args() { + print_indent(depth, format!(" {}number-of-args = {}", prefix, num)); + } + if let Some(num) = c.num_template_args() { + print_indent(depth, format!(" {}number-of-template-args = {}", prefix, num)); + } + if let Some(width) = c.bit_width() { + print_indent(depth, format!(" {}bit-width = {}", prefix, width)); + } + if let Some(ty) = c.enum_type() { + print_indent(depth, format!(" {}enum-type = {}", prefix, type_to_str(ty.kind()))); + } + if let Some(val) = c.enum_val_signed() { + print_indent(depth, format!(" {}enum-val = {}", prefix, val)); + } + if let Some(ty) = c.typedef_type() { + print_indent(depth, format!(" {}typedef-type = {}", prefix, type_to_str(ty.kind()))); + } + + if let Some(def) = c.definition() { + if def != *c { + println!(); + print_cursor(depth, String::from(prefix) + "definition.", &def); + } + } + + if let Some(refd) = c.referenced() { + if refd != *c { + println!(); + print_cursor(depth, String::from(prefix) + "referenced.", &refd); + } + } + + let canonical = c.canonical(); + if canonical != *c { + println!(); + print_cursor(depth, String::from(prefix) + "canonical.", &canonical); + } + + if let Some(specialized) = c.specialized() { + if specialized != *c { + println!(); + print_cursor(depth, String::from(prefix) + "specialized.", &specialized); + } + } + } + + fn print_type<S: AsRef<str>>(depth: isize, prefix: S, ty: &Type) { + let prefix = prefix.as_ref(); + + let kind = ty.kind(); + print_indent(depth, format!(" {}kind = {}", prefix, type_to_str(kind))); + if kind == CXType_Invalid { + return; + } + + print_indent(depth, format!(" {}spelling = \"{}\"", prefix, ty.spelling())); + let num_template_args = unsafe { + clang_Type_getNumTemplateArguments(ty.x) + }; + if num_template_args >= 0 { + print_indent(depth, format!(" {}number-of-template-args = {}", + prefix, + num_template_args)); + } + if let Some(num) = ty.num_elements() { + print_indent(depth, format!(" {}number-of-elements = {}", prefix, num)); + } + print_indent(depth, format!(" {}is-variadic? {}", prefix, ty.is_variadic())); + + let canonical = ty.canonical_type(); + if canonical != *ty { + println!(); + print_type(depth, String::from(prefix) + "canonical.", &canonical); + } + + if let Some(pointee) = ty.pointee_type() { + if pointee != *ty { + println!(); + print_type(depth, String::from(prefix) + "pointee.", &pointee); + } + } + + if let Some(elem) = ty.elem_type() { + if elem != *ty { + println!(); + print_type(depth, String::from(prefix) + "elements.", &elem); + } + } + + if let Some(ret) = ty.ret_type() { + if ret != *ty { + println!(); + print_type(depth, String::from(prefix) + "return.", &ret); + } + } + + let named = ty.named(); + if named != *ty && named.is_valid() { + println!(); + print_type(depth, String::from(prefix) + "named.", &named); } - println!("{}", s); } - print_indent(depth, - &format!("(kind: {}, spelling: {}, type: {}", - kind_to_str(c.kind()), - c.spelling(), - type_to_str(c.cur_type().kind()))); + print_indent(depth, "("); + print_cursor(depth, "", c); + + println!(); + let ty = c.cur_type(); + print_type(depth, "type.", &ty); + + let declaration = ty.declaration(); + if declaration != *c && declaration.kind() != CXCursor_NoDeclFound { + println!(); + print_cursor(depth, "type.declaration.", &declaration); + } // Recurse. - c.visit(|s| ast_dump(&s, depth + 1)); + let mut found_children = false; + c.visit(|s| { + if !found_children { + println!(); + found_children = true; + } + ast_dump(&s, depth + 1) + }); print_indent(depth, ")"); |