Page 274 - 《软件学报》2024年第4期
P. 274

1852                                                       软件学报  2024  年第  35  卷第  4  期


                    综上所述, BEEP    模型中的各个模块共同作用使该模型的有效性达到最优, 其中对代码令牌进行拆分后再进
                 行编码对模型有效性的提升最明显.

                  5   分析与讨论

                    在评估了    BEEP  方法在细粒度缺陷定位上的有效性后, 本节着重讨论如何构建基于细粒度缺陷定位的缺陷自
                 动修复技术并分析其有效性与效率.
                  5.1   基于细粒度缺陷定位的缺陷自动修复

                    在对当前的缺陷自动修复技术进行了系统调研后, 我们发现, 已有技术                       [37,42,45] 与当前缺陷定位技术有着高耦
                 合关系, 也即当前修复技术仅接收现有的语句级别的定位结果为输入, 后运用不同的算法生成新的正确语句. 因
                 此, 我们提出两种基于细粒度缺陷定位信息              (缺陷代码令牌) 的修复方案, 其工作流程如下.
                    ● 输入. 我们假定缺陷方法是已知的. 由于近期的方法级缺陷定位技术                     [1,31] 在定位效果上取得了较大进展, 因
                 此这是一个较为合理的假设.
                    ● 缺陷定位. 我们使用      BEEP  对输入的缺陷方法进行预测, 得到一个排序后的操作路径列表.
                    ● 操作路径选择. 已有研究表明, 搜索空间过大会降低修复工具的效率, 由表                      3  的结果, 绝大部分缺陷的标准
                 操作路径都出现在       BEEP  预测结果的前    20  条中, 因此我们在这一步中仅考虑前          20  条预测结果. 随后进行不断的
                 尝试, 每次按照排名顺序选取每条操作路径, 将其输入到下一阶段的补丁生成过程中, 如果尝试了所有                                20  条路径
                 但并没有生成能够通过所有测试用例的补丁, 则尝试将操作路径两两组合                        (例如, 将预测结果中的第一条和第二条
                 操作路径一同送入下一阶段). 为了限制搜索空间在合理的范围内, 本文提出的方法目前最多将两条路径组合在一
                 起. 当生成能够通过所有测试用例的补丁后, 则结束此过程.
                    ● 补丁生成. 在此阶段, 补丁通过一个代码补全技术或一套简单的启发式生成. 我们将在整个工作流程介绍完
                 后详细介绍这两种补丁生成方法.
                    ● 补丁验证. 生成的补丁通过执行测试用例进行验证. 当一个能够通过所有测试用例的补丁被生成后, 整个工
                 作流程被结束. 我们随后人工检验该补丁的正确性. 该过程通过人工对生成的补丁与开发人员提供的标准补丁进
                 行比对, 依据   Liu  等人  [3] 提出的补丁正确性评判规约, 检验生成的补丁是否与标准补丁具有语义一致性.
                    下面我们详细介绍两种补丁生成方法.
                    ● 基于代码补全的补丁生成. Alon        等人  [14] 提出了一种利用软件自然性的静态代码补全方法, AnyCodeGen, 能
                 够像预测自然语言中缺失的文本一样预测程序中缺失的代码元素. 实验结果表明该方法在                               Java 语言上的补全能
                 力显著优于包括序列到序列模型            (Seq2Seq) 在内的早期方法. 因此, 我们使用该方法生成补丁. 在获取到操作路径
                 后, 我们解析出其中的缺陷代码令牌与变换操作. 如果变换操作为                    DELETE, 我们直接删除该令牌; 如果变换操作
                 为  UPDATE, 我们移除原令牌后将缺陷方法作为输入传给               AnyCodeGen, 将其返回的代码补全结果作为补丁; 如果
                 变换操作为    INSERT, 我们在该令牌后添加占位符并调用            AnyCodeGen.
                    ● 基于启发式的补丁生成. 我们根据          BEEP  预测的缺陷代码令牌的类别设计了一套启发式规则用以生成补丁.
                    • 如果缺陷令牌是一个运算符, 将其变为另一个运算符                (  == → ! = >= → > ).
                                                                        ,
                    • 如果缺陷令牌是一个布尔值, 将其变为相反的布尔值                (false   → true).
                    • 如果缺陷令牌代表一种数据类型, 将其变为另一种数据类型                   (int   →  float).
                    • 如果缺陷令牌是一个普通标识符, 从缺陷方法的代码令牌序列中选取距离其最近的                            5  个用于生成补丁. 由
                 于  AnyCodeGen  针对代码补全仅返回     5  个候选补丁, 因此此处也仅考虑        5  个距离最近的代码令牌.
                  5.2   缺陷自动修复实验设置
                    为了分析基于细粒度缺陷定位的程序自动修复方案的修复效果, 我们在                         4  个常用的  Java 语言缺陷数据集上
                 进行实验, 分别为     Defects4J [10] , Bears [66] , QuixBugs [67] 以及  Bugs.jar [68] . 已有修复方法广泛地于这些数据集上进行测
                 评, 因此我们可以直接将修复结果与已有方法进行比较.
   269   270   271   272   273   274   275   276   277   278   279