summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-07-10 15:16:14 -0700
committerGitHub <noreply@github.com>2017-07-10 15:16:14 -0700
commita00db0446f7296891c2c78bd19cdbff825e1a18f (patch)
tree3ec07ef83d22ceb36d87c626cf64c324949172a7
parent02afb5b4b1b1e5d49743d6529bce6871918a49cb (diff)
parent96304f90a4ce8c93f6ae39ee249fd72ab34bcfa4 (diff)
Auto merge of #799 - emilio:comment-indent, r=fitzgen
codegen: Make comments indentation-aware. This commit moves comment processing to a central place (well, two, because of field docs, but that's fine). Also, it makes comments indentation aware, so multiline comments don't appear garbled. Finally, it also fixes an out-of-bounds panic when processing an empty multiline comment.
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/codegen/helpers.rs4
-rw-r--r--src/codegen/mod.rs55
-rw-r--r--src/ir/comment.rs64
-rw-r--r--src/ir/comp.rs3
-rw-r--r--src/ir/enum_ty.rs3
-rw-r--r--src/ir/function.rs3
-rw-r--r--src/ir/item.rs37
-rw-r--r--tests/expectations/tests/comment-indent.rs114
-rw-r--r--tests/expectations/tests/layout_eth_conf.rs26
-rw-r--r--tests/expectations/tests/layout_mbuf.rs2
-rw-r--r--tests/headers/comment-indent.hpp47
13 files changed, 281 insertions, 81 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5daefa20..1615200e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
[root]
name = "bindgen"
-version = "0.26.3"
+version = "0.27.0"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index 5fbe1a26..06772302 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@ name = "bindgen"
readme = "README.md"
repository = "https://github.com/servo/rust-bindgen"
documentation = "https://docs.rs/bindgen"
-version = "0.26.3"
+version = "0.27.0"
build = "build.rs"
exclude = [
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
index eb843a65..4a64f799 100644
--- a/src/codegen/helpers.rs
+++ b/src/codegen/helpers.rs
@@ -30,8 +30,8 @@ pub mod attributes {
aster::AstBuilder::new().attr().word("inline")
}
- pub fn doc(comment: &str) -> ast::Attribute {
- aster::AstBuilder::new().attr().doc(comment)
+ pub fn doc(comment: String) -> ast::Attribute {
+ aster::AstBuilder::new().attr().doc(&*comment)
}
pub fn link_name(name: &str) -> ast::Attribute {
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 0621ea62..6f2bf96b 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -11,14 +11,14 @@ use aster::struct_field::StructFieldBuilder;
use ir::annotations::FieldAccessorKind;
use ir::comp::{Base, BitfieldUnit, Bitfield, CompInfo, CompKind, Field,
FieldData, FieldMethods, Method, MethodKind};
+use ir::comment;
use ir::context::{BindgenContext, ItemId};
use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
use ir::int::IntKind;
-use ir::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalName,
- ItemCanonicalPath, ItemSet};
+use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath, ItemSet};
use ir::item_kind::ItemKind;
use ir::layout::Layout;
use ir::module::Module;
@@ -42,23 +42,13 @@ use syntax::ptr::P;
// Name of type defined in constified enum module
pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type";
-fn root_import_depth(ctx: &BindgenContext, item: &Item) -> usize {
- if !ctx.options().enable_cxx_namespaces {
- return 0;
- }
-
- item.ancestors(ctx)
- .filter(|id| ctx.resolve_item(*id).is_module())
- .fold(1, |i, _| i + 1)
-}
-
fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec<ast::Ident> {
let mut path = vec![ctx.rust_ident_raw("self")];
if ctx.options().enable_cxx_namespaces {
let super_ = ctx.rust_ident_raw("super");
- for _ in 0..root_import_depth(ctx, item) {
+ for _ in 0..item.codegen_depth(ctx) {
path.push(super_.clone());
}
}
@@ -616,10 +606,8 @@ impl CodeGenerator for Type {
let rust_name = ctx.rust_ident(&name);
let mut typedef = aster::AstBuilder::new().item().pub_();
- if ctx.options().generate_comments {
- if let Some(comment) = item.comment() {
- typedef = typedef.attr().doc(comment);
- }
+ if let Some(comment) = item.comment(ctx) {
+ typedef = typedef.with_attr(attributes::doc(comment));
}
// We prefer using `pub use` over `pub type` because of:
@@ -839,6 +827,7 @@ trait FieldCodegen<'a> {
fn codegen<F, M>(&self,
ctx: &BindgenContext,
fields_should_be_private: bool,
+ codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
anon_field_names: &mut AnonFieldNames,
@@ -857,6 +846,7 @@ impl<'a> FieldCodegen<'a> for Field {
fn codegen<F, M>(&self,
ctx: &BindgenContext,
fields_should_be_private: bool,
+ codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
anon_field_names: &mut AnonFieldNames,
@@ -872,6 +862,7 @@ impl<'a> FieldCodegen<'a> for Field {
Field::DataMember(ref data) => {
data.codegen(ctx,
fields_should_be_private,
+ codegen_depth,
accessor_kind,
parent,
anon_field_names,
@@ -884,6 +875,7 @@ impl<'a> FieldCodegen<'a> for Field {
Field::Bitfields(ref unit) => {
unit.codegen(ctx,
fields_should_be_private,
+ codegen_depth,
accessor_kind,
parent,
anon_field_names,
@@ -903,6 +895,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
fn codegen<F, M>(&self,
ctx: &BindgenContext,
fields_should_be_private: bool,
+ codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
anon_field_names: &mut AnonFieldNames,
@@ -945,8 +938,9 @@ impl<'a> FieldCodegen<'a> for FieldData {
let mut attrs = vec![];
if ctx.options().generate_comments {
- if let Some(comment) = self.comment() {
- attrs.push(attributes::doc(comment));
+ if let Some(raw_comment) = self.comment() {
+ let comment = comment::preprocess(raw_comment, codegen_depth + 1);
+ attrs.push(attributes::doc(comment))
}
}
@@ -1153,6 +1147,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
fn codegen<F, M>(&self,
ctx: &BindgenContext,
fields_should_be_private: bool,
+ codegen_depth: usize,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
anon_field_names: &mut AnonFieldNames,
@@ -1197,6 +1192,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
for bf in self.bitfields() {
bf.codegen(ctx,
fields_should_be_private,
+ codegen_depth,
accessor_kind,
parent,
anon_field_names,
@@ -1277,6 +1273,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
fn codegen<F, M>(&self,
ctx: &BindgenContext,
_fields_should_be_private: bool,
+ _codegen_depth: usize,
_accessor_kind: FieldAccessorKind,
parent: &CompInfo,
_anon_field_names: &mut AnonFieldNames,
@@ -1409,10 +1406,8 @@ impl CodeGenerator for CompInfo {
let mut attributes = vec![];
let mut needs_clone_impl = false;
let mut needs_default_impl = false;
- if ctx.options().generate_comments {
- if let Some(comment) = item.comment() {
- attributes.push(attributes::doc(comment));
- }
+ if let Some(comment) = item.comment(ctx) {
+ attributes.push(attributes::doc(comment));
}
if self.packed() {
attributes.push(attributes::repr_list(&["C", "packed"]));
@@ -1545,9 +1540,11 @@ impl CodeGenerator for CompInfo {
let mut methods = vec![];
let mut anon_field_names = AnonFieldNames::default();
+ let codegen_depth = item.codegen_depth(ctx);
for field in self.fields() {
field.codegen(ctx,
fields_should_be_private,
+ codegen_depth,
struct_accessor_kind,
self,
&mut anon_field_names,
@@ -2367,10 +2364,8 @@ impl CodeGenerator for Enum {
builder = builder.with_attr(attributes::repr("C"));
}
- if ctx.options().generate_comments {
- if let Some(comment) = item.comment() {
- builder = builder.with_attr(attributes::doc(comment));
- }
+ if let Some(comment) = item.comment(ctx) {
+ builder = builder.with_attr(attributes::doc(comment));
}
if !is_constified_enum {
@@ -3069,10 +3064,8 @@ impl CodeGenerator for Function {
let mut attributes = vec![];
- if ctx.options().generate_comments {
- if let Some(comment) = item.comment() {
- attributes.push(attributes::doc(comment));
- }
+ if let Some(comment) = item.comment(ctx) {
+ attributes.push(attributes::doc(comment));
}
if let Some(mangled) = mangled_name {
diff --git a/src/ir/comment.rs b/src/ir/comment.rs
index 15237b91..f772482e 100644
--- a/src/ir/comment.rs
+++ b/src/ir/comment.rs
@@ -1,5 +1,7 @@
//! Utilities for manipulating C/C++ comments.
+use std::iter;
+
/// The type of a comment.
#[derive(Debug, PartialEq, Eq)]
enum Kind {
@@ -10,11 +12,12 @@ enum Kind {
/// entire block ends with `*/`.
MultiLine,
}
+
/// Preprocesses a C/C++ comment so that it is a valid Rust comment.
-pub fn preprocess(comment: String) -> String {
+pub fn preprocess(comment: &str, indent: usize) -> String {
match self::kind(&comment) {
- Some(Kind::SingleLines) => preprocess_single_lines(&comment),
- Some(Kind::MultiLine) => preprocess_multi_line(&comment),
+ Some(Kind::SingleLines) => preprocess_single_lines(comment, indent),
+ Some(Kind::MultiLine) => preprocess_multi_line(comment, indent),
None => comment.to_owned(),
}
}
@@ -30,38 +33,59 @@ fn kind(comment: &str) -> Option<Kind> {
}
}
+fn make_indent(indent: usize) -> String {
+ const RUST_INDENTATION: usize = 4;
+
+ iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
+}
+
/// Preprocesses mulitple single line comments.
///
/// Handles lines starting with both `//` and `///`.
-fn preprocess_single_lines(comment: &str) -> String {
- assert!(comment.starts_with("//"), "comment is not single line");
+fn preprocess_single_lines(comment: &str, indent: usize) -> String {
+ debug_assert!(comment.starts_with("//"), "comment is not single line");
+ let indent = make_indent(indent);
+ let mut is_first = true;
let lines: Vec<_> = comment.lines()
- .map(|l| l.trim_left_matches('/').trim())
- .map(|l| format!("/// {}", l).trim().to_owned())
- .collect();
+ .map(|l| l.trim_left_matches('/').trim())
+ .map(|l| {
+ let indent = if is_first { "" } else { &*indent };
+ is_first = false;
+ let maybe_space = if l.is_empty() { "" } else { " " };
+ format!("{}///{}{}", indent, maybe_space, l)
+ })
+ .collect();
lines.join("\n")
}
-fn preprocess_multi_line(comment: &str) -> String {
+fn preprocess_multi_line(comment: &str, indent: usize) -> String {
let comment = comment.trim_left_matches('/')
- .trim_left_matches("*")
- .trim_left_matches("!")
+ .trim_left_matches('*')
+ .trim_left_matches('!')
.trim_right_matches('/')
.trim_right_matches('*')
.trim();
+ let indent = make_indent(indent);
// Strip any potential `*` characters preceding each line.
+ let mut is_first = true;
let mut lines: Vec<_> = comment.lines()
.map(|line| line.trim().trim_left_matches('*').trim())
.skip_while(|line| line.is_empty()) // Skip the first empty lines.
- .map(|line| format!("/// {}", line).trim().to_owned())
+ .map(|line| {
+ let indent = if is_first { "" } else { &*indent };
+ is_first = false;
+ let maybe_space = if line.is_empty() { "" } else { " " };
+ format!("{}///{}{}", indent, maybe_space, line)
+ })
.collect();
- // Remove the trailing `*/`.
- let last_idx = lines.len() - 1;
- if lines[last_idx].is_empty() {
- lines.remove(last_idx);
+ // Remove the trailing line corresponding to the `*/`.
+ let last_line_is_empty = lines.last().map_or(false, |l| l.is_empty());
+
+ if last_line_is_empty {
+ lines.pop();
}
lines.join("\n")
@@ -79,16 +103,16 @@ mod test {
#[test]
fn processes_single_lines_correctly() {
- assert_eq!(preprocess("/// hello".to_owned()), "/// hello");
- assert_eq!(preprocess("// hello".to_owned()), "/// hello");
+ assert_eq!(preprocess("/// hello", 0), "/// hello");
+ assert_eq!(preprocess("// hello", 0), "/// hello");
}
#[test]
fn processes_multi_lines_correctly() {
- assert_eq!(preprocess("/** hello \n * world \n * foo \n */".to_owned()),
+ assert_eq!(preprocess("/** hello \n * world \n * foo \n */", 0),
"/// hello\n/// world\n/// foo");
- assert_eq!(preprocess("/**\nhello\n*world\n*foo\n*/".to_owned()),
+ assert_eq!(preprocess("/**\nhello\n*world\n*foo\n*/", 0),
"/// hello\n/// world\n/// foo");
}
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 4854949f..6dfc9980 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -1,7 +1,6 @@
//! Compound types (unions and structs) in our intermediate representation.
use super::annotations::Annotations;
-use super::comment;
use super::context::{BindgenContext, ItemId};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
use super::dot::DotAttributes;
@@ -1102,7 +1101,7 @@ impl CompInfo {
Some(potential_id),
ctx);
- let comment = cur.raw_comment().map(comment::preprocess);
+ let comment = cur.raw_comment();
let annotations = Annotations::new(&cur);
let name = cur.spelling();
let is_mutable = cursor.is_mutable_field();
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index 731961a6..38de01d9 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -1,6 +1,5 @@
//! Intermediate representation for C/C++ enumerations.
-use super::comment;
use super::context::{BindgenContext, ItemId};
use super::item::Item;
use super::ty::TypeKind;
@@ -114,7 +113,7 @@ impl Enum {
})
});
- let comment = cursor.raw_comment().map(comment::preprocess);
+ let comment = cursor.raw_comment();
variants.push(EnumVariant::new(name,
comment,
val,
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 299bd65c..9865997d 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -1,6 +1,5 @@
//! Intermediate representation for C/C++ functions and methods.
-use super::comment;
use super::context::{BindgenContext, ItemId};
use super::dot::DotAttributes;
use super::item::Item;
@@ -406,7 +405,7 @@ impl ClangSubItemParser for Function {
mangled_name = None;
}
- let comment = cursor.raw_comment().map(comment::preprocess);
+ let comment = cursor.raw_comment();
let function = Self::new(name, mangled_name, sig, comment);
Ok(ParseResult::New(function, Some(cursor)))
diff --git a/src/ir/item.rs b/src/ir/item.rs
index cd721c61..e65b7a99 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -480,9 +480,35 @@ impl Item {
self.parent_id = id;
}
- /// Get this `Item`'s comment, if it has any.
- pub fn comment(&self) -> Option<&str> {
- self.comment.as_ref().map(|c| &**c)
+ /// Returns the depth this item is indented to.
+ ///
+ /// FIXME(emilio): This may need fixes for the enums within modules stuff.
+ pub fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
+ if !ctx.options().enable_cxx_namespaces {
+ return 0;
+ }
+
+ self.ancestors(ctx)
+ .filter(|id| {
+ ctx.resolve_item(*id).as_module().map_or(false, |module| {
+ !module.is_inline() ||
+ ctx.options().conservative_inline_namespaces
+ })
+ })
+ .count() + 1
+ }
+
+
+ /// Get this `Item`'s comment, if it has any, already preprocessed and with
+ /// the right indentation.
+ pub fn comment(&self, ctx: &BindgenContext) -> Option<String> {
+ if !ctx.options().generate_comments {
+ return None;
+ }
+
+ self.comment.as_ref().map(|comment| {
+ comment::preprocess(comment, self.codegen_depth(ctx))
+ })
}
/// What kind of item is this?
@@ -1012,7 +1038,7 @@ impl ClangItemParser for Item {
return Err(ParseError::Continue);
}
- let comment = cursor.raw_comment().map(comment::preprocess);
+ let comment = cursor.raw_comment();
let annotations = Annotations::new(&cursor);
let current_module = ctx.current_module();
@@ -1218,8 +1244,7 @@ impl ClangItemParser for Item {
};
let comment = decl.raw_comment()
- .or_else(|| location.raw_comment())
- .map(comment::preprocess);
+ .or_else(|| location.raw_comment());
let annotations = Annotations::new(&decl)
.or_else(|| Annotations::new(&location));
diff --git a/tests/expectations/tests/comment-indent.rs b/tests/expectations/tests/comment-indent.rs
new file mode 100644
index 00000000..127c1b0e
--- /dev/null
+++ b/tests/expectations/tests/comment-indent.rs
@@ -0,0 +1,114 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
+pub mod root {
+ #[allow(unused_imports)]
+ use self::super::root;
+ /// This is a multi-line doc comment.
+ ///
+ /// This class is really really interesting, look!
+ #[repr(C)]
+ #[derive(Debug, Default, Copy)]
+ pub struct Foo {
+ pub _address: u8,
+ }
+ /// This nested class is also a multi-line doc comment.
+ ///
+ /// This class is not so interesting, but worth a bit of docs too!
+ #[repr(C)]
+ #[derive(Debug, Default, Copy)]
+ pub struct Foo_Bar {
+ pub _address: u8,
+ }
+ #[test]
+ fn bindgen_test_layout_Foo_Bar() {
+ assert_eq!(::std::mem::size_of::<Foo_Bar>() , 1usize , concat ! (
+ "Size of: " , stringify ! ( Foo_Bar ) ));
+ assert_eq! (::std::mem::align_of::<Foo_Bar>() , 1usize , concat ! (
+ "Alignment of " , stringify ! ( Foo_Bar ) ));
+ }
+ impl Clone for Foo_Bar {
+ fn clone(&self) -> Self { *self }
+ }
+ #[test]
+ fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
+ "Size of: " , stringify ! ( Foo ) ));
+ assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
+ "Alignment of " , stringify ! ( Foo ) ));
+ }
+ impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+ }
+ pub mod test {
+ #[allow(unused_imports)]
+ use self::super::super::root;
+ /// I'm in a namespace, and thus I may be on a rust module, most of the time.
+ /// My documentation is pretty extensive, I guess.
+ #[repr(C)]
+ #[derive(Debug, Default, Copy)]
+ pub struct Baz {
+ /// This member is plain awesome, just amazing.
+ ///
+ /// It also has super-extensive docs, with even a nice ascii-art diagram.
+ ///
+ /// +------+ +-------+
+ /// | foo | ----> | bar |
+ /// +------+ +-------+
+ pub member: ::std::os::raw::c_int,
+ }
+ #[test]
+ fn bindgen_test_layout_Baz() {
+ assert_eq!(::std::mem::size_of::<Baz>() , 4usize , concat ! (
+ "Size of: " , stringify ! ( Baz ) ));
+ assert_eq! (::std::mem::align_of::<Baz>() , 4usize , concat ! (
+ "Alignment of " , stringify ! ( Baz ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const Baz ) ) . member as * const _ as
+ usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( Baz ) , "::" ,
+ stringify ! ( member ) ));
+ }
+ impl Clone for Baz {
+ fn clone(&self) -> Self { *self }
+ }
+ /// I'm in an inline namespace, and as such I shouldn't get generated inside
+ /// a rust module, except when the relevant option is specified. Also, this
+ /// comment shouldn't be misaligned.
+ #[repr(C)]
+ #[derive(Debug, Default, Copy)]
+ pub struct InInlineNS {
+ pub _address: u8,
+ }
+ #[test]
+ fn bindgen_test_layout_InInlineNS() {
+ assert_eq!(::std::mem::size_of::<InInlineNS>() , 1usize , concat !
+ ( "Size of: " , stringify ! ( InInlineNS ) ));
+ assert_eq! (::std::mem::align_of::<InInlineNS>() , 1usize , concat
+ ! ( "Alignment of " , stringify ! ( InInlineNS ) ));
+ }
+ impl Clone for InInlineNS {
+ fn clone(&self) -> Self { *self }
+ }
+
+ #[repr(C)]
+ #[derive(Debug, Default, Copy)]
+ pub struct Bazz {
+ pub _address: u8,
+ }
+ #[test]
+ fn bindgen_test_layout_Bazz() {
+ assert_eq!(::std::mem::size_of::<Bazz>() , 1usize , concat ! (
+ "Size of: " , stringify ! ( Bazz ) ));
+ assert_eq! (::std::mem::align_of::<Bazz>() , 1usize , concat ! (
+ "Alignment of " , stringify ! ( Bazz ) ));
+ }
+ impl Clone for Bazz {
+ fn clone(&self) -> Self { *self }
+ }
+ }
+}
diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs
index f5cafbfc..cc32c3cc 100644
--- a/tests/expectations/tests/layout_eth_conf.rs
+++ b/tests/expectations/tests/layout_eth_conf.rs
@@ -1182,12 +1182,12 @@ pub struct rte_eth_fdir_masks {
/// Bit mask for L4 destination port in big endian.
pub dst_port_mask: u16,
/// 6 bit mask for proper 6 bytes of Mac address, bit 0 matches the
-/// first byte on the wire
+ /// first byte on the wire
pub mac_addr_byte_mask: u8,
/// Bit mask for tunnel ID in big endian.
pub tunnel_id_mask: u32,
/// < 1 - Match tunnel type,
-/// 0 - Ignore tunnel type.
+ /// 0 - Ignore tunnel type.
pub tunnel_type_mask: u8,
}
#[test]
@@ -1460,29 +1460,29 @@ impl Clone for rte_intr_conf {
#[repr(C)]
pub struct rte_eth_conf {
/// < bitmap of ETH_LINK_SPEED_XXX of speeds to be
-/// used. ETH_LINK_SPEED_FIXED disables link
-/// autonegotiation, and a unique speed shall be
-/// set. Otherwise, the bitmap defines the set of
-/// speeds to be advertised. If the special value
-/// ETH_LINK_SPEED_AUTONEG (0) is used, all speeds
-/// supported are advertised.
+ /// used. ETH_LINK_SPEED_FIXED disables link
+ /// autonegotiation, and a unique speed shall be
+ /// set. Otherwise, the bitmap defines the set of
+ /// speeds to be advertised. If the special value
+ /// ETH_LINK_SPEED_AUTONEG (0) is used, all speeds
+ /// supported are advertised.
pub link_speeds: u32,
/// < Port RX configuration.
pub rxmode: rte_eth_rxmode,
/// < Port TX configuration.
pub txmode: rte_eth_txmode,
/// < Loopback operation mode. By default the value
-/// is 0, meaning the loopback mode is disabled.
-/// Read the datasheet of given ethernet controller
-/// for details. The possible values of this field
-/// are defined in implementation of each driver.
+ /// is 0, meaning the loopback mode is disabled.
+ /// Read the datasheet of given ethernet controller
+ /// for details. The possible values of this field
+ /// are defined in implementation of each driver.
pub lpbk_mode: u32,
/// < Port RX filtering configuration (union).
pub rx_adv_conf: rte_eth_conf__bindgen_ty_1,
/// < Port TX DCB configuration (union).
pub tx_adv_conf: rte_eth_conf__bindgen_ty_2,
/// Currently,Priority Flow Control(PFC) are supported,if DCB with PFC
-/// is needed,and the variable must be set ETH_DCB_PFC_SUPPORT.
+ /// is needed,and the variable must be set ETH_DCB_PFC_SUPPORT.
pub dcb_capability_en: u32,
/// < FDIR configuration.
pub fdir_conf: rte_fdir_conf,
diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs
index e527ac92..29779b3c 100644
--- a/tests/expectations/tests/layout_mbuf.rs
+++ b/tests/expectations/tests/layout_mbuf.rs
@@ -98,7 +98,7 @@ pub struct rte_mbuf {
pub next: *mut rte_mbuf,
pub __bindgen_anon_4: rte_mbuf__bindgen_ty_5,
/// Size of the application private data. In case of an indirect
-/// mbuf, it stores the direct mbuf private data size.
+ /// mbuf, it stores the direct mbuf private data size.
pub priv_size: u16,
/// Timesync flags for use with IEEE1588.
pub timesync: u16,
diff --git a/tests/headers/comment-indent.hpp b/tests/headers/comment-indent.hpp
new file mode 100644
index 00000000..96c13fcc
--- /dev/null
+++ b/tests/headers/comment-indent.hpp
@@ -0,0 +1,47 @@
+// bindgen-flags: --enable-cxx-namespaces
+
+/**
+ * This is a multi-line doc comment.
+ *
+ * This class is really really interesting, look!
+ */
+class Foo {
+ /**
+ * This nested class is also a multi-line doc comment.
+ *
+ * This class is not so interesting, but worth a bit of docs too!
+ */
+ class Bar { };
+};
+
+namespace test {
+ /**
+ * I'm in a namespace, and thus I may be on a rust module, most of the time.
+ * My documentation is pretty extensive, I guess.
+ */
+ class Baz {
+ /**
+ * This member is plain awesome, just amazing.
+ *
+ * It also has super-extensive docs, with even a nice ascii-art diagram.
+ *
+ * +------+ +-------+
+ * | foo | ----> | bar |
+ * +------+ +-------+
+ */
+ int member;
+ };
+
+ inline namespace foobiedoobie {
+ /**
+ * I'm in an inline namespace, and as such I shouldn't get generated inside
+ * a rust module, except when the relevant option is specified. Also, this
+ * comment shouldn't be misaligned.
+ */
+ class InInlineNS {
+ };
+ }
+
+ /**/
+ class Bazz {};
+}