一种考虑代码语句顺序信息的代码片段推荐方法与流程

文档序号:17441125发布日期:2019-04-17 04:46阅读:233来源:国知局
一种考虑代码语句顺序信息的代码片段推荐方法与流程

本发明涉及代码推荐,具体涉及一种考虑代码语句顺序信息的代码片段推荐方法。



背景技术:

代码片段是指一组代码序列,其能够指导开发人员快速的掌握某一程序接口的使用方式或某一编程任务的实现方法。近年来,代码推荐方向的研究均着重于如何使用信息检索或机器学习的方式来进行代码推荐。这些研究所使用的代码特征相对单一,均着重使用代码的文本信息。以rosf为例,在数据准备阶段,其首先使用将java工程切分为多个类文件,之后再将类文件切分多个代码片段。之后,针对每一个代码片段,其使用主题模型、代码度量等方式抽取代码片段的三方面的特征:文本特征、主题特征和结构特征。该方法的推荐阶段可细分为两阶段:粗粒度的查询和细粒度的重排。在粗粒度的查询阶段,其首先使用信息检索的方法,将代码文本特征和用户输入的查询进行相似度比较计算,从而得到与用户输入查询最为相关的一组代码片段。而后,在细粒度的重排阶段,针对在第一阶段得到的一组代码片段,使用机器学习的方法,对其进行细粒度的重排,并最终将排序结果返回给用户。

编程上下文是指开发者当前正在编写的一段代码片段,其可能是不完整的,不正确的,但是其仍然在一定程度上反映了开发者在本方法中希望实现的功能和实现该功能的思路,使用编程上下文中的信息进行推荐能够使得推荐结果更为符合开发者当前的需求同时因为其不需要开发者重新手动构建查询,其也进一步简化了查询过程。近年来,使用编程上下文进行代码推荐的研究大多将编程上下文当成没有结构信息的纯文本数据,并使用自然语言处理的相关方法对其进行处理,之后,使用信息检索和机器学习等方法进行当前编程上下文和代码片段库中的代码片段之间的相似度计算,并根据计算结果进行推荐。

代码语句的顺序信息指的是某一代码片段中各行代码之间的顺序关系。如下面的代码所示:

1log.error(empty_line);

2log.error(stringbuilder.tostring());

3log.info("droppingandrecreatingdb");

这个代码片段中有3行代码,我们将其当前的顺序:第一行语句("log.error(empty_line);")在第二行语句("log.error(stringbuilder.tostring());")之前;第二行语句("log.error(stringbuilder.tostring());")在第三行语句("log.info("droppingandrecreatingdb");")之前。认为是这个代码片段的顺序信息。因为代码的执行是有序的,即使是相同的代码语句,但是执行顺序的不同也会带来结果和功能的不同。

完整的推荐过程通常可以分为两个子步骤:查询过程和排序过程。其中,查询过程是指通过查询、推荐算法在构建的代码库中查询、搜索与输入相关的代码片段,其通常返回一组有序的与输入相似的代码片段。排序过程是指在通过排序方法将查询过程中得到的代码片段进行进一步的筛选以及重新排序的过程,其通常返回一组重新排序后的代码片段。现有代码推荐技术多使用代码文本信息进行相关推荐,仅使用文本信息进行代码推荐将会造成代码本身的结构信息和顺序信息的丢失,从而造成推荐结果的不准确。并且现有代码推荐技术没有充分考虑最后推荐结果与当前编程上下文之间的相似性,会导致最终排序效果不佳。



技术实现要素:

发明目的:针对现有技术的不足,本发明的目的在于提供一种考虑代码语句顺序信息的代码片段推荐方法,提高推荐的准确性,使用户能够更好的使用推荐的代码片段。

技术方案:为实现上述发明目的,本发明采用如下技术方案:

一种考虑代码语句顺序信息的代码片段推荐方法,包括如下步骤:

(1)获取当前代码上下文,包括当前正在编辑的方法信息和当前光标位置前后的若干行代码信息,进行格式化、结构信息和声明的变量类型提取,并将清理后的代码片段转化为lc序列;

