summaryrefslogtreecommitdiff
path: root/src/clang.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/clang.rs')
-rw-r--r--src/clang.rs179
1 files changed, 151 insertions, 28 deletions
diff --git a/src/clang.rs b/src/clang.rs
index f8a68e12..5618007b 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -15,9 +15,24 @@ pub struct Cursor {
x: CXCursor
}
+impl fmt::Debug for Cursor {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Cursor({} kind: {}, loc: {})",
+ self.spelling(), kind_to_str(self.kind()), self.location())
+ }
+}
+
pub type CursorVisitor<'s> = for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult + 's;
impl Cursor {
+ pub fn is_declaration(&self) -> bool {
+ unsafe { clang_isDeclaration(self.kind()) != 0 }
+ }
+
+ pub fn null() -> Self {
+ Cursor { x: unsafe { clang_getNullCursor() } }
+ }
+
// common
pub fn spelling(&self) -> String {
unsafe {
@@ -43,18 +58,71 @@ impl Cursor {
}
}
+ pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
+ let sp = self.semantic_parent();
+ if sp == *self || !sp.is_valid() {
+ return None;
+ }
+ Some(sp)
+ }
+
pub fn semantic_parent(&self) -> Cursor {
unsafe {
Cursor { x: clang_getCursorSemanticParent(self.x) }
}
}
+ pub fn num_template_args(&self) -> c_int {
+ unsafe {
+ clang_Cursor_getNumTemplateArguments(self.x)
+ }
+ }
+
+
+ /// This function gets the translation unit cursor. Note that we shouldn't
+ /// create a TranslationUnit struct here, because bindgen assumes there will
+ /// only be one of them alive at a time, and dispose it on drop. That can
+ /// change if this would be required, but I think we can survive fine
+ /// without it.
+ pub fn translation_unit(&self) -> Cursor {
+ assert!(self.is_valid());
+ unsafe {
+ let tu = clang_Cursor_getTranslationUnit(self.x);
+ let cursor = Cursor {
+ x: clang_getTranslationUnitCursor(tu),
+ };
+ assert!(cursor.is_valid());
+ cursor
+ }
+ }
+
+ pub fn is_toplevel(&self) -> bool {
+ let mut semantic_parent = self.semantic_parent();
+
+ while semantic_parent.kind() == CXCursor_Namespace ||
+ semantic_parent.kind() == CXCursor_NamespaceAlias ||
+ semantic_parent.kind() == CXCursor_NamespaceRef
+ {
+ semantic_parent = semantic_parent.semantic_parent();
+ }
+
+ let tu = self.translation_unit();
+ // Yes, the second can happen with, e.g., macro definitions.
+ semantic_parent == tu || semantic_parent == tu.semantic_parent()
+ }
+
pub fn kind(&self) -> Enum_CXCursorKind {
unsafe {
clang_getCursorKind(self.x)
}
}
+ pub fn is_anonymous(&self) -> bool {
+ unsafe {
+ clang_Cursor_isAnonymous(self.x) != 0
+ }
+ }
+
pub fn is_template(&self) -> bool {
self.specialized().is_valid()
}
@@ -77,10 +145,11 @@ impl Cursor {
}
}
- pub fn raw_comment(&self) -> String {
- unsafe {
+ pub fn raw_comment(&self) -> Option<String> {
+ let s = unsafe {
String_ { x: clang_Cursor_getRawCommentText(self.x) }.to_string()
- }
+ };
+ if s.is_empty() { None } else { Some(s) }
}
pub fn comment(&self) -> Comment {
@@ -165,12 +234,18 @@ impl Cursor {
}
}
- pub fn enum_val(&self) -> i64 {
+ pub fn enum_val_signed(&self) -> i64 {
unsafe {
clang_getEnumConstantDeclValue(self.x) as i64
}
}
+ pub fn enum_val_unsigned(&self) -> u64 {
+ unsafe {
+ clang_getEnumConstantDeclUnsignedValue(self.x) as u64
+ }
+ }
+
// typedef
pub fn typedef_type(&self) -> Type {
unsafe {
@@ -195,7 +270,7 @@ impl Cursor {
pub fn args(&self) -> Vec<Cursor> {
unsafe {
let num = self.num_args() as usize;
- let mut args = vec!();
+ let mut args = vec![];
for i in 0..num {
args.push(Cursor { x: clang_Cursor_getArgument(self.x, i as c_uint) });
}
@@ -235,6 +310,12 @@ impl Cursor {
}
}
+ pub fn method_is_const(&self) -> bool {
+ unsafe {
+ clang_CXXMethod_isConst(self.x) != 0
+ }
+ }
+
pub fn method_is_virtual(&self) -> bool {
unsafe {
clang_CXXMethod_isVirtual(self.x) != 0
@@ -274,29 +355,40 @@ impl PartialEq for Cursor {
clang_equalCursors(self.x, other.x) == 1
}
}
-
- fn ne(&self, other: &Cursor) -> bool {
- !self.eq(other)
- }
}
impl Eq for Cursor {}
impl Hash for Cursor {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.x.kind.hash(state);
- self.x.xdata.hash(state);
- self.x.data[0].hash(state);
- self.x.data[1].hash(state);
- self.x.data[2].hash(state);
+ unsafe { clang_hashCursor(self.x) }.hash(state)
}
}
// type
+#[derive(Clone, Hash)]
pub struct Type {
x: CXType
}
+impl PartialEq for Type {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ clang_equalTypes(self.x, other.x) != 0
+ }
+ }
+}
+
+impl Eq for Type {}
+
+impl fmt::Debug for Type {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Type({}, kind: {}, decl: {:?}, canon: {:?})",
+ self.spelling(), type_to_str(self.kind()), self.declaration(),
+ self.declaration().canonical())
+ }
+}
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum LayoutError {
Invalid,
@@ -358,7 +450,7 @@ impl Type {
pub fn is_const(&self) -> bool {
unsafe {
- clang_isConstQualifiedType(self.x) == 1
+ clang_isConstQualifiedType(self.x) != 0
}
}
@@ -378,6 +470,24 @@ impl Type {
}
}
+ pub fn fallible_align(&self) -> Result<usize, LayoutError> {
+ unsafe {
+ let val = clang_Type_getAlignOf(self.x);
+ if val < 0 {
+ Err(LayoutError::from(val as i32))
+ } else {
+ Ok(val as usize)
+ }
+ }
+ }
+
+ pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> {
+ use ir::layout::Layout;
+ let size = try!(self.fallible_size());
+ let align = try!(self.fallible_align());
+ Ok(Layout::new(size, align))
+ }
+
pub fn align(&self) -> usize {
unsafe {
let val = clang_Type_getAlignOf(self.x);
@@ -427,7 +537,7 @@ impl Type {
// function
pub fn is_variadic(&self) -> bool {
unsafe {
- clang_isFunctionTypeVariadic(self.x) == 1
+ clang_isFunctionTypeVariadic(self.x) != 0
}
}
@@ -581,21 +691,25 @@ pub struct Index {
}
impl Index {
- pub fn create(pch: bool, diag: bool) -> Index {
+ pub fn new(pch: bool, diag: bool) -> Index {
unsafe {
Index { x: clang_createIndex(pch as c_int, diag as c_int) }
}
}
+}
- pub fn dispose(&self) {
+impl fmt::Debug for Index {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Index {{ }}")
+ }
+}
+
+impl Drop for Index {
+ fn drop(&mut self) {
unsafe {
clang_disposeIndex(self.x);
}
}
-
- pub fn is_null(&self) -> bool {
- self.x.is_null()
- }
}
// Token
@@ -609,6 +723,12 @@ pub struct TranslationUnit {
x: CXTranslationUnit
}
+impl fmt::Debug for TranslationUnit {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "TranslationUnit {{ }}")
+ }
+}
+
impl TranslationUnit {
pub fn parse(ix: &Index, file: &str, cmd_args: &[String],
unsaved: &[UnsavedFile], opts: ::libc::c_uint) -> TranslationUnit {
@@ -655,12 +775,6 @@ impl TranslationUnit {
}
}
- pub fn dispose(&self) {
- unsafe {
- clang_disposeTranslationUnit(self.x);
- }
- }
-
pub fn is_null(&self) -> bool {
self.x.is_null()
}
@@ -687,6 +801,15 @@ impl TranslationUnit {
}
}
+impl Drop for TranslationUnit {
+ fn drop(&mut self) {
+ unsafe {
+ clang_disposeTranslationUnit(self.x);
+ }
+ }
+}
+
+
// Diagnostic
pub struct Diagnostic {
x: CXDiagnostic