当前位置:首页 > 网站旧栏目 > 学习园地 > 设计软件教程 > Ddoc文档注释学习笔记

Ddoc文档注释学习笔记
2010-01-13 22:52:58  作者:  来源:
Ddoc学习笔记

ddoc的英文文档在:
http://www.digitalmars.com/d/ddoc.html

D语言可以在代码中嵌入文档注释(以下称文档)。
它不仅仅是注释,而且还是一段可供阅读的文档。
这样做的好处是,在开发、维护代码的时候,就能同时维护文档。
对于程序员,写文档比写代码还痛苦;写注释倒是一个大家还可以接受的事情。
在写代码的时候,顺便把文档写了,也许能改善一下文档不全的问题。
个人挺喜欢这样方式的。至于太团队项目开发中有没有效果。
因为还没有实践过,不敢乱做评判。


文档有以下几个步骤处理:
  1. 词法 文档注释被 附加的记号 标识..
  2. 解析 文档注释 被关联到 特殊的定义和组合
  3. 段落 每个文档注释 被 分解到一个段落的序列
  4. 处理特定的节.
  5. 非特殊的段落完成后高亮显示.
  6. 合并模块中的所有段落.
  7. 在最终结果执行宏文本替换.


下面按照这个顺序来展开;

推荐先熟悉文档的写法,一般编译方法,常用节;和学习使用Candydoc;
其他内容可以后期在看;


文档的语法

从一个最简单的程序开始吧:

Java代码 复制代码
  1. /**  
  2.  * 这个一个Ddoc文档例子  
  3.  *   
  4.  * Authors: Dehong Liu  
  5.  * Date:    2007年8月13日  
  6.  */  
  7.   
  8. void main()   
  9. {   
  10. }  

注意注释符号 /**,和单词Authors/Date。

编译这个文件(a1.d),并且生成文档doc1/a1.html
Java代码 复制代码
  1. dmd -Dddoc1 a1.d            # -DdXXX 指定文档生成路径为XXX  

用浏览器打开这个html文件,看起来像下面这样【见附件 doc1/a1.html】:
Java代码 复制代码
  1. a1   
  2.   
  3. void main();   
  4.     这个一个Ddoc文档例子   
  5.   
  6.     Authors:   
  7.     Dehong Liu   
  8.   
  9.     Date:   
  10.     2007813日    
  11.   
  12. -------------------------------------------------------------      
  13. Page generated by Ddoc.   

看着很奇怪?这只是个开始。至少明白了哪些写法会变成文档,表现形式和怎么生成。

现在一个个开始解释。
文档有下面三种写法:
Java代码 复制代码
  1.   
  2. /** ...   */        / 后面两个*    
  3. /++ ...   +/        / 后面两个+   
  4. ///                 三个 /      


下面有一个完整的文档写法例子(a2.d):
Java代码 复制代码
  1. /// 这是一个行文档注释   
  2.   
  3. /** 这也是 */  
  4.   
  5. /++ 同样 +/   
  6.   
  7. /**  
  8.    这是一个摘要文档  
  9.  */  
  10.   
  11. /**  
  12.  * 开头的* 不是文档的一部分  
  13.  */  
  14.   
  15. /*********************************  
  16.    在 /** 后面的连续的*,  
  17.    不是文档的一部分  
  18.  */  
  19.   
  20. /++   
  21.    这也是一个摘要文档   
  22.  +/   
  23.   
  24. /++   
  25.  + 开头的+ 不是文档的一部分   
  26.  +/   
  27.   
  28. /+++++++++++++++++++++++++++++++++   
  29.    在 /++ 后面的连续的+,   
  30.    不是文档的一部分   
  31.    上面的斜杠是中文符号,避免语法错误   
  32.   
  33.    换行:注意上面的空行   
  34.  +/   
  35.   
  36. /*********** 前面连续的*号不是,这部分*****是文档,后面的又不是  *****************/  
  37.   
  38. module a2;  


