diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-10-26 17:58:50 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-26 17:58:50 -0500 |
commit | e72e466deca59d1ab26036b96731bb4114d915ba (patch) | |
tree | 1bb2b1b754c20adff0e0d4fcc74c6226c43d2f01 | |
parent | 818b29113d9fa6fb867fc08db587ae8ec75579fb (diff) | |
parent | 85f1a3fe9cd89126394604a0b5c4c64f793d4b3a (diff) |
Auto merge of #146 - fitzgen:moar-docs, r=fitzgen
Document the `clang` module
I found an OK way to require docs on public methods for internal modules with a macro and feature flag combo (see first commit). Then I made documentation for public methods in the `clang` module required, and filled them out (see the second commit).
r? @emilio
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | CONTRIBUTING.md | 4 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | src/clang.rs | 299 | ||||
-rwxr-xr-x | src/lib.rs | 23 |
5 files changed, 270 insertions, 60 deletions
diff --git a/.travis.yml b/.travis.yml index 70db4df3..031c61ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,7 @@ script: - git add -A - git diff @ - git diff-index --quiet HEAD + - cargo build --features "llvm_stable _docs" notifications: webhooks: http://build.servo.org:54856/travis diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3011a853..3f1e39d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,10 @@ issue, provide us with: Build instructions are in the [README](./README.md). +Additionally, you may want to build and test with the `_docs` feature to ensure +that you aren't forgetting to document types and functions. CI will catch it if +you forget, but the turn around will be a lot slower ;) + ## Testing <span id="tests"/> ### Overview <span id="tests-overview"/> @@ -22,6 +22,7 @@ name = "bindgen" quasi_codegen = "0.20" [dependencies] +cfg-if = "0.1.0" clang-sys = "0.8.0" lazy_static = "0.1.*" libc = "0.2" @@ -46,6 +47,8 @@ version = "0.20" [features] llvm_stable = [] static = [] +# This feature only exists for CI -- don't use it! +_docs = [] [lib] name = "bindgen" diff --git a/src/clang.rs b/src/clang.rs index de405c9d..fa4eb01b 100644..100755 --- a/src/clang.rs +++ b/src/clang.rs @@ -1,3 +1,6 @@ +//! A higher level Clang API built on top of the generated bindings in the +//! `clangll` module. + #![allow(non_upper_case_globals, dead_code)] use std::os::raw::{c_uint, c_char, c_int, c_ulong, c_longlong}; @@ -9,7 +12,9 @@ use std::ffi::{CString, CStr}; use clangll::*; -// Cursor +/// A cursor into the Clang AST, pointing to an AST node. +/// +/// We call the AST node pointed to by the cursor the cursor's "referent". #[derive(Copy, Clone)] pub struct Cursor { x: CXCursor @@ -22,9 +27,18 @@ impl fmt::Debug for Cursor { } } +/// A cursor visitor function. +/// +/// The first argument is the AST node currently being visited. The second +/// argument is the parent of the AST node currently being visited. The return +/// value informs how traversal should proceed. pub type CursorVisitor<'s> = for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult + 's; impl Cursor { + /// Get the Unified Symbol Resolution for this cursor's referent, if + /// available. + /// + /// The USR can be used to compare entities across translation units. pub fn usr(&self) -> Option<String> { let s = String_ { x: unsafe { clang_getCursorUSR(self.x) } }.to_string(); if s.is_empty() { @@ -34,39 +48,67 @@ impl Cursor { } } + /// Is this cursor's referent a declaration? pub fn is_declaration(&self) -> bool { unsafe { clang_isDeclaration(self.kind()) != 0 } } + /// Get the null cursor, which has no referent. pub fn null() -> Self { Cursor { x: unsafe { clang_getNullCursor() } } } - // common + /// Get this cursor's referent's spelling. pub fn spelling(&self) -> String { unsafe { String_ { x: clang_getCursorSpelling(self.x) }.to_string() } } + /// Get this cursor's referent's display name. + /// + /// This is not necessarily a valid identifier. It includes extra + /// information, such as parameters for a function, etc. pub fn display_name(&self) -> String { unsafe { String_ { x: clang_getCursorDisplayName(self.x) }.to_string() } } + /// Get the mangled name of this cursor's referent. pub fn mangling(&self) -> String { unsafe { String_ { x: clang_Cursor_getMangling(self.x) }.to_string() } } + /// Get the `Cursor` for this cursor's referent's lexical parent. + /// + /// The lexical parent is the parent of the definition. The semantic parent + /// is the parent of the declaration. Generally, the lexical parent doesn't + /// have any effect on semantics, while the semantic parent does. + /// + /// In the following snippet, the `Foo` class would be the semantic parent + /// of the out-of-line `method` definition, while the lexical parent is the + /// translation unit. + /// + /// ```c++ + /// class Foo { + /// void method(); + /// }; + /// + /// void Foo::method() { /* ... */ } + /// ``` pub fn lexical_parent(&self) -> Cursor { unsafe { Cursor { x: clang_getCursorLexicalParent(self.x) } } } + /// Get the referent's semantic parent, if one is available. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. pub fn fallible_semantic_parent(&self) -> Option<Cursor> { let sp = self.semantic_parent(); if sp == *self || !sp.is_valid() { @@ -75,24 +117,31 @@ impl Cursor { Some(sp) } + /// Get the referent's semantic parent. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. pub fn semantic_parent(&self) -> Cursor { unsafe { Cursor { x: clang_getCursorSemanticParent(self.x) } } } + /// Return the number of template arguments used by this cursor's referent, + /// if the referent is either a template specialization or + /// declaration. Returns -1 otherwise. 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. + /// Get a cursor pointing to this referent's containing translation unit. + /// + /// 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 + /// disposes 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 { @@ -105,6 +154,7 @@ impl Cursor { } } + /// Is the referent a top level construct? pub fn is_toplevel(&self) -> bool { let mut semantic_parent = self.semantic_parent(); @@ -120,26 +170,33 @@ impl Cursor { semantic_parent == tu || semantic_parent == tu.semantic_parent() } + /// Get the kind of referent this cursor is pointing to. pub fn kind(&self) -> Enum_CXCursorKind { unsafe { clang_getCursorKind(self.x) } } + /// Is the referent an anonymous record definition? pub fn is_anonymous(&self) -> bool { unsafe { clang_Cursor_isAnonymous(self.x) != 0 } } + /// Is the referent a template specialization? pub fn is_template(&self) -> bool { self.specialized().is_valid() } + /// Is the referent a fully specialized template specialization without any + /// remaining free template arguments? pub fn is_fully_specialized_template(&self) -> bool { self.is_template() && self.num_template_args() > 0 } + /// Is the referent a template specialization that still has remaining free + /// template arguments? pub fn is_in_non_fully_specialized_template(&self) -> bool { if self.is_toplevel() { return false; @@ -149,24 +206,28 @@ impl Cursor { parent.is_in_non_fully_specialized_template() } + /// Is this cursor pointing a valid referent? pub fn is_valid(&self) -> bool { unsafe { clang_isInvalid(self.kind()) == 0 } } + /// Get the source location for the referent. pub fn location(&self) -> SourceLocation { unsafe { SourceLocation { x: clang_getCursorLocation(self.x) } } } + /// Get the source location range for the referent. pub fn extent(&self) -> CXSourceRange { unsafe { clang_getCursorExtent(self.x) } } + /// Get the raw declaration comment for this referent, if one exists. pub fn raw_comment(&self) -> Option<String> { let s = unsafe { String_ { x: clang_Cursor_getRawCommentText(self.x) }.to_string() @@ -174,47 +235,68 @@ impl Cursor { if s.is_empty() { None } else { Some(s) } } + /// Get the referent's parsed comment. pub fn comment(&self) -> Comment { unsafe { Comment { x: clang_Cursor_getParsedComment(self.x) } } } + /// Get the referent's type. pub fn cur_type(&self) -> Type { unsafe { Type { x: clang_getCursorType(self.x) } } } + /// Given that this cursor's referent is a reference to another type, or is + /// a declaration, get the cursor pointing to the referenced type or type of + /// the declared thing. pub fn definition(&self) -> Cursor { unsafe { Cursor { x: clang_getCursorDefinition(self.x) } } } + /// Given that this cursor's referent is reference type, get the cursor + /// pointing to the referenced type. pub fn referenced(&self) -> Cursor { unsafe { Cursor { x: clang_getCursorReferenced(self.x) } } } + /// Get the canonical cursor for this referent. + /// + /// Many types can be declared multiple times before finally being properly + /// defined. This method allows us to get the canonical cursor for the + /// referent type. pub fn canonical(&self) -> Cursor { unsafe { Cursor { x: clang_getCanonicalCursor(self.x) } } } + /// Given that this cursor points to a template specialization, get a cursor + /// pointing to the template definition that is being specialized. pub fn specialized(&self) -> Cursor { unsafe { Cursor { x: clang_getSpecializedCursorTemplate(self.x) } } } + /// Assuming that this cursor's referent is a template declaration, get the + /// kind of cursor that would be generated for its specializations. pub fn template_kind(&self) -> Enum_CXCursorKind { unsafe { clang_getTemplateCursorKind(self.x) } } - pub fn visit<F>(&self, func:F) + /// Traverse this cursor's referent and its children. + /// + /// Call the given function on each AST node traversed. See `CursorVisitor` + /// for details on arguments passed to the function and how its return value + /// is interpreted. + pub fn visit<F>(&self, func: F) where F: for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult { let mut data: Box<CursorVisitor> = Box::new(func); @@ -224,6 +306,7 @@ impl Cursor { } } + /// Is the referent an inlined function? #[cfg(not(feature="llvm_stable"))] pub fn is_inlined_function(&self) -> bool { unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 } @@ -232,12 +315,15 @@ impl Cursor { // TODO: Remove this when LLVM 3.9 is released. // // This is currently used for CI purposes. + + /// Is the referent an inlined function? #[cfg(feature="llvm_stable")] pub fn is_inlined_function(&self) -> bool { false } - // bitfield + /// Get the width of this cursor's referent bit field, or `None` if the + /// referent is not a bit field. pub fn bit_width(&self) -> Option<u32> { unsafe { let w = clang_getFieldDeclBitWidth(self.x); @@ -249,46 +335,62 @@ impl Cursor { } } - // enum + /// Get the integer representation type used to hold this cursor's referent + /// enum type. pub fn enum_type(&self) -> Type { unsafe { Type { x: clang_getEnumDeclIntegerType(self.x) } } } + /// Get the signed constant value for this cursor's enum variant referent. + /// + /// Returns `LLONG_MIN` if the cursor's referent is not an enum variant, + /// which is also a valid enum value, so callers should check the cursor + /// kind before calling this method (see issue #127). pub fn enum_val_signed(&self) -> i64 { unsafe { clang_getEnumConstantDeclValue(self.x) as i64 } } + /// Get the unsigned constant value for this cursor's enum variant referent. + /// + /// Returns `ULLONG_MAX` if the cursor's referent is not an enum variant, + /// which is also a valid enum value, so callers should check the cursor + /// kind before calling this method (see issue #128). pub fn enum_val_unsigned(&self) -> u64 { unsafe { clang_getEnumConstantDeclUnsignedValue(self.x) as u64 } } - // typedef + /// Given that this cursor's referent is a `typedef`, get the `Type` that is + /// being aliased. pub fn typedef_type(&self) -> Type { unsafe { Type { x: clang_getTypedefDeclUnderlyingType(self.x) } } } - // function, variable + /// Get the linkage kind for this cursor's referent. + /// + /// This only applies to functions and variables. pub fn linkage(&self) -> Enum_CXLinkageKind { unsafe { clang_getCursorLinkage(self.x) } } + /// Get the visibility of this cursor's referent. pub fn visibility(&self) -> Enum_CXVisibilityKind { unsafe { clang_getCursorVisibility(self.x) } } - // function + /// Given that this cursor's referent is a function, return cursors to its + /// parameters. pub fn args(&self) -> Vec<Cursor> { unsafe { let num = self.num_args() as usize; @@ -300,64 +402,82 @@ impl Cursor { } } + /// Given that this cursor's referent is a function/method call or + /// declaration, return a cursor to its return type. pub fn ret_type(&self) -> Type { unsafe { Type { x: clang_getCursorResultType(self.x) } } } + /// Given that this cursor's referent is a function/method call or + /// declaration, return the number of arguments it takes. + /// + /// Returns -1 if the cursor's referent is not a function/method call or + /// declaration. pub fn num_args(&self) -> i32 { unsafe { clang_Cursor_getNumArguments(self.x) } } - // CXX member + /// Get the access specifier for this cursor's referent. pub fn access_specifier(&self) -> Enum_CX_CXXAccessSpecifier { unsafe { clang_getCXXAccessSpecifier(self.x) } } + /// Is this cursor's referent a field declaration that is marked as + /// `mutable`? pub fn is_mutable_field(&self) -> bool { unsafe { clang_CXXField_isMutable(self.x) != 0 } } - // CXX method + /// Is this cursor's referent a member function that is declared `static`? pub fn method_is_static(&self) -> bool { unsafe { clang_CXXMethod_isStatic(self.x) != 0 } } + /// Is this cursor's referent a member function that is declared `const`? pub fn method_is_const(&self) -> bool { unsafe { clang_CXXMethod_isConst(self.x) != 0 } } + /// Is this cursor's referent a member function that is declared `const`? pub fn method_is_virtual(&self) -> bool { unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } } - // CXX base + /// Is this cursor's referent a struct or class with virtual members? pub fn is_virtual_base(&self) -> bool { unsafe { clang_isVirtualBase(self.x) != 0 } } - // CXX template + /// Given that this cursor's referent is a template specialization or + /// declaration, get the `i`th template argument kind. + /// + /// If the referent is not a template or `i` is out of bounds, an invalid + /// kind is returned. pub fn template_arg_kind(&self, i: c_int) -> CXTemplateArgumentKind { unsafe { clang_Cursor_getTemplateArgumentKind(self.x, i as c_uint) } } + /// Given that this cursor's referent is a template specialization, and that + /// the `i`th template argument is an integral, get the `i`th template + /// argument value. pub fn template_arg_value(&self, i: c_int) -> c_longlong { unsafe { clang_Cursor_getTemplateArgumentValue(self.x, i as c_uint) @@ -387,7 +507,7 @@ impl Hash for Cursor { } } -// type +/// The type of a node in clang's AST. #[derive(Clone, Hash)] pub struct Type { x: CXType @@ -411,13 +531,21 @@ impl fmt::Debug for Type { } } +/// An error about the layout of a struct, class, or type. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum LayoutError { + /// Asked for the layout of an invalid type. Invalid, + /// Asked for the layout of an incomplete type. Incomplete, + /// Asked for the layout of a dependent type. Dependent, + /// Asked for the layout of a type that does not have constant size. NotConstantSize, + /// Asked for the layout of a field in a type that does not have such a + /// field. InvalidFieldName, + /// An unknown layout error. Unknown, } @@ -436,46 +564,34 @@ impl ::std::convert::From<i32> for LayoutError { } impl Type { - // common + /// Get this type's kind. pub fn kind(&self) -> Enum_CXTypeKind { self.x.kind } + /// Get a cursor pointing to this type's declaration. pub fn declaration(&self) -> Cursor { unsafe { Cursor { x: clang_getTypeDeclaration(self.x) } } } + /// Get a raw display name for this type. pub fn spelling(&self) -> String { unsafe { String_ { x: clang_getTypeSpelling(self.x) }.to_string() } } - - // XXX make it more consistent - // - // This is currently only used to detect typedefs, - // so it should not be a problem. - pub fn sanitized_spelling(&self) -> String { - self.spelling() - .replace("const ", "") - .split(' ').next().unwrap_or("").to_owned() - } - - pub fn sanitized_spelling_in(&self, possible: &[String]) -> bool { - let type_spelling = self.sanitized_spelling(); - possible.iter() - .any(|spelling| *spelling == *type_spelling) - } - + /// Is this type const qualified? pub fn is_const(&self) -> bool { unsafe { clang_isConstQualifiedType(self.x) != 0 } } + /// What is the size of this type? Paper over invalid types by returning `0` + /// for them. pub fn size(&self) -> usize { unsafe { let val = clang_Type_getSizeOf(self.x); @@ -483,6 +599,7 @@ impl Type { } } + /// What is the size of this type? pub fn fallible_size(&self) -> Result<usize, LayoutError> { let val = unsafe { clang_Type_getSizeOf(self.x) }; if val < 0 { @@ -492,6 +609,16 @@ impl Type { } } + /// What is the alignment of this type? Paper over invalid types by + /// returning `0`. + pub fn align(&self) -> usize { + unsafe { + let val = clang_Type_getAlignOf(self.x); + if val < 0 { 0 } else { val as usize } + } + } + + /// What is the alignment of this type? pub fn fallible_align(&self) -> Result<usize, LayoutError> { unsafe { let val = clang_Type_getAlignOf(self.x); @@ -503,6 +630,8 @@ impl Type { } } + /// Get the layout for this type, or an error describing why it does not + /// have a valid layout. pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> { use ir::layout::Layout; let size = try!(self.fallible_size()); @@ -510,59 +639,63 @@ impl Type { Ok(Layout::new(size, align)) } - pub fn align(&self) -> usize { - unsafe { - let val = clang_Type_getAlignOf(self.x); - if val < 0 { 0 } else { val as usize } - } - } - + /// If this type is a class template specialization, return its number of + /// template arguments. Otherwise, return -1. pub fn num_template_args(&self) -> c_int { unsafe { clang_Type_getNumTemplateArguments(self.x) } } + /// Get the type of the `i`th template argument for this template + /// specialization. pub fn template_arg_type(&self, i: c_int) -> Type { unsafe { Type { x: clang_Type_getTemplateArgumentAsType(self.x, i) } } } - // pointer + /// Given that this type is a pointer type, return the type that it points + /// to. pub fn pointee_type(&self) -> Type { unsafe { Type { x: clang_getPointeeType(self.x) } } } - // array, vector or complex. + /// Given that this type is an array, vector, or complex type, return the + /// type of its elements. pub fn elem_type(&self) -> Type { unsafe { Type { x: clang_getElementType(self.x) } } } + /// Given that this type is an array or vector type, return its number of + /// elements. pub fn num_elements(&self) -> usize { unsafe { clang_getNumElements(self.x) as usize } } - // typedef + /// Get the canonical version of this type. This sees through `typdef`s and + /// aliases to get the underlying, canonical type. pub fn canonical_type(&self) -> Type { unsafe { Type { x: clang_getCanonicalType(self.x) } } } - // function + /// Is this type a variadic function type? pub fn is_variadic(&self) -> bool { unsafe { clang_isFunctionTypeVariadic(self.x) != 0 } } + /// Given that this type is a function type, get the types of its + /// parameters. pub fn arg_types(&self) -> Vec<Type> { unsafe { let num = clang_getNumArgTypes(self.x) as usize; @@ -574,18 +707,24 @@ impl Type { } } + /// Given that this type is a function type, get the type of its return + /// value. pub fn ret_type(&self) -> Type { unsafe { Type { x: clang_getResultType(self.x) } } } + /// Given that this type is a function type, get its calling convention. If + /// this is not a function type, `CXCallingConv_Invalid` is returned. pub fn call_conv(&self) -> Enum_CXCallingConv { unsafe { clang_getFunctionTypeCallingConv(self.x) } } + /// For elaborated types (types which use `class`, `struct`, or `union` to + /// disambiguate types from local bindings), get the underlying type. #[cfg(not(feature="llvm_stable"))] pub fn named(&self) -> Type { unsafe { @@ -594,12 +733,15 @@ impl Type { } } -// SourceLocation +/// A `SourceLocation` is a file, line, column, and byte offset location for +/// some source text. pub struct SourceLocation { x: CXSourceLocation } impl SourceLocation { + /// Get the (file, line, column, byte offset) tuple for this source + /// location. pub fn location(&self) -> (File, usize, usize, usize) { unsafe { let mut file = ptr::null_mut(); @@ -623,49 +765,61 @@ impl fmt::Display for SourceLocation { } } -// Comment +/// A comment in the source text. +/// +/// Comments are sort of parsed by Clang, and have a tree structure. pub struct Comment { x: CXComment } impl Comment { + /// What kind of comment is this? pub fn kind(&self) -> Enum_CXCommentKind { unsafe { clang_Comment_getKind(self.x) } } + /// Get the number of children this comment node has. pub fn num_children(&self) -> c_uint { unsafe { clang_Comment_getNumChildren(self.x) } } + /// Get this comment's `idx`th child comment pub fn get_child(&self, idx: c_uint) -> Comment { unsafe { Comment { x: clang_Comment_getChild(self.x, idx) } } } - // HTML + /// Given that this comment is the start or end of an HTML tag, get its tag + /// name. pub fn get_tag_name(&self) -> String { unsafe { String_ { x: clang_HTMLTagComment_getTagName(self.x) }.to_string() } } + /// Given that this comment is an HTML start tag, get the number of HTML + /// attributes it has. pub fn get_num_tag_attrs(&self) -> c_uint { unsafe { clang_HTMLStartTag_getNumAttrs(self.x) } } + /// Given that this comment is an HTML start tag, get the `idx`th + /// attribute's name. pub fn get_tag_attr_name(&self, idx: c_uint) -> String { unsafe { String_ { x: clang_HTMLStartTag_getAttrName(self.x, idx) }.to_string() } } + /// Given that this comment is an HTML start tag, get the `idx`th + /// attribute's value. pub fn get_tag_attr_value(&self, idx: c_uint) -> String { unsafe { String_ { x: clang_HTMLStartTag_getAttrValue(self.x, idx) }.to_string() @@ -673,12 +827,13 @@ impl Comment { } } -// File +/// A source file. pub struct File { x: CXFile } impl File { + /// Get the name of this source file. pub fn name(&self) -> Option<String> { if self.x.is_null() { return None; @@ -689,7 +844,7 @@ impl File { } } -// String +/// A Clang string. pub struct String_ { x: CXString } @@ -707,12 +862,19 @@ impl fmt::Display for String_ { } } -// Index +/// An `Index` is an environment for a set of translation units that will +/// typically end up linked together in one final binary. pub struct Index { x: CXIndex } impl Index { + /// Construct a new `Index`. + /// + /// The `pch` parameter controls whether declarations in pre-compiled + /// headers are included when enumerating a translation unit's "locals". + /// + /// The `diag` parameter controls whether debugging diagnostics are enabled. pub fn new(pch: bool, diag: bool) -> Index { unsafe { Index { x: clang_createIndex(pch as c_int, diag as c_int) } @@ -734,14 +896,16 @@ impl Drop for Index { } } -// Token +/// A token emitted by clang's lexer. #[derive(Debug)] pub struct Token { + /// The kind of token this is. pub kind: CXTokenKind, + /// A display name for this token. pub spelling: String, } -// TranslationUnit +/// A translation unit (or "compilation unit"). pub struct TranslationUnit { x: CXTranslationUnit } @@ -753,6 +917,7 @@ impl fmt::Debug for TranslationUnit { } impl TranslationUnit { + /// Parse a source file into a translation unit. pub fn parse(ix: &Index, file: &str, cmd_args: &[String], unsaved: &[UnsavedFile], opts: ::libc::c_uint) -> TranslationUnit { let fname = CString::new(file).unwrap(); @@ -770,6 +935,8 @@ impl TranslationUnit { TranslationUnit { x: tu } } + /// Reparse this translation unit, maybe because the file changed on disk or + /// something like that. pub fn reparse(&self, unsaved: &[UnsavedFile], opts: usize) -> bool { let mut c_unsaved: Vec<Struct_CXUnsavedFile> = unsaved.iter().map(|f| f.x).collect(); @@ -781,6 +948,8 @@ impl TranslationUnit { } } + /// Get the Clang diagnostic information associated with this translation + /// unit. pub fn diags(&self) -> Vec<Diagnostic> { unsafe { let num = clang_getNumDiagnostics(self.x) as usize; @@ -792,16 +961,20 @@ impl TranslationUnit { } } + /// Get a cursor pointing to the root of this translation unit's AST. pub fn cursor(&self) -> Cursor { unsafe { Cursor { x: clang_getTranslationUnitCursor(self.x) } } } + /// Is this the null translation unit? pub fn is_null(&self) -> bool { self.x.is_null() } + /// Invoke Clang's lexer on this translation unit and get the stream of + /// tokens that come out. pub fn tokens(&self, cursor: &Cursor) -> Option<Vec<Token>> { let range = cursor.extent(); let mut tokens = vec![]; @@ -833,30 +1006,35 @@ impl Drop for TranslationUnit { } -// Diagnostic +/// A diagnostic message generated while parsing a translation unit. pub struct Diagnostic { x: CXDiagnostic } impl Diagnostic { + /// Get the default diagnostic display option bit flags. pub fn default_opts() -> usize { unsafe { clang_defaultDiagnosticDisplayOptions() as usize } } + /// Format this diagnostic message as a string, using the given option bit + /// flags. pub fn format(&self, opts: usize) -> String { unsafe { String_ { x: clang_formatDiagnostic(self.x, opts as c_uint) }.to_string() } } + /// What is the severity of this diagnostic message? pub fn severity(&self) -> Enum_CXDiagnosticSeverity { unsafe { clang_getDiagnosticSeverity(self.x) } } + /// Destroy this diagnostic message. pub fn dispose(&self) { unsafe { clang_disposeDiagnostic(self.x); @@ -864,7 +1042,7 @@ impl Diagnostic { } } -// UnsavedFile +/// A file which has not been saved to disk. pub struct UnsavedFile { x: Struct_CXUnsavedFile, name: CString, @@ -872,6 +1050,7 @@ pub struct UnsavedFile { } impl UnsavedFile { + /// Construct a new unsaved file with the given `name` and `contents`. pub fn new(name: &str, contents: &str) -> UnsavedFile { let name = CString::new(name).unwrap(); let contents = CString::new(contents).unwrap(); @@ -888,6 +1067,7 @@ impl UnsavedFile { } } +/// Convert a cursor kind into a static string. pub fn kind_to_str(x: Enum_CXCursorKind) -> &'static str { match x { CXCursor_UnexposedDecl => "UnexposedDecl", @@ -1057,6 +1237,7 @@ pub fn kind_to_str(x: Enum_CXCursorKind) -> &'static str { } } +/// Convert a type kind to a static string. pub fn type_to_str(x: Enum_CXTypeKind) -> &'static str { match x { CXType_Invalid => "Invalid", @@ -1117,7 +1298,7 @@ pub fn type_to_str(x: Enum_CXTypeKind) -> &'static str { } } -// Debug +/// Dump the Clang AST to stdout for debugging purposes. pub fn ast_dump(c: &Cursor, depth: isize)-> Enum_CXVisitorResult { fn print_indent(depth: isize, s: &str) { let mut i = 0; @@ -21,6 +21,8 @@ // constant. #![allow(non_upper_case_globals)] +#[macro_use] +extern crate cfg_if; extern crate syntex_syntax as syntax; extern crate aster; extern crate quasi; @@ -32,11 +34,30 @@ extern crate log; #[macro_use] extern crate lazy_static; +// A macro to declare an internal module for which we *must* provide +// documentation for. If we are building with the "_docs" feature, then the +// module is declared public, and our `#![deny(missing_docs)]` pragma applies to +// it. This feature is used in CI, so we won't let anything slip by +// undocumented. Normal builds, however, will leave the module private, so that +// we don't expose internals to library consumers. +macro_rules! doc_mod { + ($m:ident) => { + cfg_if! { + if #[cfg(feature = "_docs")] { + pub mod $m; + } else { + mod $m; + } + } + }; +} + mod clangll; -mod clang; +doc_mod!(clang); mod ir; mod parse; mod regex_set; + mod codegen { include!(concat!(env!("OUT_DIR"), "/codegen.rs")); } |