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 .