(2)计算代码数据库中代码片段和当前代码上下文的bwt相似度和变量类型相似度,从代码数据库中获取若干与当前代码上下文相似度最高的代码片段作为候选集;所述代码数据库中包括从java应用程序项目中抽取的若干格式化代码片段以及格式化代码片段的结构信息、声明的变量类型以及lc序列;

(3)根据候选集中代码片段与当前代码上下文的bwt相似性、变量相似性和结构相似性对候选代码片段进行重新排序,并向用户呈现重新排序的列表。

作为优选,所述步骤(2)中根据如下公式计算代码数据库中代码片段与当前代码上下文的相似度:

codesimilarity(csn,csm)

=α1*bwtsimilarity(csn,csm)+α2

*variabletypesimilarity(csn,csm)

其中,codesimilarity(csn,csm)表示两个代码片段csn和csm之间的代码相似度;bwtsimilarity(csn,csm)和variabletypesimilarity(csn,csm)为两个代码片段之间的bwt相似度和变量类型相似度;α1,α2为权重因子;

其中,length(seedsequence)是当前代码上下文生成的lc序列的长度;linesimilarityi是指代码段csn和csm第i行的相似度;n1为代码段csn中的代码语句数量;

其中,variabletypen和variabletypem分别表示csn和csm中变量类型的集合。

作为优选,所述步骤(2)中根据如下公式计算两个代码语句的相似度:

其中,linesimilarity(cli,clj)表示代码语句cli和clj之间的相似度;qtn是第n的词牌tokenn在cli中出现的次数;tn是tokenn出现在clj中的次数;ql是cli的长度;dl是clj的长度;avgdl是代码数据库中代码语句的平均长度;n为cli中词牌的总数量;b、k1、k2是调整因子。

作为优选,所述步骤(2)中采用滑动窗口匹配方法计算代码数据库中代码片段和当前代码上下文的bwt相似度,在匹配时不只是将种子序列的当前元素与频率序列的当前元素匹配,如果当前元素不被视为匹配,将种子序列的当前元素附近的元素与频率序列的当前元素附近的元素进行匹配;其中种子序列是由当前代码上下文生成的lc序列,频率序列是代码数据库中存储的由代码片段生成的lc序列。

作为优选,所述步骤(3)中根据如下公式计算排序分数:

rankscore(csn,csm)=α3*codesimilarity(csn,csm)+α4*ss(csn,csm)

其中,rankscore(csn,csm)表示两个代码片段csn和csm之间的排序分数;codesimilarity(csn,csm)和ss(csn,csm)为两个代码片段之间的代码相似度和结构相似度;α3、α4为权重因子;

其中,lcs()为最长子序列算法,jacard()表示jacard相似度算法;分别表示代码片段csn和csm的方法名;分别表示代码片段csn和csm的返回值;分别表示代码片段csn和csm的参数集合;分别表示代码片段csn和csm的变量名集合;β1、β2、β3、β4为权重因子。

作为优选,所述方法根据如下数据处理步骤生成代码数据库:

从java应用程序项目中抽取java文件,解析每个java文件,抽取方法级别代码片段,并进行格式化,将格式化代码片段存储在数据库中;

收集格式化代码片段的结构信息,包括:代码片段所属的方法的名称,代码片段所属的方法的返回值,代码片段所属的方法的输入参数和该代码片段所属的方法中声明的变量名称;

抽取格式化代码片段中的所有变量声明语句,并将这些变量声明语句在格式化代码片段中删除,并将清理后的代码片段中的所有变量的变量名替换为其原本的变量类型;

利用bwt算法的转换步骤将清理后的代码片段转换为lc序列。

有益效果:本发明在进行代码推荐时考虑使用了代码语句之间的顺序信息,使得推荐的代码片段与查询之间的相似度更高,用户能够更好的使用推荐的代码片段。同时,在最后的排序过程中引入了结构信息,使其能够获得更好的排序的效果。

附图说明

图1为本发明实施例的方法流程图。

图2为本发明实施例中滑动窗口匹配示意图。

具体实施方式

