Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/noirc_frontend/src/hir/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ impl<'context, 'string> ItemPrinter<'context, 'string> {
self.push('\n');
self.write_indent();
}
self.push_str(" * ");
self.push_str(line);
}

Expand All @@ -180,7 +181,7 @@ impl<'context, 'string> ItemPrinter<'context, 'string> {

self.push_str("*/");
} else {
self.push_str("///");
self.push_str("/// ");
self.push_str(comment);
}
self.push('\n');
Expand Down
95 changes: 87 additions & 8 deletions compiler/noirc_frontend/src/parser/parser/doc_comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ impl Parser<'_> {

fn parse_inner_doc_comment(&mut self) -> Option<String> {
self.eat_kind(TokenKind::InnerDocComment).map(|token| match token.into_token() {
Token::LineComment(comment, Some(DocStyle::Inner))
| Token::BlockComment(comment, Some(DocStyle::Inner)) => comment,
Token::LineComment(comment, Some(DocStyle::Inner)) => fix_line_comment(comment),
Token::BlockComment(comment, Some(DocStyle::Inner)) => fix_block_comment(comment),
_ => unreachable!(),
})
}
Expand All @@ -27,8 +27,8 @@ impl Parser<'_> {
/// OuterDocComment = outer_doc_comment
pub(super) fn parse_outer_doc_comment(&mut self) -> Option<String> {
self.eat_kind(TokenKind::OuterDocComment).map(|token| match token.into_token() {
Token::LineComment(comment, Some(DocStyle::Outer))
| Token::BlockComment(comment, Some(DocStyle::Outer)) => comment,
Token::LineComment(comment, Some(DocStyle::Outer)) => fix_line_comment(comment),
Token::BlockComment(comment, Some(DocStyle::Outer)) => fix_block_comment(comment),
_ => unreachable!(),
})
}
Expand All @@ -53,6 +53,45 @@ impl Parser<'_> {
}
}

/// Strips leading ' ' from a line comment.
fn fix_line_comment(comment: String) -> String {
Comment thread
asterite marked this conversation as resolved.
if let Some(comment) = comment.strip_prefix(' ') { comment.to_string() } else { comment }
}

/// Strips leading '*' from a block comment if all non-empty lines have it.
fn fix_block_comment(comment: String) -> String {
let all_stars = comment.lines().enumerate().all(|(index, line)| {
if index == 0 || line.trim().is_empty() {
// The first line never has a star. Then we ignore empty lines.
true
} else {
line.trim_start().starts_with('*')
}
});

let mut fixed_comment = String::new();
for (index, line) in comment.lines().enumerate() {
if index > 0 {
fixed_comment.push('\n');
}

if all_stars {
if let Some(line) = line.trim_start().strip_prefix("*") {
fixed_comment.push_str(line.strip_prefix(' ').unwrap_or(line));
continue;
}
}

if let Some(line) = line.strip_prefix(' ') {
fixed_comment.push_str(line);
continue;
}

fixed_comment.push_str(line);
}
fixed_comment.trim().to_string()
}

#[cfg(test)]
mod tests {
use crate::parser::{Parser, parser::tests::expect_no_errors};
Expand All @@ -64,8 +103,28 @@ mod tests {
let comments = parser.parse_inner_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 2);
assert_eq!(comments[0], " Hello");
assert_eq!(comments[1], " World");
assert_eq!(comments[0], "Hello");
assert_eq!(comments[1], "World");
}

#[test]
fn parses_inner_block_doc_comments() {
let src = "/*! Hello\n * World\n *\n * !\n*/";
let mut parser = Parser::for_str_with_dummy_file(src);
let comments = parser.parse_inner_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 1);
assert_eq!(comments[0], "Hello\nWorld\n\n!");
}

#[test]
fn parses_inner_block_doc_comments_with_indentation() {
let src = " /*! Hello\n * World\n *\n * !\n */";
let mut parser = Parser::for_str_with_dummy_file(src);
let comments = parser.parse_inner_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 1);
assert_eq!(comments[0], "Hello\nWorld\n\n!");
}

#[test]
Expand All @@ -75,7 +134,27 @@ mod tests {
let comments = parser.parse_outer_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 2);
assert_eq!(comments[0], " Hello");
assert_eq!(comments[1], " World");
assert_eq!(comments[0], "Hello");
assert_eq!(comments[1], "World");
}

#[test]
fn parses_outer_block_doc_comments() {
let src = "/** Hello\n * World\n *\n * !\n*/";
let mut parser = Parser::for_str_with_dummy_file(src);
let comments = parser.parse_outer_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 1);
assert_eq!(comments[0], "Hello\nWorld\n\n!");
}

#[test]
fn parses_outer_block_doc_comments_not_every_line_has_stars() {
let src = "/** Hello\n * World\n Oops\n * !\n*/";
let mut parser = Parser::for_str_with_dummy_file(src);
let comments = parser.parse_outer_doc_comments();
expect_no_errors(&parser.errors);
assert_eq!(comments.len(), 1);
assert_eq!(comments[0], "Hello\n* World\nOops\n* !");
}
}
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/parser/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ mod tests {
let item = &module.items[0];
assert_eq!(
item.doc_comments,
vec![" One".to_string(), " Two".to_string(), " Three".to_string(),]
vec!["One".to_string(), "Two".to_string(), "Three".to_string(),]
);
let ItemKind::Function(func) = &item.kind else {
panic!("Expected function");
Expand Down
8 changes: 4 additions & 4 deletions tooling/lsp/src/requests/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ mod hover_tests {

---

Red, blue, etc."
Red, blue, etc."
));
}

Expand All @@ -463,7 +463,7 @@ mod hover_tests {

---

Red, blue, etc."
Red, blue, etc."
));
}

Expand All @@ -478,7 +478,7 @@ mod hover_tests {

---

Like a tomato"
Like a tomato"
));
}

Expand All @@ -493,7 +493,7 @@ mod hover_tests {

---

Like a tomato"
Like a tomato"
));
}

Expand Down
Loading