forked from rust-lang/rust-bindgen
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Intelligently convert C/C++ comments to Rust
With this change, we can correctly parse C++ block comments. ``` /** * Does a thing * * More documentation. This test does something * useful. */ ``` into ``` /// Does a thing /// /// More documentation. This test does something /// useful. ``` Fixes rust-lang#426.
- Loading branch information
1 parent
78e7546
commit 37f5d85
Showing
25 changed files
with
464 additions
and
458 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/// 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, | ||
} | ||
|
||
/// Checks if a comment should be emitted as a Rust doc comment. | ||
pub fn is_doc(comment: &str) -> bool { | ||
self::kind(comment).is_some() | ||
} | ||
|
||
/// 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 a C/C++ comment so that it is a valid Rust comment. | ||
pub fn preprocess(comment: &str) -> String { | ||
match self::kind(comment) { | ||
Some(Kind::SingleLines) => preprocess_single_lines(comment), | ||
Some(Kind::MultiLine) => preprocess_multi_line(comment), | ||
None => panic!("comment is not a doc comment"), | ||
} | ||
} | ||
|
||
fn preprocess_single_lines(comment: &str) -> String { | ||
assert!(comment.starts_with("///"), "comment is not single line"); | ||
// We don't need to amend the comment because each line already | ||
// starts with `///`. | ||
comment.to_owned() | ||
} | ||
|
||
fn preprocess_multi_line(comment: &str) -> String { | ||
let comment = comment.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)) | ||
.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 ignores_non_doc_comments() { | ||
assert_eq!(kind("// hello"), None); | ||
} | ||
|
||
#[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"), "/// hello"); | ||
} | ||
|
||
#[test] | ||
fn processes_multi_lines_correctly() { | ||
assert_eq!(preprocess("/** hello \n * world \n * foo \n */"), | ||
"/// hello\n/// world\n/// foo"); | ||
|
||
assert_eq!(preprocess("/**\nhello\n*world\n*foo\n*/"), | ||
"/// hello\n/// world\n/// foo"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.