下面结合附图和具体实施例对本发明做进一步说明。

如图1所示,本发明实施例公开的一种考虑代码语句顺序信息的代码片段推荐方法主要涉及两个阶段,数据处理阶段和推荐阶段,其核心在于推荐阶段。

在数据处理阶段,输入是从开源软件托管平台github收集的开源java应用程序项目,输出是代码数据库,该代码数据库由4部分组成:格式化代码片段,声明的变量类型,结构信息和lc序列(lastcolumnsequence,lc序列指的是将清理后的代码片段作为输入,经由bwt算法的转换步骤生成的新的序列)。其具体步骤可分为5步:

1)从java应用程序项目中抽取java文件并将它们存储在存储库中。其次,解析每个java文件,抽取方法级别代码片段,然后利用eclipse提供的codeformatter将代码片段的编程风格统一至预先定义的编程风格,我们称这些编程风格统一后的代码片段为格式化代码片段。并将这些格式化代码片段存储在数据库中,这是我们代码数据库的第一部分-格式化代码片段;

2)收集格式化代码片段的结构信息,其中包括:该代码片段所属的方法的名称,该代码片段所属的方法的返回值,该代码片段所属的方法的输入参数和该代码片段所属的方法中声明的变量名称。这一步骤我们利用ast中提供的解析器来完成,我们将这些信息组织为代码数据库的第二部分-结构信息;

3)抽取格式化代码片段中的所有变量声明语句,统计其声明的变量类型信息,并将这些变量声明语句在格式化代码片段中删除。而抽取的变量声明为代码数据库的第三部分-声明的变量类型。同时,我们称抽取了变量声明语句的格式化代码片段为清理后的代码片段。并将清理后的代码片段中的所有变量的变量名替换为其原本的变量类型。形如:若格式化代码片段为

“loglog=newlog;log.error(stringbuilder.tostring());”,则清理后的代码片段为“log.error(stringbuilder.tostring());”。本步骤同样由ast中提供的解析器来完成。

4)利用bwt算法的转换步骤将清理后的代码片段转换为lc序列(本步骤为bwt算法的基础步骤,通过实现bwt算法来进行)。我们将lc序列视为代码数据库的第四部分-lc序列。

5)为了在推荐过程中更方便地使用这些信息,我们在它们之间进行索引并

为每种方法设置唯一的id。

在推荐阶段,输入包含用户当前的编程上下文和收集的代码数据库。输出是具有n个排名代码片段的列表。我们将代码推荐过程分为两个过程:搜索和重新排序。

在推荐阶段的搜索过程中,主要包括:

1)对于新的推荐请求,我们首先获取当前代码上下文,此处的代码上下文分为两个部分:当前正在编辑的方法的信息(当前方法信息)和当前光标位置前后的若干行代码(当前代码信息)。当前方法信息包括当前正在编辑的方法的结构信息和声明的变量类型,其提取方法和数据处理阶段提取这两种信息的方法和步骤一致。当前代码信息的长度可根据需要进行调整,默认设置为10行(光标位置之前5行,光标位置之后5行)。并将其按照数据处理阶段的方法将其转换为lc序列。

2)通过计算代码数据库中代码片段和当前代码上下文的bwt相似度和变量类型相似度从代码片段库中获取包含n个与当前代码上下文相似度最高的代码片段,作为候选集。

在重新排序阶段,主要包括:

1)根据候选集中代码片段与当前代码上下文的bwt相似性,变量相似性和结构相似性对候选代码片段进行重新排序。

2)最后,我们向用户呈现重新排序的列表,用户可以查看推荐代码片段的全部信息,并通过复制粘贴轻松使用它们并进行修改。

本发明最为核心的部分为如何计算两个代码片段之间的相似度,本发明选择使用改进后的bwt算法来进行两个代码片段之间的相似度计算。burrowswheeler变换(bwt)由burrowswheeler提出,它可以将原始文本转换为类似的文本,并连续或相邻地转换相同的字符位置。它可用于压缩数据和查找子序列,后者广泛用于比较符号序列之间的相似性,如核苷酸碱基。由于它能够轻松快速地再现原始序列,因此可以快速执行子序列搜索,并且不会增加存储空间的优异特性。我们选择它作为指令序列匹配的核心算法。为了使得bwt算法满足代码推荐中的要求,我们做了在其基础之上进行了一些改进。

