【APR-自动代码修复】论文分享:PyTy

论文名称:PyTy: Repairing Static Type Errors in Python

论文链接:arxiv.org/abs/2401.06...

机构:斯图加特大学

Github代码链接:github.com/sreejadadis...

简介

本文提出了PyTy方法,针对Python语法中静态可检测类型错误的自动化程序修复方法。主要做了三个贡献:

  • 根据开源的Github仓库数据,调查开发人员的Python类型错误分布以及修复方式等。
  • 提出了一种自动提取类型错误修复的方法,能够从176个GitHub存储库中创建一个包含2,766个错误修复对的数据集,名为PyTyDefects。
  • 由于相对缺乏数据,PyTy 核心的神经模型通过跨语言迁移学习进行训练。

经过评测,PyTy 提供了针对 10 种常见类型错误的修复,成功解决了 281 个实际错误中的 85.4%。这种有效性优于要求修复类型错误的最先进的大型语言模型(2.1 倍),并补充了以前针对运行时出现的类型错误的技术。 最后,开发人员合并了 30 个带有 PyTy 建议修复程序的拉取请求中的 20 个,显示了 PyTy 在实践中的有用性。

Python类型检查器背景

2015年,python引入了类型注释的语法。目前流行的python类型检查器有Pyre, Mypy, Pytype, and Pyright等。不同的检查器可能会显示不同的类型错误。

本文的方法是通用的,但实验是建立在最流行的Pyre上面的。图1举了一些PyTy修复的类型错误例子,(b)通过交换参数修复了(a)的错误。(d)通过添加可选注释来修复了(c)的错误。

Preliminary Study

三个研究问题

首先,作者摆出了三个问题:

Q1: 实际开发中的类型错误和类型错误修复有多重复?

解释:指的是在编程过程中,程序员是否经常犯相同或类似的类型错误,以及他们是否通常采用相同或类似的方法来修复这些错误。

Q2: 确定给定类型错误的修复位置有多困难?

解释:主要是想看类型错误的修复位置分布情况,是集中在当前类型错误报出行,还是其他位置。

Q3:类型检查器提供的错误消息在修复类型错误时有多有用?

解释:主要是看检查工具提供的报错信息,对于修复错误是否真正有用以及能起多大用处。

为了给这三个问题寻找答案,作者进行了一些初步研究,包括收集数据+画分布图等。

数据收集

主要分以下三步收集数据:

  • Step 1:在Github上搜索请求帮助修复类型错误的问题。

关键字搜索相关的Request等。

  • Step 2:通过关键词"type+fix"、"pyre"和"mypy"在拥有超过100颗星的Python仓库中搜索提交。

所用的关键词跟类型错误比较有相关性。

  • Step 3:使用已有的10000个Python仓库中提取的数据集,该数据集包含与插入、移除或更新类型注释相关的编辑提交。

其实是加了一个数据源,应该是Step 1&2的数据量太少,不够研究。

收集完这些commit之后,就开始Clone仓库并在每次提交前后运行类型检查器。并移除了以下内容:

  • 删除整个函数或文件的修复,而实际上并没有修复类型错误。

解释:指的是在代码库中,为了解决一个类型错误,开发者选择了删除引起问题的代码部分(如一个函数或整个文件),而不是直接修正类型错误。这种做法虽然在技术上消除了错误(因为删除后,类型检查器不再报告那个错误),但它并没有真正地解决问题,只是简单地移除了引起问题的代码。

  • 与导入相关的警告,因为它们通常是由于类型检查器的搜索路径中缺少库。

解释:在研究类型错误修复时,研究者可能更感兴趣的是那些真正的类型不匹配或类型注释错误,而不是由于环境配置问题导致的警告。

  • 添加注释# pyre-ignore或# type:ignore来抑制类型检查器的警告的修复。

总的来说,作者从14个GitHub仓库中收集了125个类型错误修复,根据这些数据对之前提出的三个问题进行了解答。

三个问题的答案

  • Q1: 实际开发中的类型错误和类型错误修复有多重复?

Answer to Q1 :图2展示了125条数据的类型错误(左)和相关修复模式(右)分布图,可以看到不兼容的返回类型、变量类型和参数类型是最常见的错误类型 ,占比64.8%。除了分布情况,该图还表明从类型错误类别到修复模式没有简单的映射关系。最常见的关系是不兼容的返回类型通过修改函数返回类型的模式修复(14.4%),以及不兼容的参数类型通过修改函数参数类型的模式修复(13.6%)。然而,同一类类型错误也可能通过应用其他几种修复模式来解决。

  • Q2: 确定给定类型错误的修复位置有多困难?

Answer to Q2 :据图2中修复模式的分类,可以看到大多数修复都是单行编辑 ,例如将一个类型注解从一个类型修改为另一个类型、更改操作符、移除类型注解或添加类型转换。作者还研究了修复的位置(见图4a),超过一半的修复发生在报告类型错误的那一行,其他位置包括函数参数、返回注解和函数调用者(即被调用的函数)

  • Q3:类型检查器提供的错误消息在修复类型错误时有多有用?

Answer to Q3 :在125个类型修复中,有89个(占71.2%)是由类型检查器正确提示的。这些提示的类型可以作为自动程序修复(APR)工具的参考,以缩小搜索范围。正确提示的代码更改类型显示在图4b中,图4c展示了开发者如何使用正确提示的类型。