输出的html结果【见附件 doc1/a2.html】:
Java代码 复制代码
  1. a2   
  2. 这是一个行文档注释   
  3.   
  4. 这也是   
  5.   
  6. 同样   
  7.   
  8.   
  9.   
  10. 这是一个摘要文档   
  11.   
  12.   
  13.   
  14. 开头的* 不是文档的一部分   
  15.   
  16.   
  17.   
  18. 在 /** 后面的连续的*, 不是文档的一部分   
  19.   
  20.   
  21.   
  22. 这也是一个摘要文档   
  23.   
  24.   
  25.   
  26. 开头的+ 不是文档的一部分   
  27.   
  28.   
  29.   
  30. 在 /++ 后面的连续的+, 不是文档的一部分 上面的斜杠是中文符号,避免语法错误   
  31.   
  32. 换行:注意上面的空行   
  33.   
  34. 前面连续的*号不是,这部分*****是文档,后面的又不是   



文档和申明关联

每一个文档都和一个申明(declaration)相关联:
引用

1. 如果某单行文档的最左边是空格,它就和下面的申明关联
2. 多个关联到同一个申明的文档会被连接在一起
3. 没有关联到申明的文档会被忽略
4. 在module申明前的所有文档会被应用到整个模块
5. 如果文档出现在申明的右边,则关联到它
6. 如果文档只是ditto,则应用上一个申明的文档
7. 如果一个申明没有文档,则不会出现在html输出中,要出现,可以写一个空的文档,如 ///
 


看一个例子吧:
Java代码 复制代码
  1. /**  
  2.  * 整个模块的文档  
  3.  */  
  4.   
  5. module a3;   
  6.   
  7. int a;  /// a;的文档,b没有文档   
  8. int b;   
  9.   
  10. /** c和d的文档 */  
  11. /** 再添加些c和d的文档的文档 */  
  12. int c;   
  13. /** ditto */  
  14. int d;   
  15.   
  16. /** e和f的文档 */ int e;   
  17. int f;  /// ditto   
  18.   
  19. /** g的文档 */  
  20. int g; /// 在添加点g的文档   
  21.   
  22. /// C和D的文档   
  23. class C   
  24. {   
  25.     int x;    /// C.x的文档   
  26.   
  27.     /** C.y 和 C.z的文档 */  
  28.     int y;   
  29.     int z;    /// ditto   
  30. }   
  31.   
  32. /// ditto   
  33. class D   
  34. {   
  35. }   
  36.   
  37. int h; // 只有注释,没有文档,不会出现在html中   
  38.   
  39. // 下面是空文档   
  40. int j; ///    
  41.   
  42. /// 被忽略的文档  


看起来像这样【见附件 doc1/a3.html】
Java代码 复制代码
  1. a3   
  2. 整个模块的文档   
  3.   
  4. int a;   
  5.     a;的文档,b没有文档   
  6.   
  7. int c;   
  8. int d;   
  9.     c和d的文档   
  10.   
  11.     再添加些c和d的文档的文档   
  12.   
  13. int e;   
  14. int f;   
  15.     e和f的文档   
  16.   
  17. int g;   
  18.     g的文档   
  19.   
  20.     在添加点g的文档   
  21.   
  22. class C;   
  23. class D;   
  24.     C和D的文档   
  25.   
  26.     int x;   
  27.         C.x的文档   
  28.   
  29.     int y;   
  30.     int z;   
  31.         C.y 和 C.z的文档   
  32.   
  33. int j;  



文档的节

a1.d例子中的Authors / Date 就是节(Sections)。
节由 "非空格字符" + ":" 组成,其中标识符部分叫节名,它不区分大小写

概要(Summary):
第一个节就是概要,它没有节名;
它是第一个段落,遇到空行或者节名结束;
可以把概要写成多行,但写成一行比较好
概要节是可选的

描述(Description):
第二个没有名字的节 是描述
遇到一个节名或者到文档的结束

给个例子(a4.d):
Java代码 复制代码
  1. /***********************************  
  2.  * 这是一个概要(Brief summary)  
  3.  * 描述myfunch函数的使用;这两行形成一个概要节  
  4.  *  
  5.  * 描述节的第一个段落  
  6.  *  
  7.  * 还是描述节:  
  8.  * 可以写更多内容  
  9.  */  
  10.   
  11. void myfunc() { }  

html输出【见附件 doc1/a4.html】:
Java代码 复制代码
  1. void myfunc();   
  2.     这是一个概要(Brief summary) 描述myfunch函数的使用;这两行形成一个概要节   
  3.   
  4.     描述节的第一个段落   
  5.   
  6.     还是描述节: 可以写更多内容   



标准节

有一些预定义好了的节,看看它们的意思:
  • Authors: 列出作者名字
  • Bugs: 列出已知BUG
  • Date: 列出当前修订的时间,应当是 std.date 能解析的形式
  • Deprecated: 做 "抗议"标记(?弃用标记)--最好给出理由和纠正的方法
  • Examples: 例子
  • History: 修订历史
  • License: 版权申明
  • Returns: 解释函数的返回值;如果返回void,就不要写在文档中了
  • See_Also: 列出相关符号,或者URL链接
  • Standards: 如果申明涉及到某个标准,在此描述
  • Throws: 列出在哪些环境下会抛出异常
  • Version: 指定当前申明的版本号
  • See_Also: 列出相关符号,或者链接
  • See_Also: 列出相关符号,或者链接