首先,我们提出了一种局部代码语句相似性度量算法来计算两个代码语句的相似度。本发明中说的代码语句指的是代码片段中的一行代码,每行代码均已分号结束,所以可以通过分号从代码片段中切割代码语句。如果两个代码语句的相似度大于或等于预设阈值,我们认为这两个代码语句是相似的。在计算两个代码语句的相似度时,我们将代码语句中的括号,分号,逗号,数字,替换为空格字符,之后根据空格字符对代码语句进行切割,将其转换为一组词牌的集合。此过程可以形式化为:codeline={token1,token2,token3,...,tokenn}。然后,对于每个词牌,我们预先进行自然语言预处理,例如:分词,删除停止词和词干抽取。到目前为止,我们已经将计算两行代码相似度的问题转化为计算两个纯文本相似度的问题。我们采用经典的文本检索算法bm25来计算两个代码语句的相似度,并进行了一些修改以适应当前的应用场景。我们将原始bm25公式中的idf算法改为权重算法,因为我们更为重视代码语句间的词牌的重合度,而不关注如何去除那些词牌中的高频词。同时,因为代码语句总是很短并且同一词牌在一个代码语句中出现不止一次的情况是很常见的,因此我们使用了idf算法的原始形式。公式如下所示:

其中,linesimilarity(cli,clj)表示代码语句cli和clj之间的相似度;cli和clj是分别命名为i和j的两个代码语句;qtn是第n的词牌在cli中出现的次数;tn是tokenn出现在clj中的次数;ql是cli的长度;dl是clj的长度;avgdl是数据库中代码语句的平均长度;n为cli中词牌的总数量;b,k1,k2是调整因子。根据经验,设置b=0.75,k1=1.2,k2=1.2。

其次,为了应对当前用户的实际代码与代码数据库中的代码之间的差距,本文在匹配过程中增加了滑动窗口匹配,使得该方法可以在代码数据库中找到更多类似的代码片段。滑动窗口匹配意味着我们不只是将种子序列的当前元素(即)与频率序列的当前元素匹配(bwt算法是序列匹配算法,其作用是匹配两个序列,即判断序列a是否为序列b的子序列,在算法中,习惯性称序列a为种子序列,将序列b称为频率序列,即种子序列是之前所说的由当前代码上下文生成的lc序列,频率序列是代码数据库中存储的由代码片段生成的lc序列)。如果当前元素不被视为匹配,我们可以尝试将种子序列的当前元素附近的元素与频率序列的当前元素附近的元素进行匹配。如图2所示,当我们尝试将种子序列中的183与频率序列匹配时,我们发现它不匹配(183!=182)。在这种情况下,滑动窗口匹配将尝试将183与180和19匹配,这是根据bwt在频率序列中当前元素的下一个和最后一个元素。这意味着两个元素在频率序列的原始序列中接近182,如果它得到匹配,那么我们也将其视为匹配,更重要的是,如果匹配元素是频率序列的下一个元素bwt。算法的指针将在开始下一个步骤之前指向下一个元素。如果没有,我们将尝试将182与180和19匹配,这是种子序列中当前元素的下一个和最后一个元素,如果它得到匹配,那么我们将其视为匹配,并且与之前的情况相同,如果匹配元素是种子序列的下一个元素,下一个要匹配的元素是下一步的下一个元素,在图中,它应该是90。此外,窗口的大小可以根据用户需求或用户对建议的敏感度进行调整,此设置增加了方法的灵活性。在此基础之上,我们通过以下公式来进代码数据库中代码片段和当前代码上下文的计算:

其中,bwtsimilarity(csn,csm)表示两个代码片段csn和csm之间的bwt相似度;csn和csm是分别命名为n和m的两个代码片段;length(seedsequence)是种子序列的长度;linesimilarityi是指代码段csn和csm第i行的相似度;n1为代码段csn中的代码语句数量。

