diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/comment.rs | 94 | ||||
-rw-r--r-- | src/ir/comp.rs | 3 | ||||
-rw-r--r-- | src/ir/enum_ty.rs | 3 | ||||
-rw-r--r-- | src/ir/function.rs | 3 | ||||
-rw-r--r-- | src/ir/item.rs | 6 | ||||
-rw-r--r-- | src/ir/mod.rs | 1 |
6 files changed, 105 insertions, 5 deletions
diff --git a/src/ir/comment.rs b/src/ir/comment.rs new file mode 100644 index 00000000..15237b91 --- /dev/null +++ b/src/ir/comment.rs @@ -0,0 +1,94 @@ +//! Utilities for manipulating C/C++ comments. + +/// The type of a comment. +#[derive(Debug, PartialEq, Eq)] +enum Kind { + /// A `///` comment, or something of the like. + /// All lines in a comment should start with the same symbol. + SingleLines, + /// A `/**` comment, where each other line can start with `*` and the + /// entire block ends with `*/`. + MultiLine, +} +/// Preprocesses a C/C++ comment so that it is a valid Rust comment. +pub fn preprocess(comment: String) -> String { + match self::kind(&comment) { + Some(Kind::SingleLines) => preprocess_single_lines(&comment), + Some(Kind::MultiLine) => preprocess_multi_line(&comment), + None => comment.to_owned(), + } +} + +/// Gets the kind of the doc comment, if it is one. +fn kind(comment: &str) -> Option<Kind> { + if comment.starts_with("/*") { + Some(Kind::MultiLine) + } else if comment.starts_with("//") { + Some(Kind::SingleLines) + } else { + None + } +} + +/// 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"); + + let lines: Vec<_> = comment.lines() + .map(|l| l.trim_left_matches('/').trim()) + .map(|l| format!("/// {}", l).trim().to_owned()) + .collect(); + lines.join("\n") +} + +fn preprocess_multi_line(comment: &str) -> String { + let comment = comment.trim_left_matches('/') + .trim_left_matches("*") + .trim_left_matches("!") + .trim_right_matches('/') + .trim_right_matches('*') + .trim(); + + // Strip any potential `*` characters preceding each line. + 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()) + .collect(); + + // Remove the trailing `*/`. + let last_idx = lines.len() - 1; + if lines[last_idx].is_empty() { + lines.remove(last_idx); + } + + lines.join("\n") +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn picks_up_single_and_multi_line_doc_comments() { + assert_eq!(kind("/// hello"), Some(Kind::SingleLines)); + assert_eq!(kind("/** world */"), Some(Kind::MultiLine)); + } + + #[test] + fn processes_single_lines_correctly() { + assert_eq!(preprocess("/// hello".to_owned()), "/// hello"); + assert_eq!(preprocess("// hello".to_owned()), "/// hello"); + } + + #[test] + fn processes_multi_lines_correctly() { + assert_eq!(preprocess("/** hello \n * world \n * foo \n */".to_owned()), + "/// hello\n/// world\n/// foo"); + + assert_eq!(preprocess("/**\nhello\n*world\n*foo\n*/".to_owned()), + "/// hello\n/// world\n/// foo"); + } +} diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 6dfc9980..4854949f 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1,6 +1,7 @@ //! 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; @@ -1101,7 +1102,7 @@ impl CompInfo { Some(potential_id), ctx); - let comment = cur.raw_comment(); + let comment = cur.raw_comment().map(comment::preprocess); 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 38de01d9..731961a6 100644 --- a/src/ir/enum_ty.rs +++ b/src/ir/enum_ty.rs @@ -1,5 +1,6 @@ //! Intermediate representation for C/C++ enumerations. +use super::comment; use super::context::{BindgenContext, ItemId}; use super::item::Item; use super::ty::TypeKind; @@ -113,7 +114,7 @@ impl Enum { }) }); - let comment = cursor.raw_comment(); + let comment = cursor.raw_comment().map(comment::preprocess); variants.push(EnumVariant::new(name, comment, val, diff --git a/src/ir/function.rs b/src/ir/function.rs index 9865997d..299bd65c 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -1,5 +1,6 @@ //! Intermediate representation for C/C++ functions and methods. +use super::comment; use super::context::{BindgenContext, ItemId}; use super::dot::DotAttributes; use super::item::Item; @@ -405,7 +406,7 @@ impl ClangSubItemParser for Function { mangled_name = None; } - let comment = cursor.raw_comment(); + let comment = cursor.raw_comment().map(comment::preprocess); 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 cfda4953..cd721c61 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -2,6 +2,7 @@ use super::super::codegen::CONSTIFIED_ENUM_MODULE_REPR_NAME; use super::annotations::Annotations; +use super::comment; use super::context::{BindgenContext, ItemId, PartialType}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::dot::DotAttributes; @@ -1011,7 +1012,7 @@ impl ClangItemParser for Item { return Err(ParseError::Continue); } - let comment = cursor.raw_comment(); + let comment = cursor.raw_comment().map(comment::preprocess); let annotations = Annotations::new(&cursor); let current_module = ctx.current_module(); @@ -1217,7 +1218,8 @@ impl ClangItemParser for Item { }; let comment = decl.raw_comment() - .or_else(|| location.raw_comment()); + .or_else(|| location.raw_comment()) + .map(comment::preprocess); let annotations = Annotations::new(&decl) .or_else(|| Annotations::new(&location)); diff --git a/src/ir/mod.rs b/src/ir/mod.rs index f28ca9cb..6d4d8a23 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -6,6 +6,7 @@ pub mod annotations; pub mod analysis; pub mod comp; +pub mod comment; pub mod context; pub mod derive; pub mod dot; |