diff --git a/library/bind-utils/src/lib.rs b/library/bind-utils/src/lib.rs index bb5e5c3d5..cf66761ab 100644 --- a/library/bind-utils/src/lib.rs +++ b/library/bind-utils/src/lib.rs @@ -8,6 +8,8 @@ struct Cb; impl ParseCallbacks for Cb { fn process_comment(&self, comment: &str) -> Option { let comment = comment.replace("@retval {", "@retval return_value {"); + // doxygen-rs は @param[in] name: の "name:" をパースできないためコロンを除去 + let comment = strip_doxygen_param_colon(&comment); let dox = doxygen_rs::transform(&comment) .trim() .replace('[', r"\[") @@ -20,6 +22,64 @@ impl ParseCallbacks for Cb { } } +/// `@param[in] name: desc` や `@param[in]: desc` のコロンを除去する。 +/// +/// doxygen-rs はパラメータ名やディレクション指定の直後にコロンがある形式を +/// パースできないため、bindgen に渡す前にコロンを取り除く。 +fn strip_doxygen_param_colon(comment: &str) -> String { + let mut result = String::with_capacity(comment.len()); + for line in comment.lines() { + if !result.is_empty() { + result.push('\n'); + } + // @param を含む行のみ処理 + if let Some(param_pos) = line.find("@param") { + let after_param = &line[param_pos + "@param".len()..]; + // @param[in]/[out]/[in,out] をスキップ + let rest = if after_param.starts_with('[') { + match after_param.find(']') { + Some(bracket_end) => &after_param[bracket_end + 1..], + None => { + result.push_str(line); + continue; + } + } + } else { + after_param + }; + // ケース1: @param[in]: desc (パラメータ名なし、コロンが直後) + let rest_trimmed = rest.trim_start(); + if rest_trimmed.starts_with(':') { + let colon_pos = param_pos + + "@param".len() + + (after_param.len() - rest.len()) + + (rest.len() - rest_trimmed.len()); + result.push_str(&line[..colon_pos]); + result.push_str(&line[colon_pos + 1..]); + continue; + } + // ケース2: @param[in] name: desc (パラメータ名の末尾にコロン) + let name_end = rest_trimmed + .find(|c: char| !c.is_alphanumeric() && c != '_') + .unwrap_or(rest_trimmed.len()); + if name_end > 0 && rest_trimmed.as_bytes().get(name_end) == Some(&b':') { + let colon_pos = param_pos + + "@param".len() + + (after_param.len() - rest.len()) + + (rest.len() - rest_trimmed.len()) + + name_end; + result.push_str(&line[..colon_pos]); + result.push_str(&line[colon_pos + 1..]); + } else { + result.push_str(line); + } + } else { + result.push_str(line); + } + } + result +} + pub fn bind_c2a_builder() -> bindgen::Builder { bindgen::Builder::default() .blocklist_type("max_align_t") // https://github.com/servo/rust-bindgen/issues/550