特殊节:一些有特殊含义和语法的节
  • Copyright: 版权申明。如果是在module申明中,该节会被COPYRIGHT宏替换;
  • Params: 函数的参数描述文档; "标识符 =' 开始一个新的参数描述;它可以跨越多行
  • Macros: 和Params节有类似的语法;它是一系列 NAME=value 组成 NAME 是宏名,VALUE是要替换成的文字
     


全部列出来看看:
Java代码 复制代码
  1. /** Copyright: Public Domain */  
  2.   
  3. module a5;   
  4.   
  5. /**  
  6.  * Authors: Melvin D. Nerd, melvin@mailinator.com  
  7.  *  
  8.  * Bugs: Doesn't work for negative values.  
  9.  *  
  10.  * Date: March 14, 2003  
  11.  */  
  12.   
  13. void foo1() {}   
  14.   
  15. /**  
  16.  * Deprecated: superseded by function bar().  
  17.  */  
  18.   
  19. deprecated void foo2() {  }   
  20.   
  21. /**  
  22.  * Examples:  
  23.  * --------------------  
  24.  * writefln("3"); // writes '3' to stdout  
  25.  * --------------------  
  26.  *  
  27.  * History:  
  28.  *  V1 is initial version  
  29.  *  
  30.  *  V2 added feature X  
  31.  *  
  32.  * License: use freely for any purpose  
  33.  */  
  34.   
  35. void bar() { }   
  36.   
  37. /**  
  38.  * Read the file.  
  39.  * Returns: The contents of the file.  
  40.  */  
  41.   
  42. void[] readFile(char[] filename) { return "filename"; }   
  43.   
  44. /**  
  45.  * See_Also:  
  46.  *    foo, bar, http://www.digitalmars.com/d/phobos/index.html  
  47.  *  
  48.  * Standards: Conforms to DSPEC-1234  
  49.  *  
  50.  * Throws: WriteException on failure.  
  51.  *  
  52.  * Version: 1.6a  
  53.  */  
  54.   
  55. void writeFile(char[] filename) {  }   
  56.   
  57. // 特殊节   
  58.   
  59. /***********************************  
  60.  * foo does this.  
  61.  * Params:  
  62.  *  x = is for this  
  63.  *      and not for that  
  64.  *  y = is for that  
  65.  */  
  66.   
  67. void foo(int x, int y)   
  68. {   
  69. }   
  70.   
  71. /**  
  72.  * Macros:  
  73.  *  FOO =   now is the time for  
  74.  *      all good men  
  75.  *  BAR =   bar  
  76.  *  MAGENTA =   <font color=magenta></font>  
  77.  *  COPYRIGHT = 版权归热爱地球的火星人所有  
  78.  */  
  79.   
  80. /**  
  81.  * Foo: $(FOO)  
  82.  * Bar: $(BAR)  
  83.  * MAGENTA: $(MAGENTA)  
  84.  * Copyright: Public Domain   
  85.  */  
  86. void foo3() {   }  

输出效果是【见附件doc1/a5.html】:
Java代码 复制代码
  1. a5   
  2.   
  3. void foo1();   
  4.     Authors:   
  5.     Melvin D. Nerd, melvin@mailinator.com   
  6.   
  7.     BUGS:   
  8.     Doesn't work for negative values.   
  9.   
  10.     Date:   
  11.     March 142003  
  12.   
  13. deprecated void foo2();   
  14.     Deprecated:   
  15.     superseded by function bar().   
  16.   
  17. void bar();   
  18.     Examples:   
  19.   
  20.      writefln("3"); // writes '3' to stdout   
  21.   
  22.   
  23.   
  24.     History:   
  25.     V1 is initial version   
  26.   
  27.     V2 added feature X   
  28.   
  29.     License:   
  30.     use freely for any purpose   
  31.   
  32. void[] readFile(char[] filename);   
  33.     Read the file.   
  34.   
  35.     Returns:   
  36.     The contents of the file.   
  37.   
  38. void writeFile(char[] filename);   
  39.     See Also:   
  40.     foo, bar, http://www.digitalmars.com/d/phobos/index.html   
  41.   
  42.     Standards:   
  43.     Conforms to DSPEC-1234  
  44.   
  45.     Throws:   
  46.     WriteException on failure.   
  47.   
  48.     Version:   
  49.     1.6a   
  50.   
  51. void foo(int x, int y);   
  52.     foo does this.   
  53.   
  54.     Params:   
  55.     int x   is for this and not for that   
  56.     int y   is for that   
  57.   
  58. void foo3();   
  59.     Foo:   
  60.     now is the time for all good men   
  61.   
  62.     Bar:   
  63.     bar   
  64.   
  65.     MAGENTA:   
  66.     <font color=magenta></font>   
  67.   
  68.     Copyright:   
  69.     Public Domain   
  70.   
  71. Page generated by Ddoc. 版权归热爱地球的火星人所有   


