diff options
| author | Gareth Daniel Smith <garethdanielsmith@gmail.com> | 2012-06-30 11:54:54 +0100 |
|---|---|---|
| committer | Gareth Daniel Smith <garethdanielsmith@gmail.com> | 2012-06-30 11:54:54 +0100 |
| commit | 0b653ab9539140bb04941de9a36c03cf10bfc28b (patch) | |
| tree | 491d1b3f128a281ffb3a12240e6858a919f5f3dd /src/libsyntax/parse/comments.rs | |
| parent | d7823de5e2bfc749c2fb4fcfe4d65d54b28e3a92 (diff) | |
| download | rust-0b653ab9539140bb04941de9a36c03cf10bfc28b.tar.gz rust-0b653ab9539140bb04941de9a36c03cf10bfc28b.zip | |
initial draft of fix for issue #2498:
1. make /// ... and //! ... and /** ... */ and /*! ... */ into sugar for #[doc = ...] attributes. 2. add a script in etc/ to help converting doc-attributes to doc-comments 3. add some functions to core::str to help with (1)
Diffstat (limited to 'src/libsyntax/parse/comments.rs')
| -rw-r--r-- | src/libsyntax/parse/comments.rs | 128 |
1 files changed, 115 insertions, 13 deletions
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index b6ab87ad1bc..7a6a9f0f3d7 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -8,6 +8,7 @@ export cmnt; export lit; export cmnt_style; export gather_comments_and_literals; +export is_doc_comment, doc_comment_style, strip_doc_comment_decoration; enum cmnt_style { isolated, // No code on either side of each line of the comment @@ -18,6 +19,81 @@ enum cmnt_style { type cmnt = {style: cmnt_style, lines: [str]/~, pos: uint}; +fn is_doc_comment(s: str) -> bool { + s.starts_with("///") || + s.starts_with("//!") || + s.starts_with("/**") || + s.starts_with("/*!") +} + +fn doc_comment_style(comment: str) -> ast::attr_style { + assert is_doc_comment(comment); + if comment.starts_with("//!") || comment.starts_with("/*!") { + ast::attr_inner + } else { + ast::attr_outer + } +} + +fn strip_doc_comment_decoration(comment: str) -> str { + + /// remove whitespace-only lines from the start/end of lines + fn vertical_trim(lines: [str]/~) -> [str]/~ { + let mut i = 0u, j = lines.len(); + while i < j && lines[i].trim().is_empty() { + i += 1u; + } + while j > i && lines[j - 1u].trim().is_empty() { + j -= 1u; + } + ret lines.slice(i, j); + } + + // drop leftmost columns that contain only values in chars + fn block_trim(lines: [str]/~, chars: str, max: option<uint>) -> [str]/~ { + + let mut i = max.get_default(uint::max_value); + for lines.each {|line| + if line.trim().is_empty() { + cont; + } + for line.each_chari {|j, c| + if j >= i { + break; + } + if !chars.contains_char(c) { + i = j; + break; + } + } + } + + ret lines.map {|line| + let chars = str::chars(line); + if i > chars.len() { + "" + } else { + str::from_chars(chars.slice(i, chars.len())) + } + }; + } + + if comment.starts_with("//") { + ret comment.slice(3u, comment.len()).trim(); + } + + if comment.starts_with("/*") { + let lines = str::lines_any(comment.slice(3u, comment.len() - 2u)); + let lines = vertical_trim(lines); + let lines = block_trim(lines, "\t ", none); + let lines = block_trim(lines, "*", some(1u)); + let lines = block_trim(lines, "\t ", none); + ret str::connect(lines, "\n"); + } + + fail "not a doc-comment: " + comment; +} + fn read_to_eol(rdr: string_reader) -> str { let mut val = ""; while rdr.curr != '\n' && !is_eof(rdr) { @@ -57,29 +133,41 @@ fn consume_whitespace_counting_blank_lines(rdr: string_reader, } } -fn read_shebang_comment(rdr: string_reader, code_to_the_left: bool) -> cmnt { + +fn read_shebang_comment(rdr: string_reader, code_to_the_left: bool, + &comments: [cmnt]/~) { #debug(">>> shebang comment"); let p = rdr.chpos; #debug("<<< shebang comment"); - ret {style: if code_to_the_left { trailing } else { isolated }, - lines: [read_one_line_comment(rdr)]/~, - pos: p}; + vec::push(comments, { + style: if code_to_the_left { trailing } else { isolated }, + lines: [read_one_line_comment(rdr)]/~, + pos: p + }); } -fn read_line_comments(rdr: string_reader, code_to_the_left: bool) -> cmnt { +fn read_line_comments(rdr: string_reader, code_to_the_left: bool, + &comments: [cmnt]/~) { #debug(">>> line comments"); let p = rdr.chpos; let mut lines: [str]/~ = []/~; while rdr.curr == '/' && nextch(rdr) == '/' { let line = read_one_line_comment(rdr); log(debug, line); + if is_doc_comment(line) { // doc-comments are not put in comments + break; + } vec::push(lines, line); consume_non_eol_whitespace(rdr); } #debug("<<< line comments"); - ret {style: if code_to_the_left { trailing } else { isolated }, - lines: lines, - pos: p}; + if !lines.is_empty() { + vec::push(comments, { + style: if code_to_the_left { trailing } else { isolated }, + lines: lines, + pos: p + }); + } } fn all_whitespace(s: str, begin: uint, end: uint) -> bool { @@ -101,13 +189,27 @@ fn trim_whitespace_prefix_and_push_line(&lines: [str]/~, vec::push(lines, s1); } -fn read_block_comment(rdr: string_reader, code_to_the_left: bool) -> cmnt { +fn read_block_comment(rdr: string_reader, code_to_the_left: bool, + &comments: [cmnt]/~) { #debug(">>> block comment"); let p = rdr.chpos; let mut lines: [str]/~ = []/~; let mut col: uint = rdr.col; bump(rdr); bump(rdr); + + // doc-comments are not really comments, they are attributes + if rdr.curr == '*' || rdr.curr == '!' { + while !(rdr.curr == '*' && nextch(rdr) == '/') && !is_eof(rdr) { + bump(rdr); + } + if !is_eof(rdr) { + bump(rdr); + bump(rdr); + } + ret; + } + let mut curr_line = "/*"; let mut level: int = 1; while level > 0 { @@ -143,7 +245,7 @@ fn read_block_comment(rdr: string_reader, code_to_the_left: bool) -> cmnt { style = mixed; } #debug("<<< block comment"); - ret {style: style, lines: lines, pos: p}; + vec::push(comments, {style: style, lines: lines, pos: p}); } fn peeking_at_comment(rdr: string_reader) -> bool { @@ -156,11 +258,11 @@ fn consume_comment(rdr: string_reader, code_to_the_left: bool, &comments: [cmnt]/~) { #debug(">>> consume comment"); if rdr.curr == '/' && nextch(rdr) == '/' { - vec::push(comments, read_line_comments(rdr, code_to_the_left)); + read_line_comments(rdr, code_to_the_left, comments); } else if rdr.curr == '/' && nextch(rdr) == '*' { - vec::push(comments, read_block_comment(rdr, code_to_the_left)); + read_block_comment(rdr, code_to_the_left, comments); } else if rdr.curr == '#' && nextch(rdr) == '!' { - vec::push(comments, read_shebang_comment(rdr, code_to_the_left)); + read_shebang_comment(rdr, code_to_the_left, comments); } else { fail; } #debug("<<< consume comment"); } |
