class RDoc::Parser::C

RDoc::Parser::C 尝试解析 C 扩展文件。它会查找扩展中常见的标准模式:rb_define_classrb_define_method 等等。它会尝试查找方法对应的 C 源代码并提取注释,但如果失败,我们也不会太担心。

与 Ruby 方法关联的注释是从 实现 该方法的例程关联的 C 注释块中提取的,也就是说,其名称在 rb_define_method 调用中给出的方法。例如,您可以编写

/*
 * Returns a new array that is a one-dimensional flattening of this
 * array (recursively). That is, for every element that is an array,
 * extract its elements into the new array.
 *
 *    s = [ 1, 2, 3 ]           #=> [1, 2, 3]
 *    t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
 *    a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
 *    a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 */
 static VALUE
 rb_ary_flatten(VALUE ary)
 {
     ary = rb_obj_dup(ary);
     rb_ary_flatten_bang(ary);
     return ary;
 }

 ...

 void
 Init_Array(void)
 {
   ...
   rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);

在这里,RDoc 将从 rb_define_method 行确定在 Array 类中存在一个名为“flatten”的方法,并将在方法 rb_ary_flatten 中查找实现。然后,它将在 HTML 输出中使用该方法中的注释。此方法必须与 rb_define_method 在同一源文件中。

注释块可以包含特殊指令

Document-class: name

指定类的文档。

Document-module: name

指定模块的文档。

Document-const: name

指定 rb_define_const 的文档。

常量值可以在注释的第一行提供,如下所示

/* 300: The highest possible score in bowling */
rb_define_const(cFoo, "PERFECT", INT2FIX(300));

只要使用 \ 进行转义,该值就可以包含内部冒号。

Document-global: name

指定 rb_define_global_const 的文档

Document-variable: name

指定 rb_define_variable 的文档

Document-method: method_name

指定方法的文档。当方法名称明确时使用此方法。

Document-method: ClassName::method_name

给定类中单例方法的文档。当方法名称本身不明确时使用此方法。

Document-method: ClassName#method_name

给定类中实例方法的文档。当方法名称本身不明确时使用此方法。

Document-attr: name

指定属性的文档。

call-seq: 直到空行的文本

由于 C 源代码没有为 Ruby 级别的参数提供描述性名称,因此您需要显式地记录调用序列

此外,RDoc 默认情况下假定实现 Ruby 函数的 C 方法与 rb_define_method 调用在同一源文件中。如果不是这种情况,请添加注释

rb_define_method(....);  // in filename

例如,我们可能有一个在其 Init_xxx 方法中定义多个类的扩展。我们可以使用以下方式记录它们

/*
 * Document-class:  MyClass
 *
 * Encapsulate the writing and reading of the configuration
 * file. ...
 */

/*
 * Document-method: read_value
 *
 * call-seq:
 *   cfg.read_value(key)            -> value
 *   cfg.read_value(key} { |key| }  -> value
 *
 * Return the value corresponding to +key+ from the configuration.
 * In the second form, if the key isn't found, invoke the
 * block and return its value.
 */