summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-10-26 17:58:50 -0500
committerGitHub <noreply@github.com>2016-10-26 17:58:50 -0500
commite72e466deca59d1ab26036b96731bb4114d915ba (patch)
tree1bb2b1b754c20adff0e0d4fcc74c6226c43d2f01
parent818b29113d9fa6fb867fc08db587ae8ec75579fb (diff)
parent85f1a3fe9cd89126394604a0b5c4c64f793d4b3a (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.yml1
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--Cargo.toml3
-rwxr-xr-x[-rw-r--r--]src/clang.rs299
-rwxr-xr-xsrc/lib.rs23
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"/>
diff --git a/Cargo.toml b/Cargo.toml
index dbbaf4a7..65a8033b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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;
diff --git a/src/lib.rs b/src/lib.rs
index 4a5e8076..29369d41 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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"));
}