FixMiner:挖掘相关的修复模式以实现自动程序修复

FixMiner:挖掘相关的修复模式以实现自动程序修复–翻译记录

Anil Koyuncu1·Kui Liu1·Tegawendé F. Bissyandé1·Dongsun Kim2·
Jacques Klein1·Martin Monperrus3·Yves Le Traon1
Springer Science+Business Media, LLC, part of Springer Nature 2020

摘要

打补丁是软件开发中的常见活动。它通常在源代码基础上执行,以解决bug或添加新功能。在这种情况下,如果bug在项目之间反复出现,可以利用相关的类似补丁来提取通用的修复操作。虽然文献包括利用补丁之间的相似性来指导程序修复的各种方法,但这些方法通常不能产生可处理和可重用的修复模式,作为APR系统的可操作输入。在本文中,我们提出了一种系统的、自动化的方法来挖掘相关的、可操作的修复模式,该方法基于应用于补丁内部原子变化的迭代聚类策略。FixMiner的目标是推断独立的、可重用的补丁模式,这些模式可以在其他补丁生成系统中使用。我们的技术FixMiner利用了Rich Edit Script,这是一种专门的编辑脚本树结构,它捕获了代码更改的ast级上下文。FixMiner对每一轮集群使用Rich Edit Scripts的不同树表示来识别类似的更改。它们是抽象语法树、编辑操作树和代码上下文树。我们已经对从开源项目中收集的数千个软件补丁进行了FixMiner的评估。初步结果表明,我们能够挖掘准确的模式,有效地利用富编辑脚本中的变化信息。我们进一步将挖掘的模式集成到一个自动程序修复原型PARFixMiner中,通过它,我们能够正确地修复Defects4J基准测试的26个bug。除了这一量化性能,我们还表明挖掘的修复模式能够产生具有高概率正确性的补丁:81%的PARFixMiner生成的似是而非的补丁是正确的。
关键词:修复模式·补丁·程序修复·调试·经验软件工程

1.介绍