上面的例子都还好理解,把不容易理解的说说:
/** Copyright: Public Domain */ 在module申明前和后的效果不一样;
前者的效果在哪里?看页面的最后一行

代码的文档是这么写的:
Java代码 复制代码
  1. * Examples:     
  2. * --------------------     
  3. * writefln("3"); // writes '3' to stdout     
  4. * --------------------    

代码的上下有一条分割线:至少三个连字符(-)

文档的高亮处理

内嵌注释 Embedded Comments
不懂

内嵌代码 Embedded Code
上面已经演示了

内嵌的HTML Embedded HTML
内嵌的HTML代码不会被转译,直接输出给html文件
虽然如此,基于某些原因(我没看懂),还是最好不要用html
Java代码 复制代码
  1. /** Example of embedded HTML:  
  2.  *     
  3.  *      <li> <a href="http://www.digitalmars.com">Digital Mars</a> </li>  
  4.  *      <li> <a href="http://www.classicempire.com">Empire</a> </li>  
  5.  */  


强调 Emphasis
函数参数等标识符会被以斜体,粗体,超链接等形式强调处理;具体形式文档没有说

特殊符号Character Entities
< > & 有特殊含义,如果要使用这3个符号,换成相应的:&lt; &gt; &amp;
以下情况除外:在代码节中;不是立即跟一个 # 或 字母

文档的宏

宏来自于下面这些地方,并按照特定步骤处理:
  1. 预定义宏
  2. sc.ini配置文件中的DDOCFILE项指定的文件
  3. 命令行指定的*.ddoc文件
  4. Ddoc运行时产生的定义,如BODY,TITLE
  5. 文件中的宏节


宏主要用在对文档格式的自定义上。
通过修改宏,能自定义HTML输出格式。

CandyDoc的使用

dmd默认的格式很简单,可以使用CandyDoc来美化文档格式和增强功能。
使用方法很简单:(.ddoc是宏文件的后缀)
下载CandyDoc程序
主页:http://www.dsource.org/projects/helix/wiki/CandyDoc
下载:http://svn.dsource.org/projects/helix/downloads/candydoc-0.80.zip

假设要编译: a5.d  doc2/candydoc
Java代码 复制代码
  1. dmd -c -Dddoc2 a5.d doc2/candydoc/*.ddoc  

生成的a5.html文件在 doc2/目录下,和candydoc一个目录,如果不是同一目录,会显示不正常;

candydoc有2个.ddoc文件:candy.ddoc  modules.ddoc
如果要定义样式,在candy.ddoc中定义,一般不改;
modules.ddoc 要修改成自己的模块,默认是:
Java代码 复制代码
  1. MODULES =    
  2.     $(MODULE helix.basic)   
  3.     $(MODULE helix.color)   
  4.     $(MODULE helix.config)   
  5.     $(MODULE helix.linalgebra)  


以上面的5个程序为例:
Java代码 复制代码
  1. MODULES =   
  2.     $(MODULE a.a1)   
  3.     $(MODULE a.a2)   
  4.     $(MODULE a.a3)   
  5.     $(MODULE a.a4)   
  6.     $(MODULE a.a5)  

编译之:
Java代码 复制代码
  1. dmd -c -Dddoc2 a1 a2 a3 a4 a5.d doc2/candydoc/*.ddoc  


如果要用Candydoc替换默认的文档格式,这么做:
修改dmd.conf文件,添加一行:
DDOCFILE=candy.ddoc
看起来像这样
Java代码 复制代码
  1. [Environment]   
  2. DFLAGS=-I%@P%/../src/phobos -L-L%@P%/../lib -L-L/usr/lib -L-L/usr/local/lib -version=Phobos   
  3. DDOCFILE=candy.ddoc  


上面的配置只写了candy.ddoc文件,没有写module.ddoc。所以编译的时候要添加module.ddoc,这样做很不爽;
我的办法是自己写一个.ddoc文件--proj.ddoc
把candydoc.ddoc和 module.ddoc两个文件合并在一起

[模块部分的导航要求所有的html都在一个目录下,这点还没有仔细研究,回头再写]

注意,如果没有效果,检查:
1. Linux是修改dmd.conf文件;Windows是修改sc.ini文件;不要弄错了
2. dmd.conf 可能在多个地方:/etc 或 dmd命令所在目录等
3. candy.doc是相对于当前目录而已,不是dmd.conf文件;请按照实际情况设定路径


文档用起来还算简单,开始会不习惯,慢慢就习惯了。

安徽新华电脑学校专业职业规划师为你提供更多帮助【在线咨询