来源: ASE, 2010.
这是一篇基于模板的代码摘要生成文章,首次提出了自动注释生成的方法,利用方法(函数)的结构和语言线索捕获此方法的主题、动作等的描述短语,最后组合成句,实现注释摘要的自动生成。
一、论文背景
好的注释可以帮助程序员快速理解方法(函数)的功能,有利于程序理解和软件维护。但很少有软件项目能充分地注释其代码。为解决上述问题,一种方法是在写代码时使用非常具有描述性的标识符名称,这样不用注释也知道程序的功能;另一种方法是鼓励开发人员写注释,如:自动提醒开发人员输入注释、使用自上而向下的设计范例直接从规范生成注释或使用文档优先开发方法等。显然上述方法都比较麻烦,且只适用于开发阶段,对于曾经写好的项目并不适用,因此论文提出一种针对JAVA的注释自动生成的方法,主要关注于自动生成描述一段方法功能的摘要——descriptive comments。
二、主要贡献
- 提出一种自动提取核心代码语句的算法,用于方法的摘要注释生成
- 提出一种文本生成技术,输入是Java代码语句,输出是表示代码含义的自然语言
- 对自动生成的描述性摘要注释的准确性、内容的充分性和简明性进行人工评估。
三、问题与挑战
1.问题描述
给定方法M的方法签名和主体语句,生成准确、充分、简明扼要地总结M的整体操作的自然语言文本。
2.挑战
假设:开发人员使用了有意义的标识符名称
(1)Method names are inadequate summaries
当使用一个方法签名(方法的名称和参数类型)来总结一个方法的操作时,是基于该方法的名称准确地捕获了该方法的主要操作的假设。然而,有些方法并不是基于正在执行的操作来命名的,而是基于在某个操作发生的条件下来命名的。这样单纯依靠方法签名来生成注释显然是不够的,还必须从函数主体提取有用信息。
(2)Not all method body statements belong in a summary
另一种生成主要描述性注释的方法是简单地为方法中的每个语句生成一个注释短语。然而,这样的注释并非是该方法操作的摘要,而是无用地重复整个方法主体。要使注释成为摘要,它必须包含更少的信息,并且比方法的源代码更快、更易于阅读。虽然方法中的每一个语句都是代码正确执行所必需的,但可能只有几个语句对摘要有用。
(3)Using names in the summary loses contextual information from the source code
假设可以自动选择包含摘要中应该包含内容的重要语句,如何呈现该内容又是一个难点。最简单的方法是仅基于这些重要语句生成一个个短语。但这样做严重的问题是缺少上下文信息,这些生成的短语具体代表什么并不能表达清楚,因此还需获取这些语句的上下文信息。对于任何给定语句,可能有大量的上下文信息——变量类型、返回类型或声明方法类,使用所有这些上下文信息会导致摘要注释冗长或冗余。因此还必须仔细挑选这些信息。
四、自动摘要生成
1.整体框架
- 论文提出方法的三个组件
(1)选择将要包含在摘要注释的内容或s_units;
(2)词汇化以及生成自然语言文本来表达内容 ;
(3)组合生成文本并平滑生成文本。
- 设计目标
(1)准确地表示方法的主要操作;
(2)包含理解所需的精确上下文信息;
(3)简洁并避免不必要的词语。
2.源代码预处理
- 使用词干分割方法,如通过大小写分割,或根据大写字母、下划线和数字来分割标识符单词。
- 自动识别和扩展代码中的缩略词。
- 在摘要内容选择过程中,使用控制流图、数据和控制依赖信息,以及利用 Software Word Usage Model(SWUM)获得的文本线索。
3.代码语句转换
自动生成注释需要识别任意方法的语言元素。即识别给定方法的动作、主题和任何次要参数都非常重要,论文提出一个新的模型——Software Word Usage Model(SWUM)来识别。SWUM不仅可以捕获出现在代码中的单词,还可以捕获它们的语言和结构关系。基于通用的Java命名约定,论文假设大多数方法名称都以一个动词开头。SWUM将此动词指定为动作,并在方法名的其余部分、形参和类中查找主题。对于并不以动词开头的方法,SWUM分别为方法添加动作。
最后利用主题的语言信息和次要参数的结构关系选择摘要内容。对于文本生成,使用动作-主题关系所捕获的语义与实际的单词相结合,来生成准确表示代码的可理解短语。
4. S_unit选择
S_unit是Java中除了控制流语句之外的语句, 其次,S_unit是具有if、white、for或switch等关键字的控制流表达式。
4.1识别候选的S_unit
论文描述了一些特征来表明S_unit何时是方法摘要注释的较好选择。主要有如下一些S_unit。
(1)Ending S_units
Ending S_units位于一个方法的控制出口处。大量的观察发现,通常方法执行一系列动作的目的都是为了完成最终动作,因此是摘要注释生成的较好选择。下图第6行语句就是Ending S_units。
(2)Void-Return S_units
Void-Return S_units是调用无返回值或返回值没有分配给变量的方法的语句。如上图的第4行就是Void-Return S_units。作者发现,当调用不返回值的方法时,往往是纯粹为其他作用而调用它。相比之下,有返回值的方法调用很可能只是为了促进实现一个主要操作。论文使用一个方法的AST来识别Void-Return S_units。
(3)Same-Action S_units
在方法M中,如果一个S_units有一个方法调用c,使得M和c具有相同的操作,那么该S_units被称为Same-Action S_units。下图第4行便是Same-Action S_units,因为在compile方法中,第4行, compileRE方法中的调用与compile方法具有相同的操作。
(4)Data-Facilitating S_units
Data-Facilitating S_units是将数据赋给由前三个启发式方法识别的S_units中使用的变量的S_units。例如在returnPressed方法中,第六行S_units尽管被识别为Ending S_units,但其变量“result”有关主题变量的信息很少,因此,选择变量“result”的Data-Facilitating S_unitsl来描述,即第5行。
(5)Controlling S_units
Controlling S_units是指具有if、whit、for或switch关键字之一的S_units。主要用于控制前面所提到的S_units的执行。下图第四行就是Controlling S_units,用于控制包含Ending S_units的第5行的执行。
4.2 S_units过滤
(1)程序员往往不希望在方法的摘要注释中得到描述方法的资源清理操作、日志记录或其他诊断操作的信息,对于这些计算意图对于整个程序行为不独特的操作有必要过滤掉,除非此方法的唯一目的是异常处理、资源清理或日志记录等。
如何过滤?
- 使用AST和检查一个S_units是否在一个方法的捕获或最终块内来确定这样的S_units;
- 检查 SWUM识别出的操作和主题的词如 ‘log’, ‘error’, ‘debug’, ‘trace’, ‘exception’, or ‘close’来过滤
(2)一些Ending S_units可以省略。许多方法返回一个布尔值以表示成功或失败。作者认为这些失败的路径是不必要的,因此不会在方法摘要中添加返回false的S_units。
(3)确定的 void-return 和 data-facilitating s_units可以省略。如一些变量初始化为0或null的语句,又如一些get, set, 和 object creation等并不为方法摘要的操作提供重要的区别信息的语句。
(4)一些Controlling S_units也可以省略,如一些防止空指针异常的if语句。
4.3 S_unit选择过程
(1)识别same-action, ending和 void-return s_units,将它们添加到摘要集合中。
(2)对于摘要集合中的每个s_units,将其对应 的data-facilitating s_units添加到摘要集合中。
(3)用Controlling s_units来扩充摘要集合。
上述每一步都会进行s_units过滤。最后根据方法内的行号对摘要集合进行升序排序。
5.摘要注释文本生成
这一步的工作是将上述识别得到的s_units集合转化为自然语言。文本生成器首先为s_units中的参数构造子短语,然后为整个s_units连接这些子短语。
例:
在生成参数的短语时,论文提出的方法将尽可能生成更多包含描述性的短语。如上诉例子用通过variable lexicalization的手段生成“drawing view”代替“view”。(variable lexicalization具体怎么实现我也没发现哪里有提到)
对于与方法的主题或次要参数不对应的参数如CENTER就无需添加到注释中说明。
文本生成器在允许时组合短语,并删除摘要不需要的单词。如上述例子的getContentPane() and getComponent()的生成文本中删除了“get”,这一点前面的S_units过滤有提到。
基本的S_units是一个方法调用。在nested method calls, composed method calls, assignments, returns, conditional and loop expressions中使用单个方法调用的文本生成策略。下面描述的是如何将这些S_units中使用的变量词汇化。
(1)变量的词汇化
当将变量转换为英文名词短语时,通常将变量名称放在类型名称的左侧;当类型名称是一个形容词时,将变量名称放在右侧。
(2)单个方法调用
在Java中,方法用于实现一个操作,通常以动词短语开头。因此,作者为方法调用生成一个动词短语。动词短语的模板如下:
例子:
(3)返回操作
return s_unit是一个伪方法调用,其中操作是“return”,主题是方法的返回类型。
(4)嵌套的和组合的方法调用
一个s_unit可以包含像M2(M1(…)…)这样的嵌套调用或像M1.M2(…).这样的组合调用。当SWUM检测到 theme2 =return-type1时,用于文本生成的模板和例子如下:
当theme1 = return-type1,可以从一般模板中删除第二个短语,而不会丢失信息,使用方法M1的主题和次要参数作为方法M2的主题,例:
(5)赋值操作
给定一个赋值s_unit,的一般形式,如lhs=M(……)。文本生成模板如下:
由于赋值涉及到将返回类型赋给lhs,因此可以通过将模板中的第二个(get return-type)和第三个(assign to lhs)短语组合为“get lhs”来避免冗余,例:
当lhs与主题有重叠内容时,删除多余的“get lhs”来生成一个更简洁的短语,并在文本中使用更具体的一个lhs或主题,例:
作者仍然在完善赋值的模板,如赋值语句右值是一个表达式的情况。
(6)条件表达式
对于一个if s_unit,为其布尔表达式生成文本,该表达式控制另一个已标识的s_unit的执行。
- 当一个if表达式由多个通过运算符组合的布尔表达式组成时,为每个表达式生成文本并将它们组合起来。
- 当该表达式包含一个布尔变量时,只需在生成的文本中使用该变量名。当变量是字段和形容词时,SWUM生成类名作为名词:
- 当布尔表达式是一个方法调用时,识别主语并将动词放在主语后面。当方法名以第三人称单数动词开始时,将该主语标识为方法调用的接收对象(静态方法中的第一个参数)
- 当方法调用以助动词(如,is)开始时,主语一般包含在方法名中,或者是方法调用的接收对象或参数中。
- 当调用方法名以基本动词开始,返回值表示该操作的成功或失败时,在短语的末尾添加“成功”,将动词短语转换为命题句。
(7)循环表达式
- 对于while s_units,通常其循环条件表达式的文本类似if s_units。但是while循环经常使用迭代器进行迭代,仅仅依靠其循环条件表达式的文本时不够的,因此还要利用其对应迭代器的文本信息,例:
迭代器的识别:检查循环条件表达式中的方法调用是否具有类型名包含 “Iterator” 或 “Enumeration”的接收对象。
模板: “For each item in collection”。- 对于for循环,使用def-use链和语言线索(条件表达式中的“count”、“length”或“size”等单词)来标识生成模板的item和collection。例子如下:
原型实现:原型genSumm使用SWUM实现,是一个Eclipse插件,实现了s_unit选择过程和文本生成模板。
五、评估
主要围绕2个问题展开。
RQ1:How accurately does our generated text represent the code’s actions?
RQ2: How effectively can we automatically identify the s_units for the summary?
1.评分标准
由于没有现有的自动注释生成模型可以比较,邀请了13名计算机科学的研究生和博士后(有高级到中级的Java编程经验,其中六人在软件开发行业有工作经验)进行人工评判生成的注释,打分标准如下表:
2.实验数据集
- Megamek,一款非官方的经典棋盘游戏,有9300种方法和200KLOC;
- SweetHome3D,一个室内设计应用程序,有4000种方法和73种KLOC;
- JHotDraw,一个具有4300种方法和63种KLOC的技术和结构化图形的JavaGUI框架
- Jajuk,一个用2100种方法和44种KLOC来组织和播放音乐的应用程序。
3. s_units文本生成的评估
(1)步骤
- 随机选择s_units,确保每个新选的方法都覆盖了一个新的s_units类型,直到总共选完48个s_units。12位评估者没人都检查12个s_units,因此总共有144个s_units文本的判断。
- 为每个评估者提供了每个s_units对应方法的主体和整个源程序,并指导他们阅读和理解该方法的作用,然后为s_units编写他们自己的摘要。一旦受试者为一个s_units编写了摘要文本,他们就要检查系统自动生成的文本,并根据打分标准打分。
(2)结果,毫无疑问,很不错
4. 整个摘要的评估
(1)步骤
- 为6位评估者提供四种方法,每种方法来自四个数据集项目中的一个。共有3位评估者独立评判8条摘要注释(对应每个数据集项目随机挑选的2条),因此总共有24个方法摘要判断。
- 尽可能选取没那么容易阅读或理解的方法,且具有论文尚未解决特征的方法不选(如switch语句),选择的方法包含10到40个s_units。最后评分方式和先前的一样。
(2)结果,三个方面,还是相对比较OK的。
(3)摘要生成样例
系统生成的摘要基本和开发人员以及评估人员的一致。
六、有效性威胁
因为论文针对的是JAVA语言的自动注释生成,所设置的模板都是针对JAVA方法的一些特定情况,因此结果可能无法推广到其他Java程序或其他语言。
七、总结
论文提出了第一个自动生成摘要注释的技术,通过利用该方法中的结构和语言线索可以总结任意Java方法的主要动作。系统自动生成的摘要准确,无重要内容遗漏,且简洁。