Page 277 - 《软件学报》2026年第5期
P. 277

2156                                                       软件学报  2026  年第  37  卷第  5  期


                 码为抽象语法树      (abstract syntax tree, AST), 判断  h i  所包含的变更代码是否只包含空格、缩进、换行的变更或仅涉
                 及标识符    (变量名) 的变化. 若   ∆ AST (h i ) = 0, 则  h i ∈ H style ; 或  ∆ AST (h i ) , 0 且   ∆ NonID (h i ) = 0, 则  h i ∈ H style , 其中  ∆ AST (h i )
                     h i  变更前后  AST  的差异,  ∆ NonID (h i ) 非标识符节点的变更差异.
                 表示
                  2.2.3    变更依赖分析
                                      ∗
                    给定过滤后的变更集        H , DISAC  沿用变更代码分解中构建依赖关系的方法使用              JavaParser (https://javaparser.
                 org/) 进行静态程序分析, 将前一个程序和当前程序分别转换为相应的                  AST, 通过比较之前的     AST  和当前的   AST  之
                                                                                              D < H,E,T >
                 间的差异来提取细粒度的代码变更, 识别这些细粒度代码变更之间的依赖关系. 本文使用一个三元组
                 表示  hunk  之间的依赖关系. 其中     H  表示变更代码集, 其中每个元素代表一个具有唯一                ID  的变更代码块.   E  表示
                 H  中存在的依赖关系的集合,        E = {(s,t,τ)|( s,t) ∈ H×H, s , t,τ ∈ T} 表示  E  中的每一条边连接两个不同的代码变更
                                                                {      }
                 块, 并通过依赖属性进行描述. T        表示依赖边属性的集合,        T = T dep ,T sim , 共包含了两种依赖属性: 代码依赖   T dep  和
                 相似依赖   T sim . 与传统的变更代码拆解工作不同, DISAC       方法将依赖关系作为拆解的依据之一, 结合语义分析进一
                 步优化拆解过程. 因此仅使用依赖于代码的结构性依赖和相似性依赖关系, 避免了因过度细化依赖关系而导致的
                 过度合并风险.
                      T dep  是代码分解工作中常用的属性, 表示代码之间的继承、调用以及数据流等关系, DISAC                     复用这种传统的
                 依赖分析关系, 检测代码之间的依赖关系, 并将其映射到相应的变更子集上, 帮助识别变更之间的基础依赖结构.
                 此外, 本文使用    T sim  作为依赖关系的一种补充, 表示两个变更之间存在相似关系. 本文提出了一种结合文本相似性
                 和语法相似性的计算方法, 其计算公式如下:

                                                                )
                                                            (
                                                   (
                                                       )
                                                T sim h i ,h j = S txt h i ,h j +S ast (h i ,h j ).
                    文本相似性     S txt  基于字符级别的重合程度计算, 具体公式为:

                                                                   ( )
                                                           |C (h i )∩C h j |
                                                S txt (h i ,h j ) =  ( ) ,
                                                         max(|C (h i )|,|C h j |)
                                                                 ( )
                 其中,   C (h i ) 表示  h i  的字符集,  |C (h i )| 为该集合的大小,  C (h i )∩C h j  为两个变更块中共有的字符数量. 语法相似性


                 S ast  则通过比较  AST  节点的相似性来度量, 其公式如下:

                                                                   ( )
                                                           |N (h i )∩ N h j |
                                                S ast (h i ,h j ) =  ( ) .
                                                         max(|N (h i )|,|N h j |)
                                                                              ( )

                    类似地,   N (h i ) 表示  h i  的  AST  节点集合,  |N (h i )| 为节点集合的大小,  N (h i )∩ N h j  为两个变更块中共有的节点

                                                                 θ (在本文的研究中设置   为   θ            (   )
                 数量. 为了判断    h i  和   h j  是否具有相似关系, 引入了相似度阈值                           0.7), 当  T sim h i ,h j ⩾ θ
                                                   T sim .
                 时, 则认为   h i  和  h j  之间存在相似性依赖关系
                  2.3   代码变更拆解
                  2.3.1    预合并
                    为了尽可能避免大语言模型过细粒度的拆解打破变更子集的完整性, DISAC                        根据依赖关系对      DIC  中的变更
                 代码块进行初步的拆解与合并. 与传统方法不同               [22−24,28] , DISAC  的思想并非将所有具有代码依赖关系的变更都合
                 并为同一提交, 而是关注无法分割的强依赖关系, DISAC              定义了两种基于依赖关系的强依赖关系              R = {R circ ,R dep }.
                                                                                     ( (     )        )
                      R circ  是具有环状依赖的关系. 当两个或多个变更代码块        h i  和   h j  之间存在相互依赖时, 如   T h i → h j = T sim ∨T dep ∧
                                                                                   R circ h i ,h j . 这种依赖通常表
                                                                                          )
                                                                                      (
                 (T(h j → h i ) = T sim ∨T dep ), 则认为  h i  和  h j  之间存在具有环状依赖的强依赖关系, 记为
                 示  hunk  之间存在循环引用等紧密耦合结构, 本文采用            Tarjan  算法检测依赖关系图, 将形成环状依赖的变更合并为
                 一个不可拆分的块, 避免在后续拆解过程中破坏依赖闭包.
                      R dep  是与描述符和标识符变更相关的依赖关系. 标识符是指变量、方法、类、接口、包等的名称, 描述符是
                 字段的数据类型、方法的参数列表             (包括数量、类型以及顺序) 和返回值, 它们在代码中起着重要的链接作用,
                                                                       h i  更改了代码描述符或标识符, 且另一个代
                 当这些标识符或描述符被修改时, 往往会影响其他依赖它们的代码. 若
                                                                                                   (
                                                                                                       )
                 码块  h j  对它有代码依赖关系, 即   T( h j → h i ) =  T dep , 则   h i  和   h j  之间存在一种描述符相关的强依赖关系, 记为  R dep h i ,h j .
   272   273   274   275   276   277   278   279   280   281   282