Page 288 - 《软件学报》2024年第6期
P. 288
2864 软件学报 2024 年第 35 卷第 6 期
近年来, 代码仓库如 GitHub (https://www.github.com/)、Gitee (https://gitee.com/) 和 Bitbucket (https://www.
bitbucket.org/) 中的开源项目呈井喷式增长, 优质的代码资源数量变得非常庞大, 如何准确高效地从代码仓库中
搜索出符合程序员需求的代码, 是当前软件工程和自然语言处理交叉领域的热点研究方向之一. 与二进制代码
搜索输入代码片段不同, 本文研究的目标是面向自由文本的代码搜索, 即输入一个描述代码片段功能的查询语
句 (人类自然语言), 代码搜索任务是从大型代码库中找到最匹配的代码片段. 代码搜索工具不仅可以帮助程序
开发人员找到常见程序功能的代码范例, 也可以帮助他们快速搜索其他开发者编写的个性化功能的优质代码
片段, 这在很大程度上提高了程序开发人员的工作效率. 此外, 代码搜索技术现已成为程序合成、代码推荐与
补全以及代码风格改善等程序构造技术的重要支撑 [1] . 代码搜索的简要流程图如图 1 所示.
Front-end Back-end Recommended code snippets
GitHub Gitee Bitbucket
C-VAE
Search engine IDE
How to convert a string
Code snippets
Retrieval modeling Indexing
database
图 1 代码搜索的流程图
早期的研究大部分基于传统的信息检索技术. Bajracharya 等人 [2] 提出的 Sourcerer 以代码属性和其受欢迎程
度作为评估指标, 结合 TF-IDF 统计方法返回推荐的代码片段. McMillan 等人 [3] 提出的代码搜索系统 Portfolio 基
[5]
于关键字匹配得到程序员所需的功能性函数. Lu 等人 [4] 利用 WordNet 生成的自然语言查询同义词作扩展查询,
并对代码片段的方法签名进行关键字匹配. Lv 等人 [6] 提出的 CodeHow 算法考虑文本相似性和潜在 API 对代码搜
索的影响, 并基于扩展查询和布尔模型搜索代码库. 黎宣等人 [7] 对代码片段基于提取的方法调用和结构特征作描
述增强, 利用 Lucene 进行在线查询.
基于传统信息检索技术的代码搜索方法将查询语句和源代码均视为文本进行关键词匹配, 主要有两个缺点:
一是自然语言具有普遍的歧义性, 对其进行语义理解的准确性不高; 二是忽略了代码片段的深层结构特征. 为了解
决上述问题, Gu 等人 [8] 首次将深度学习技术应用于代码搜索, 提出的 DeepCS 从方法名称、API 调用序列和源代
码中包含的 token 信息 3 个角度表示源代码, 利用长短期记忆网络 (long-short term memory, LSTM) 提取相应特征,
丰富了代码层级的语义, 查询语句经过 RNN 编码模型得到相应嵌入. 相比于传统的 Sourcer 和 CodeHow ,
[1]
[6]
DeepCS 显著提升了搜索效果.
DeepCS 的提出启发了更多软件工程的研究者应用深度神经网络解决代码搜索这一任务. Yao 等人 [9] 提出了
一种基于 sequence-to-sequence (Seq2Seq) 的代码注释生成工具 CoaCor, 可以生成用于代码搜索的良好注释. Chen
等人 [10] 提出了 BVAE 框架, 用两个变分自动编码器 和 L-VAE 分别表示代码片段和自然语言描述, 该方法
旨在通过联合训练学习代码片段和自然语言描述的分布式向量表示. Wan 等人 [11] 提出了一个新的多模态注意力
网络 MMAN, 并将其应用于代码搜索. 该网络由一个 LSTM, 一个 Tree-LSTM 和一个门控图神经网络组成, 分别
用于代码的顺序标记, 代码的抽象语法树 AST 生成和控制流图的表示.
然而, 上述基于深度学习的方法只能捕捉到代码片段的浅层信息. 许多源程序可能存在各种长程依赖特征, 例
如相同的标识符在源代码的多处进行关键性操作. 由于代码片段存在各种复杂的数据流, LSTM 等序列编码模型
无法捕捉源代码的深层语义. 为了捕捉代码的深层结构信息, 学者们尝试用图数据表征代码片段的结构. 凌春阳等
人 [12] 用 LINE 算法 [13] 嵌入代码图, 词袋模型嵌入语言查询, 并通过代码子图的搜索来匹配文本查询节点. 黄思远等
人 [14] 基于重标签算法提取程序依赖图中的子图结构信息, 并基于 Doc2Vec 的思想将子图结构作为上下文信息得