Parse a docblock into categorized lines.
(docblock: &str)
| 1048 | |
| 1049 | /// Parse a docblock into categorized lines. |
| 1050 | fn parse_docblock_lines(docblock: &str) -> Vec<DocLine> { |
| 1051 | let mut result = Vec::new(); |
| 1052 | let lines: Vec<&str> = docblock.lines().collect(); |
| 1053 | |
| 1054 | for (i, line) in lines.iter().enumerate() { |
| 1055 | let trimmed = line.trim(); |
| 1056 | |
| 1057 | if i == 0 && trimmed.starts_with("/**") { |
| 1058 | // Single-line docblock: `/** @return void */` |
| 1059 | if trimmed.ends_with("*/") && trimmed.len() > 5 { |
| 1060 | let inner = trimmed |
| 1061 | .strip_prefix("/**") |
| 1062 | .unwrap_or("") |
| 1063 | .strip_suffix("*/") |
| 1064 | .unwrap_or("") |
| 1065 | .trim(); |
| 1066 | result.push(DocLine::Open); |
| 1067 | if !inner.is_empty() { |
| 1068 | categorize_tag_line(inner, &mut result); |
| 1069 | } |
| 1070 | result.push(DocLine::Close); |
| 1071 | continue; |
| 1072 | } |
| 1073 | result.push(DocLine::Open); |
| 1074 | // Check if there's content after `/**` on the same line. |
| 1075 | let after_open = trimmed.strip_prefix("/**").unwrap_or("").trim(); |
| 1076 | if !after_open.is_empty() { |
| 1077 | categorize_tag_line(after_open, &mut result); |
| 1078 | } |
| 1079 | continue; |
| 1080 | } |
| 1081 | |
| 1082 | if trimmed == "*/" || trimmed.ends_with("*/") { |
| 1083 | // Check if there's content before `*/`. |
| 1084 | let before_close = trimmed.strip_suffix("*/").unwrap_or("").trim(); |
| 1085 | let before_close = before_close |
| 1086 | .strip_prefix('*') |
| 1087 | .unwrap_or(before_close) |
| 1088 | .trim(); |
| 1089 | if !before_close.is_empty() { |
| 1090 | categorize_tag_line(before_close, &mut result); |
| 1091 | } |
| 1092 | result.push(DocLine::Close); |
| 1093 | continue; |
| 1094 | } |
| 1095 | |
| 1096 | // Regular docblock line: ` * content` |
| 1097 | let content = trimmed.strip_prefix('*').unwrap_or(trimmed).trim(); |
| 1098 | |
| 1099 | // Check if this is a continuation line (no `@` prefix, preceded by |
| 1100 | // a tag line). If so, merge it into the previous tag line. |
| 1101 | if !content.is_empty() |
| 1102 | && !content.starts_with('@') |
| 1103 | && !result.is_empty() |
| 1104 | && matches!( |
| 1105 | result.last(), |
| 1106 | Some(DocLine::Param(_)) | Some(DocLine::Return(_)) | Some(DocLine::OtherTag(_)) |
| 1107 | ) |
no test coverage detected