博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用于Javascript的文档生成软件的开发总结

Posted on 2011-05-19 20:34  xuld  阅读(1043)  评论(3编辑  收藏  举报

  近期一直在做Js文档生成软件。

  目前占据这个领域的主要就是 jsdoc 开源项目。先介绍下 jsdoc 本身,它是用Java开发的(其实主要是Javascript开发) 基于字符串直接处理的文档工具。 因为Javscript非常灵活,Javascript的文档生成自然也比不上Java之类的准确、有效。jsdoc本身要求在注释中大量使用一些标签来告诉文档生成器这是一个类、属性、方法或其它的类型,jsdoc在解析中是通过上下文来决定变量的归属,比如上文使用 @class 标识类, 下文的 @method 就自动处理为上个 @class 所指的类,而完全忽视了代码自身的逻辑。

  且不说jsdoc的方法是否方便、有效。总之,我要做的是基于语法分析而生成文档的工具。 

  我目标是生成完全面向对象阻止的文档,即最后的文档最高级是名字空间(包) , 下级是类, 再下级是成员。

  1. 成员的归类。一个变量在定义后,它到底属于哪个父成员,这是文档分析必须要分析出的。

/**
* 将当前值转为数字。
*/
Boolean.prototype.toNumber
= function(){
return +this;
};

  从这段代码可知: 有一个 toNumber 成员, 其父成员为 Boolean.prototype , 这个情况可以轻松检测所在成员,但假如换一个写法,比如 Ext 中的写法是:

/**
* 将当前值转为数字。
*/
Ext.extend(Boolean.prototype,{
toNumber: function(){
return +this;
}
} );

  这就很麻烦了,因为文档分析程序不肯能去执行这个代码,它当然不知道 toNumber 的父成员。 jsdoc采用最近使用的 @class 最为其父成员。但这样很容易导致 @class 多很多错误的成员。

  最终我采用作用域的分析方式。即 函数调用 或 函数定义 被作为一个作用域。它们之前的 @class 将被理解为这个作用域内成员的父成员。即代码应该这样注释:

/**
* 将当前值转为数字。
* @class Boolean
*/
Ext.extend(Boolean.prototype,{
toNumber: function(){
return +this;
}
} );

@class Boolean 只对此函数有效,即 @class 只解释相邻的作用域。 同理有:

/**
* 将当前值转为数字。
* @class Boolean
*/
(function(){
function toNumber(){
return +this;
}
})();

由于这是函数定义,所以函数内部的成员的父成员也是 @class Boolean 。

  当然,这些都是无理的推算,肯能导致错误结果,可以通过指定 @memberOf 来覆盖自动判断的父变量。

  以上对于 @class C , 成员解释为 C.prototype.p 

  对于 @namespace C , 或成员已记 @static, 解释为 C.p

2. 具备识别继承、原型的功能。

比如 A.prototype = new B  是很典型的继承代码。

通过模拟运行可以实现 原型操作。

3. 根据平时写Javascript的经验,再参考jsdoc, 最终我决定将使用以下几个系统标签,它们将为文档生成做出伟大贡献。

全局标签

  全局标签主要用于全项目或文件的描述。一般全局标签只能在文件顶部使用。

  • @projectDescription Summary 当前项目功能描述
  • @author Summary 代码的作者
  • @lisense Summary 代码的协议
  • @version Summary 代码的版本
  • @fileOverview Summary 当前文件描述
  • @file Summary 表示当前文件名,默认为真实文件名

公开标签

    以下标签可以在任何位置使用,就像 HTML 中任何标签都有 tagName 的属性。

  • @summary Summary 注释的简介 - 一般不需要直接使用这个标签, 因为注释的最开始处到第一个可解析的标签前的文字就是 @summary 标签。即:  /** 内容 */   等价于  /** @summary 内容  */
  • @remark Summary 备注 - 一般不需要直接使用这个标签, 因为注释中已经使用了标签之后的文字就是 @remark 。即: 
      /**
           * @return {Number}
       * 说明
           */
    等价于
      /**
       * @return {Number}
       * @remark 说明
       */
  • @ignore 忽略有这个标记注释。
  • @define {Type} {Type} 定义同意义的类型。 比如 @define {int} {Number} 这样就可以用 int 代替 Number
  • @define Name Name  定义同意义的注释,  使用 define 可以定义标签的 别名。比如 @define description summary  之后就可用  @description   替代  @summary
  • @since [Summary] 指示自指定的版本提供。
  • @deprecated [Summary] 指示一个成员已经废弃。
  • @see Link  指向一个文件的链接。
  • @example Summary 示例。
  • @syntax Summary 手动指定语法。
  • @name Name 名字。
  • @memberOf Name 指示父成员。
  • @type Type 指示类型。

类型说明

  • @class [Name] 指示这是一个类。
  • @enum [Name] 指示这是枚举。
  • @interface [Name] 指示这是一个接口。
  • @member [Name] 指示这是一个成员。
  • @property [{Type}] [Name] 指示这是一个属性。
  • @field [{Type}] [Name] 指示这是一个字段。
  • @method [Name] 指示这是一个方法。
  • @event [{Type}] [Name] 指示当前类的事件。
  • @getter [{Type}] [Name] 指示这是一个只读属性。
  • @setter [{Type}] [Name] 指示这是一个只写属性。
  • @constructor [Name] 指示这是构造函数。
  • @config {Type} [Name] 指示这是类的配置成员。

属性说明

  • @public 指示公开
  • @private 指示一个类或函数是私有的。
  • @protected 指示保护。
  • @internal 指示内部。
  • @final 指示一个函数是不能覆盖的。
  • @static 指示一个类是静态的。
  • @abstract 指示一个类是抽象的。
  • @virtual 指示一个类是抽象的。
  • @const 指示一个值是常量值。

其它

  • @extends  Name 指示一个类派生了另一个类。
  • @implements Name 指示一个类派生了另一个类。
  • @param {Type} Name Summary 表示参数。如果是可选参数加上 [Name] ,如果是 随机参数 名字为 ... 如果有默认值, 使用 Name=Value 多类型使用任意符号分开。
  • @return [{Type}] [Summary]  返回  。
  • {@link Link} 链接。
  • {@code [{Type}] <<< Summary >>>} 代码。
  • @{   表示字符 {
  • @@ 表示字符 @
  • @} 表示字符 }
  • @* 表示字符 *