此外,因为我们从代码片段中抽取了所有变量声明,以便处理数据处理阶段中两个代码片段之间的编程风格差距。但是,是否使用相似类型的变量也是衡量两个代码片段是否相似的重要依据。通常,如果两个代码片段实现相同的功能,理论上它们应该声明并使用相似类型的变量。特别是,当实现读取文本文件内容的功能时,无论代码的具体逻辑如何以及如何执行读取操作,开发人员总是倾向于使用特定类型的变量,例如“file”,“fileinputstream”。和“string”来实现操作。同时,开发人员可以在仅输入一些变量声明后触发推荐。为了推荐的准确性和适用性,在计算两个代码段的相似性时,我们还计算了代码数据库中代码片段和当前代码上下文的变量类型相似度。计算变量类型相似度时,我们考虑两个代码片段之间使用的类型的一致程度。与jaccard相似性的基本思想。计算方法如下式所示:

其中,variabletypesimilarity(csn,csm)表示两个代码片段csn和csm之间的变量类型相似度;csn和csm是分别命名为n和m的两个代码片段;variabletypen和variabletypem分别表示csn和csm中变量类型的集合。

最终,我们提出两个代码片段之间相似度的计算方法:

codesimilarity(csn,csm)

=α1*bwtsimilarity(csn,csm)+α2

*variabletypesimilarity(csn,csm)

其中,codesimilarity(csn,csm)表示两个代码片段csn和csm之间的变量类型相似度;csn和csm是分别命名为n和m的两个代码片段;bwtsimilarity(csn,csm)和variabletypesimilarity(csn,csm)为之前步骤中计算所得的两个代码片段之间的bwt相似度和变量类型相似度;α1,α2为权重因子,根据经验,设置α1=0.7,α2=0.3。

在重新排序阶段,核心是计算排序分数。在实际应用中,用户总是希望与当前上下文更相关的结果在结果列表中具有更高的排序,即用户只需要浏览最少的结果以找到所需的代码片段。所以我们需要结合bwt。用户上下文和返回的代码片段之间的相似性和结构相似性,以重新排列返回的结果。两个代码片段的结构相似性定义为4个部分:1)方法名称;2)参数列表;3)返回值;4)变量名称。对于单个标记的文本信息,如“方法名称”和“返回值”,我们采用字符相似度来计算标记之间的文本相似度,简单地说,找到两个标记之间的lcs(最长字符子序列)和计算lcs长度与词牌长度的比率。我们将该比率作为两个词牌的相似度。设置重合(即jacard算法)用于计算集合形式中的代码信息的相似性,例如“参数列表”和“变量名称”,对于集合中的标记,我们也使用最长的字符子序列来计算相似度,当两个词牌的相似度超过0.9时,我们认为这两个词牌是相同的。我们通过以下公式来计算两个代码片段之间的结构相似性:

其中,ss(csn,csm)表示两个代码片段csn和csm之间的结构相似度;csn和csm是分别命名为n和m的两个代码片段;lcs()为最长子序列算法,jacard()表示jacard相似度算法;分别表示代码片段csn和csm的方法名;分别表示代码片段csn和csm的返回值;分别表示代码片段csn和csm的参数集合;分别表示代码片段csn和csm的变量名集合。β1,β2,β3,β4为权重因子,根据经验设置β1=0.3,β2=0.2,β3=0.2,β4=0.3。

最终,本发明通过下式来计算排序分数:

rankscore(csn,csm)=α3*codesimilarity(csn,csm)+α4*ss(csn,csm)

其中,rankscore(csn,csm)表示两个代码片段csn和csm之间的排序分数;csn和csm是分别命名为n和m的两个代码片段;codesimilarity(csn,csm)和ss(csn,csm)为之前步骤中计算所得的两个代码片段之间的代码相似度和结构相似度;α3,α4为权重因子,根据经验,设置α3=0.8,α4=0.2。

并将所有结果按照排序分数从高到低进行排列,最终反馈给用户。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1