通过做这个初步研究,可以带来如下结论:

  • 虽然类型错误和修复呈现重复的模式,但从错误到修复模式的映射是模糊的,所以需要构建一个模型,从开发者执行的修复中学习何时应用哪种修复模式
  • 大多数类型错误能够通过编辑单行代码来修复的,而且这一行通常能被类型检查器准确定位。所以,可以把研究重点集中在单行编辑的类型错误修复上,并利用类型错误位置提供的定位提示
  • 研究将错误信息作为输入提供给所提出的方法

具体方法

框架概述

图5展示了整个流程,分为两个阶段:

  • Stage 1:离线阶段,主要是收集数据&微调。

通过结合增量调试和渐进式类型检查,从GitHub自动收集一个类型错误修复的数据集,作者称为PyTyDefects,然后用PyTyDefects对预训练模型[5]进行微调。

  • Stage 2:在现阶段,主要是验证模型的结果是否成功解决了类型错误。

PyTy接收带有类型错误的代码作为输入,然后调用模型以获取修复候选方案。该方法使用类型检查器来验证应用修复候选方案后是否解决了类型错误,并且只报告确保消除目标类型错误的修复。

数据收集

跟初步研究中的步骤一样,大概分为以下几步:

  • Step 1:从Github上搜索目标仓库。

作者在GitHub上搜索了2010年至2021年间创建的、受欢迎的(≥100星)、大小适中(≤5GB)的Python仓库。

  • Step 2:在目标仓库里面搜索目标相关提交。

作者使用"fixing+typing"、"fixing+pyre"、"fixing+mypy"、"typing+bug"和"typing+error"等关键词来搜索可能移除类型错误的提交。

  • Step 3:使用类型检查器确认提交确实修复类型错误,入库。

作者在每个这样的提交前后运行类型检查器,以找到确实移除了类型错误的提交。最终获得了32,330个被4,515个提交在176个GitHub仓库中移除的类型错误。

在收集错误的过程中,作者发现一个问题,即许多提取出的提交包含与修复类型错误不直接相关的更改,而且单个提交通常修复多个类型错误。图6展示了相关例子,所以为了隔离单个类型错误的修复,作者提出了一种受delta调试启发的算法[54],该算法将提交减少为修复单个类型错误的小的代码更改。基本思想是在保留代码更改修复特定类型错误的事实的同时,迭代减少代码块的集合,具体过程看Algorithm 1。

在32330个类型错误上运行算法后,得到11955个简化的错误修复示例。为了进一步筛选这些修复,保留符合以下条件的修复:

  • 相对较小,≤512个字符且最多三行更改。
  • 不包含错误抑制和删除问题代码。
  • 位于报告的错误位置附近(即在同一个代码块内)。

最终,PyTyDefects包含,766个条目,涵盖了十种常见的类型错误。在这个最终数据集中,每个错误类别的10%(向上取整到最接近的整数)作为测试集,其余的修复分为90%用于训练,10%用于验证。

实验部分

模型训练

此块为训练模型的环节,不是单独训了一个神经网络模型,而是基于在104804个JavaScript代码样本上训练过的TFix模型上进行微调的。微调的输入是包含类型错误的一行或多行代码(即单个代码块),输出是修复该类型错误的代码。

关键结果

研究者通过测试集上的十种类型错误来评估PyTy的有效性,配置了最多50个候选修复方案。使用两个指标来评估PyTy的有效性:错误移除率(成功找到修复方案并移除目标类型错误的频率)和精确匹配率(模型输出与开发者提交的修复方案完全一致的频率)。

PyTy成功地消除了85.4%的错误类型,并且在所有错误中找到了54.4%的开发者提供的修复方案。

总结

  • 基于xx的微调训练模式还是较为通用,从0->1训练一个特定任务模型必要性不大。
  • 每个代码语言的静态类型错误还是有区别的,如果要稳妥的提升效果,还是需要一步一步来,挨个语言提升效果,后续扩充语言可以将具有相似类型错误的语言归为一类等。
  • 数据生成与清洗:仍然是重中之重,先从开源仓库中获取目标数据,再通过相关工具去筛选验证数据是否有效,并忽略一些低质量&不相关的数据。
  • 静态类型检查到的错误信息非常有用,并且大部分情况下的修复都是集中在错误报出行。
相关推荐
码破苍穹ovo1 小时前
二分查找----1.搜索插入位置
数据结构·算法
烨然若神人~2 小时前
算法第38天|322.零钱兑换\139. 单词拆分
算法
sukalot2 小时前
window显示驱动开发—输出合并器阶段
驱动开发·算法
fei_sun3 小时前
【编译原理】语句的翻译
算法
Xの哲學3 小时前
hostapd 驱动注册机制深度分析
linux·网络·算法·wireless
int型码农4 小时前
数据结构第八章(六)-置换选择排序和最佳归并树
java·c语言·数据结构·算法·排序算法
@我漫长的孤独流浪4 小时前
数据结构----排序(3)
数据结构·c++·算法
ggdpzhk5 小时前
输入两个正整数,计算最大公约数和最小公倍数
java·算法
weixin_307779137 小时前
波动方程兼容性条件分析
算法