代码更改模式在软件工程领域有多种用途。它们主要用于标记变化(Pan et al.2009)、对开发者提交的事项进行分类(Tian et al. 2012)或预测变化(Ying et al.2004)。近年来,修复模式在软件维护社区中得到了很大的利用,尤其是在构建补丁生成系统方面,这现在吸引了越来越多的兴趣(Monperrus2018)。自动程序修复(APR)确实获得了令人难以置信的势头,并采用了各种各样的方法(Nguyen et al.2013;是2009年1月;L e G u e s e t L .2012a;Kim等人2013;科克和Hafiz2013;2015年;Mechtaev et al.2015;Long和Rinard2015, 2016;L e e a L 2016a b,2017;C h e e t l .2017;长et al.2017;X u a n e t a l .2017;熊等al.2017;江等al.2018;温等al.2018;华等al.2018;Liu等人2019,b)提出,旨在通过自动生成补丁来减少人工调试工作量。自动程序修复中常见且可靠的策略是根据修复模式(Kim et al.2013)(也称为修复模板(Liu and Zhong2018)或程序转换模式(Hua et al.2018)生成具体的补丁。几个APR系统(Kim et al.2013;这是一个时间,2017;Durieux et al.2017;刘和Zhong2018;H u a等。2018;马丁内斯和Monperrus2018;Liu等人2019,b)在文献中,通过使用通过手工生成或自动挖掘bug修复数据集获得的各种修复模式集来实现这一策略。
在PAR (Kim et .2013)中,作者通过手工检查60,000个开发者补丁来挖掘修复模式。类似地,对于Relifix (Tan和Roychoudhury2015),需要对73个真实的软件回归bug修复进行手动检查,以推断修复模式。然而,手动挖掘是乏味的,容易出错,而且无法扩展。因此,为了克服手动模式推断的局限性,几个研究小组已经开始了自动推断bug修复模式的研究。在Genesis (Long et .2017)中,Longet提出了一种用于补丁生成的自动推断代码转换的方法。创世纪从577个采样转换的空间中推断出108个带有特定代码上下文的代码转换。然而,这项工作将搜索空间限制在以前成功的补丁中,这些补丁只有Java程序的三类缺陷:空指针、越界和与类强制转换相关的缺陷。
Liu和Zhong (Liu and Zhong2018)从Stack Overflow的Q&A文章中提出了SOFix来探索Java程序的修复模式,它基于GumTree (Falleri et al.2014)编辑脚本挖掘模式,并基于修复模式同构构建不同的类别。然后SOFix从每个类别挖掘一个修复模式。然而,作者指出,大多数类别都是多余的,甚至是不相关的,主要是由于两个主要问题:(1)相当一部分代码示例的设计目的不是修复bug;(2)由于底层的GumTree工具依赖于结构位置来提取修改,这些“修改不能呈现理想的语义映射”。他们依靠启发式来手动过滤类别(例如,包含多个修改的类别),然后在SOFIX挖掘修复模式之后,他们必须手动选择有用的模式(例如,由于语义相似而合并一些修复模式)。
Liu et al. (2018a)和Rolim et al.(2018)分别提出从FindBugs和PMD的静态分析违规中挖掘修复模式。这两种方法在推理过程中都利用了类似的方法。Rolim等(2018)依赖于编辑脚本之间的距离:它们之间距离较低的编辑脚本根据定义的相似度阈值分组在一起。另一方面,Liu et al. (2018a)利用深度学习来学习编辑脚本的特征,寻找相似的编辑脚本集群。最终,经验软件工程(2020)25:20 80 - 20241981这两个作品都没有在他们的编辑脚本中考虑代码上下文,而是手动地从补丁的类似编辑脚本的集群中得出修复模式。
另一方面,CapGen (Wen et al.2018)和SimFix (Jiang et al.2018)提出使用代码变更动作的频率。前者用它来驱动补丁选择,后者用它来计算捐助方代码相似度来确定补丁的优先级。然而,在这两种情况下,模式的概念都不是可操作的工件,而是指导补丁生成系统的补充信息。虽然我们同时与SimFix和CapGen共享为补丁生成添加更多上下文信息的想法,但我们的目标是推断出可操作的补丁模式,这些模式是可处理和可重用的,可以作为其他APR系统的输入。
表1概述了在文献中实现的各种自动挖掘策略,以获得不同的修复模式集。一些策略直接作为APR系统的一部分呈现,而其他的是独立的方法。我们通过考虑差异表示格式、上下文信息的使用、模式的可跟踪性(即,在补丁生成系统中它们在多大程度上是独立的和可重用的组件)和挖掘的范围(即,范围是否限于特定的代码更改)来描述不同的策略。总的来说,虽然文献方法可以方便地发现不同的修复模式集,但实际情况是,修复模式的复杂性和挖掘策略的泛化性仍然是为程序修复导出相关模式的一个挑战。
本文:我们建议研究挖掘相关的修复模式的可行性,这些修复模式可以很容易地集成到一个基于模式的自动程序修复系统中。为此,我们提出了一种迭代的、三重的集群策略FixMiner,以自动地从实际开发人员修复中的原子更改中发现相关的修复模式。FixMiner是一种模式挖掘方法,用于为程序修复系统生成修复模式。我们在本文中提出了富编辑脚本的概念,它是编辑脚本的一种专门的树状数据结构用于捕获代码更改的ast级上下文。为了推断模式,FixMiner利用相同的树,这些树是基于rich Edit scripts为每一轮迭代编码的以下信息计算的:抽象语法树、编辑操作树和代码上下文树
贡献:我们建议FixMiner模式挖掘工具作为一个独立的、可重用的组件,可以在其他补丁生成系统中使用。
论文内容:我们的贡献是:
-我们介绍了模式推理系统FixMiner的架构,它建立在三次聚类策略的基础上,在该策略中,我们迭代地发现基于不同树表示编码上下文、更改操作和代码标记的类似更改。
-我们通过在43个开源项目的11416个补丁中挖掘修复模式来评估fixminera发现模式的能力。我们进一步将发现的模式与那些可以在程序修复社区使用的数据集中找到的模式联系起来(Just et .2014)。我们评估了FixMiner模式与文献中的模式的兼容性。
-最后,我们通过将其作为自动程序修复系统的一部分来调查挖掘的修复模式的相关性。我们在Defects4J基准测试上的实验结果表明,我们挖掘的模式可以有效地修复26个错误。我们发现FixMiner模式是相关的,因为它们可以生成大部分是正确的补丁。

2.动机

近年来,挖掘、枚举和理解代码更改已经成为软件维护的一个关键挑战。十年前,Pan等人手工编制了一个与bug修复相关的27种代码变更模式的目录(Pan et al.2009)。然而,这样的“bug修复模式”是通用模式(例如,If - rmv:删除If谓词),它代表了经常修复bug的变更类型。最近,由于新的AST差异工具的可用性,研究人员提出了自动挖掘变化模式(Martinez等。2013;奥斯曼等al.2014;Oumarou et al.2015;Lin et al. 2016)。这些模式主要用于分析和理解bug修复的特征。然而,在实践中,推断的模式可能被证明是不相关的和难以处理的。
然而,我们认为挖掘修复模式可以帮助指导补丁生成的突变操作。在这种情况下,需要挖掘可以附加修复语义的真正周期性的更改模式,并提供在实践中可操作的准确的、细粒度的模式,即分离并作为其他流程的输入进行重用。我们的直觉是,相关模式无法在全球范围内挖掘,因为在野外修复的bug由于复杂的变化而受制于嘈杂的细节(Herzig和Zeller2013)。因此,需要将补丁分解为原子单元(连续的代码行形成一个块),并解释代码更改在它们之间的递归性。为了挖掘变化,我们建议依赖于编辑脚本格式,它提供了代码变化的细粒度表示,其中包括不同层次的信息:
-上下文,即被更改的代码元素的AST节点类型(例如,声明语句中的修饰符,不应推广到其他类型的语句);
-变更操作(例如,“先删除再添加”的顺序不应与“先添加再删除”的顺序混淆,因为它在AST等层次模型中可能有不同的含义);
-和代码标记(例如,将调用更改为“Log”。不应该与任何其他API方法相混淆)。我们的想法是迭代地找到上下文中的模式,每个上下文中的更改操作模式,以及这些操作中经常受到影响的文字的模式。我们现在提供背景信息来理解FixMiner的执行以及FixMiner所处理的信息。

2.1 抽象语法树

代码表示是程序分析和验证的重要步骤。抽象语法树(Abstract syntax trees, ast)通常是为程序分析和转换而产生的,它是一种数据结构,提供了一种表示程序结构的有效形式,以便进行语法甚至语义方面的推理。AST的确代表了所有的语法元素的编程语言和关注的规则而不是元素(如括号或分号终止语句在一些流行的语言比如Java或c AST是元素的层次表示递归地分解成每个编程语句他们的部分。因此,树中的每个节点表示在编程语言中出现的一个构造。
形式上,设t为AST, N为t中AST节点的集合。一个AST t有一个根,该根是root(t)∈N的节点。每个节点n∈n(和n?=root (t))有一个亲本,记为parent(n)=p∈n。注意,没有root(t)的父节点。此外,每个节点n有一组子节点(记为children(n)⊂n)。一个标签l(即。, AST节点类型)从一个给定的字母L分配给每个节点(label(n)= L∈L)。最后,每个节点都有一个字符串值v(令牌(n)=v,其中n∈n, v是一个任意字符串),表示相应的原始代码令牌。**考虑图1中Java代码的图2中的AST表示。**我们注意了AST节点与标签匹配的Java语言的结构元素(如MethodDeclaration, IfStatement orStringLiteral),可以与值代表原始标记的代码(例如,一个节点labelledStringLiteralfrom AST相关价值“嗨!”)(图2)。
在这里插入图片描述
在这里插入图片描述

2.2 代码差分

区分一个程序的两个版本是所有软件演化研究的关键预处理步骤。必须以一种使开发人员易于理解或分析变更的方式捕获演化的部分。开发人员通常能很好地处理基于文本的差异工具**,比如如图3所示的GNU Diff表示添加和删除源代码行的更改。**这种基于文本的差异的主要问题是,它没有提供更改的细粒度表示(即StringLiteral Replacement),因此不适合系统地分析更改。
在这里插入图片描述

为了解决代码差异的挑战,最近提出了基于树结构(如AST)的算法。ChangeDistiller和GumTree就是这种算法的例子,它们生成编辑脚本,这些脚本详细描述了要在给定AST的节点上执行的操作(如第2.1节所述),从而生成与新版本代码相对应的另一个AST。特别地,在此工作中,我们基于GumTree的核心算法来准备编辑脚本编辑脚本是描述以下代码更改操作的编辑操作序列:
-UPDwhere an upd (n, v)action通过将AST节点的旧值替换为新值ev来转换AST。
-INSwhere an ins(n, np,i,l,v)动作插入一个新的节点值和las标签。如果指定了parentnpi,则nis作为np的子节点插入,否则将是根节点。
-DELwhere a del(n)动作从树上移除叶子节点。
-MOV where a mov(n, np,i)动作移动有节点根的子树,使其成为父节点的子树。
编辑操作,嵌入关于节点(即解析程序的整个AST树中的相关节点)、操作符(即UPD、INS、DEL、n dMOV)的信息,描述所执行的操作,以及在更改中涉及的原始标记

2.3 混乱的代码更改

每个补丁解决一个问题通常被认为是促进维护任务的最佳实践。然而,现实项目中的补丁经常在一个补丁中解决多个问题(Tao和Kim2015;Koyuncu et al.2017)。开发人员经常提交bug修复代码更改,同时提交与修复无关的更改,如功能增强、特性请求、重构或文档。这种补丁被称为纠结补丁(Herzig和Zeller2013)或混合用途的修复提交(Nguyen et .2013)。Nguyen等人发现,用于挖掘档案的所有固定提交中有11%到39%是纠结的(Nguyen et al.2013)。
考虑图4中所示的来自GWT的示例补丁。这个补丁的目的是修复当页面以某种mime类型(例如,application/xhtml+xml)服务时,在某些web浏览器中报告了一个失败的问题。开发人员通过在遇到此类mime类型时显示警告来修复这个问题。然而&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值