Improve function documentation generation (fixes
MODIFY
binding-generator/src/comment.rs
binding-generator/src/comment.rs
@@ -204,7 +204,8 @@ pub fn render_doc_comment_with_processor(doc_comment: &str, prefix: &str, opencv
}
// comment body markers
- out.replace_in_place("@brief ", "");
+ static BRIEF: Lazy<Regex> = Lazy::new(|| Regex::new(r#"@brief[ :]*"#).unwrap());
+ out.replace_in_place_regex(&BRIEF, "");
out.replace_in_place("@note", "\nNote:");
// code blocks, don't run them during tests

MODIFY
binding-generator/src/func.rs
binding-generator/src/func.rs
@@ -609,12 +609,13 @@ impl Element for Func<'_, '_> {
fn rendered_doc_comment_with_prefix(&self, prefix: &str, opencv_version: &str) -> String {
let mut comment = self.entity.get_comment().unwrap_or_default();
+ let line = self.entity.get_location().map(|l| l.get_file_location().line).unwrap_or(0);
const OVERLOAD: &str = "@overload";
if let Some(idx) = comment.find(OVERLOAD) {
- let rep = if let Some(copy) = self.gen_env.get_func_comment(self.entity.cpp_fullname().as_ref()) {
+ let rep = if let Some(copy) = self.gen_env.get_func_comment(line, self.entity.cpp_fullname().as_ref()) {
format!("{}\n\n## Overloaded parameters\n", copy)
} else {
- "".to_string()
+ "This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.".to_string()
};
comment.replace_range(idx..idx + OVERLOAD.len(), &rep);
}
@@ -624,7 +625,7 @@ impl Element for Func<'_, '_> {
let mut copy_full_name = self.cpp_namespace().into_owned();
copy_full_name += "::";
copy_full_name += copy_name;
- if let Some(copy) = self.gen_env.get_func_comment(&copy_full_name) {
+ if let Some(copy) = self.gen_env.get_func_comment(line, &copy_full_name) {
Some(copy.into())
} else {
Some("".into())

MODIFY
binding-generator/src/generator_env.rs
binding-generator/src/generator_env.rs
@@ -66,7 +66,11 @@ impl<'tu> DbPopulator<'tu, '_> {
let raw_comment = entity.get_comment().unwrap_or_default();
if !raw_comment.is_empty() && !raw_comment.contains("@overload") {
let name = entity.cpp_fullname().into_owned();
- self.gen_env.func_comments.insert(name, comment::strip_comment_markers(&raw_comment));
+ let line = entity.get_location().map(|l| l.get_file_location().line).unwrap_or(0);
+ let defs = self.gen_env.func_comments.entry(name).or_insert_with(|| vec![]);
+ defs.push((line, comment::strip_comment_markers(&raw_comment)));
+ // reverse sort due to how we're querying this
+ defs.sort_unstable_by(|(left_line, _), (right_line, _)| right_line.cmp(left_line));
}
}
@@ -150,7 +154,7 @@ pub struct GeneratorEnv<'tu> {
export_map: HashMap<ExportIdx, ExportConfig>,
rename_map: HashMap<ExportIdx, RenameConfig>,
pub func_names: NamePool,
- func_comments: HashMap<String, String>,
+ func_comments: HashMap<String, Vec<(u32, String)>>,
class_kind_cache: MemoizeMap<String, Option<ClassKind>>,
class_constants: HashMap<String, Const<'tu>>,
type_resolve_cache: HashMap<String, Type<'tu>>,
@@ -258,8 +262,14 @@ impl<'tu> GeneratorEnv<'tu> {
Self::get_with_fuzzy_key(entity, |key| self.rename_map.get(key))
}
- pub fn get_func_comment(&self, cpp_fullname: &str) -> Option<&str> {
- self.func_comments.get(cpp_fullname).map(|x| x.as_str())
+ pub fn get_func_comment(&self, line: u32, cpp_fullname: &str) -> Option<&str> {
+ self.func_comments.get(cpp_fullname)
+ .and_then(|comments| comments.iter()
+ // try to find the source function comment that is closest to the requested
+ .find(|(source_line, _)| *source_line <= line)
+ // if it fails return at least something
+ .or_else(|| comments.last()))
+ .map(|(_, comment)| comment.as_str())
}
pub fn get_class_kind(&self, entity: Entity<'tu>) -> Option<ClassKind> {

MODIFY
binding-generator/src/lib.rs
binding-generator/src/lib.rs
// todo almost everything from the manual module must be connected to the binding generator, not the main crate
// todo check that FN_FaceDetector works at all (receiving InputArray, passing as callback)
// fixme vector<Mat*> get's interpreted as Vector<Mat> which should be wrong (e.g. Layer::forward and Layer::apply_halide_scheduler)
-// fixme most constructors of Mat have invalid comment "download data from GpuMat"
// fixme MatConstIterator::m return Mat**, is it handled correctly?
// fixme VectorOfMat::get allows mutation
// fixme TextDetectionModel_EAST (and all others inheriting from Model) seems to have no fields, but it fails when generated as simple, probably makes sense to have a special case for that

Improve function documentation generation (fixes #266)