summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/comment.rs94
-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.rs6
-rw-r--r--src/ir/mod.rs1
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 3564c6e8..540dd791 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;
@@ -1001,7 +1002,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();
@@ -1207,7 +1208,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 d703e53d..ae67015c 100644
--- a/src/ir/mod.rs
+++ b/src/ir/mod.rs
@@ -5,6 +5,7 @@
pub mod annotations;
pub mod comp;
+pub mod comment;
pub mod context;
pub mod derive;
pub mod dot;