掌桥专利:专业的专利平台
掌桥专利
首页

一种源代码的冗余导入类清理方法及装置

文献发布时间:2023-06-19 11:19:16


一种源代码的冗余导入类清理方法及装置

技术领域

本申请涉及计算机技术领域,具体涉及源代码的冗余导入类清理方法及装置。

背景技术

随着互联网技术和金融科技的发展,项目迭代速度越来越快,但由于开发人员水平层次不齐、历史遗留等问题导致的开发过程中引入了实际不需要使用的类,进而导致了大量的开源jar包依赖,项目工程臃肿等问题,在应用上云等应用场景下,应用体量显得尤其笨重。从单个类来讲,人工通过开发工具参与识别单个类是否存在导入的情况,需要识别出当前类中存在多少类是多余导入的,需要人工甄别,删除和修改后才能清理非必要的代码,人工遍历整个项目和多个项目,实现存量代码的重构。一旦存在规模上百万行的存量项目或出现多个子项目都需要做重构的情况下,对于开发人员无异是一种巨大的技术债务,亟待一种能够自动清理代码导入类的自动化方法。

发明内容

针对现有技术中的问题,本申请提供一种源代码的冗余导入类清理方法及装置,方法包括:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

本发明的一方面,提供一种源代码的冗余导入类清理方法,包括:

根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

根据所述更新的抽象语法树,对应生成清理后的源代码。

在优选的实施例中,还包括:生成所述抽象语法树。

在优选的实施例中,根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点,包括:

遍历所述抽象语法树,将该抽象语法树上的每个节点各自标记为导入类节点和非导入类节点中的一个。

在优选的实施例中,还包括:

将所有导入类节点归入导入类集合,将所有非导入类节点归入非导入集合;

剔除所述导入类集合中冗余的导入类节点;

所述将所有非冗余的导入类节点置于所述非导入类节点之前,包括:

将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部。

在优选的实施例中,所述根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点,包括:

若一个导入类节点未被所述非导入类节点引用,则将该导入类节点确定为冗余的导入类节点。

在优选的实施例中,所述根据所述更新的抽象语法树,生成清理后的源代码,包括:

遍历更新的所述抽象语法树,得到所有节点;

根据所有节点生成源代码。

在优选的实施例中,所述抽象语法树包括类根节点、包名节点、外部类类节点以及类主体节点;所述根据所有节点生成源代码,包括:按照类别将类根节点、包名节点、外部类类节点以及类主体节点输出至字符流,生成所述源代码。

在优选的实施例中,还包括:将清理后的源代码覆盖至指定目录下。

本发明的又一方面,提供一种源代码的冗余导入类清理装置,包括:

节点划分模块,根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

冗余节点确定模块,根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

抽象语法树更新模块,在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

源代码更新模块,根据所述更新的抽象语法树,对应生成清理后的源代码。

在优选的实施例中,还包括:抽象语法树生成模块,生成所述抽象语法树。

在优选的实施例中,根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点,包括:

遍历所述抽象语法树,将该抽象语法树上的每个节点各自标记为导入类节点和非导入类节点中的一个。

在优选的实施例中,还包括:

集合生成模块,将所有导入类节点归入导入类集合,将所有非导入类节点归入非导入集合;

冗余类剔除模块,剔除所述导入类集合中冗余的导入类节点;

抽象语法树重构模块,所述将所有非冗余的导入类节点置于所述非导入类节点之前,包括:

将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部。

在优选的实施例中,所述根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点,包括:

若一个导入类节点未被所述非导入类节点引用,则将该导入类节点确定为冗余的导入类节点。

在优选的实施例中,所述根据所述更新的抽象语法树,生成清理后的源代码,包括:

节点获取单元,遍历更新的所述抽象语法树,得到所有节点;

源代码生成单元,根据所有节点生成源代码。

在优选的实施例中,所述抽象语法树包括类根节点、包名节点、外部类类节点以及类主体节点;所述根据所有节点生成源代码,包括:按照类别将类根节点、包名节点、外部类类节点以及类主体节点输出至字符流,生成所述源代码。

在优选的实施例中,还包括:将清理后的源代码覆盖至指定目录下。

本发明的又一方面,本申请提供一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述程序时实现所述的源代码的冗余导入类清理方法。

本发明的又一方面,本申请提供一种计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现所述的源代码的冗余导入类清理方法。

由上述技术方案可知,本申请提供的一种源代码的冗余导入类清理方法,方法包括:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

附图说明

为了更清楚地说明本申请实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图是本申请的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。

图1是源代码的冗余导入类清理方法流程示意图。

图2是使用节点集合重构抽象语法树流程示意图。

图3是由抽象语法树重构源代码流程示意图。

图4是源代码的冗余导入类清理装置结构示意图。

图5是本申请实施例中的电子设备的结构示意图。

具体实施方式

为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整的描述,显然,所描述的实施例是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。

需要说明的是,本申请公开的源代码的冗余导入类清理方法及装置可用于信息安全技术领域,也可用于除信息安全技术领域之外的任意领域,本申请公开的源代码的冗余导入类清理方法及装置的应用领域不做限定。

随着互联网技术和金融科技的发展,项目迭代速度越来越快,但由于开发人员水平层次不齐、历史遗留等问题导致的开发过程中引入了实际不需要使用的类,进而导致了大量的开源jar包依赖,项目工程臃肿等问题,在应用上云等应用场景下,应用体量显得尤其笨重。

从单个类来讲,人工通过开发工具参与识别单个类是否存在导入的情况,需要识别出当前类中存在多少类是多余导入的,需要人工甄别,删除和修改后才能清理非必要的代码,人工遍历整个项目和多个项目,实现存量代码的重构。

一旦存在规模上百万行的存量项目或出现多个子项目都需要做重构的情况下,对于开发人员无异是一种巨大的技术债务,亟待一种能够自动清理代码导入类的自动化方法。

针对现有问题中的至少一个,本申请提供一种源代码的冗余导入类清理方法及装置,方法包括:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

下面结合附图对本发明提供的源代码的冗余导入类清理方法及装置进行详细说明。

本申请提供一种源代码的冗余导入类清理方法,如图1所示,包括:

S1:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

具体的,在计算机科学中,抽象语法树是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因些,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。可以理解,一个抽象语法树是通过分析一个软件项目的源代码而生成的。一般地,采用文件流的形式扫描源代码,将所有的源代码形成代码文件流,再将代码文件流读取为文本,以文件为基本编译单元进行词法解析。在具体的实施例过程,所述以文件为基本编译单元进行词法解析的步骤包括首先将计算机内存中代码文件以字符形式按行读取到基本编译单元对象中,然后截止读取文件最后一行,该文件源代码读取完毕,基本编译单元对象准备完成,通过对基本编译单元对象数据解析,基于编程语言语法规定,对基本编译单元中的符号、语法关键字完成规则校验。最终将基本编译单元数据解析成类根节点、包名节点、外部类类节点集合、类主体节点集合,至此词法分析结束。未完成规则校验的则标记为词法解析不成功。在完成词法解析后,筛选词法解析成功的文件流集合中的基本编译单元,输出并导入至一个空的语法树,从而生成源代码的抽象语法树。从抽象语法树的生成过程中,可以理解,抽象语法树按照源代码的结构包括了类根节点、包名节点、外部类类节点和类主体节点。

在具体的实施例中,遍历生成的抽象语法树中的所有节点,若节点对应的是一个导入外部预设类函数结构,则将该节点标记为导入类节点,若节点不是对应的一个导入类函数结构,则将该节点标记为非导入类节点。例如一个用于矩阵运算的预设类函数是预先定义好的,源代码中直接导入了该矩阵运算类,则导入该矩阵运算类的节点就是一个导入类节点;再例如一个求和函数,其没有外部预设类的导入,则将该求和函数对应的节点标记为非导入类节点。通过上述方法可以将抽象语法树中所有的节点划分为导入类节点和非导入类节点两大类。

S2:根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

具体的,本申请的目标是将代码中没有起到作用的冗余外部类清除,可以理解,若一个外部导入类被非导入类引用了,则其对于源代码而言就是有效的导入类,而如果一个导入类没有被所有的非导入类引用,说明它是一个冗余的外部导入类,可以将其删除,对源代码的逻辑没有影响,同时可以减少源代码的数据量。确定一个导入类节点是否为冗余节点的步骤包括:若一个导入类节点未被所述非导入类节点引用,则将该导入类节点确定为冗余的导入类节点。例如对于一个导入类节点a,通过遍历非导入类节点,查找该导入类节点a是否被引用,假设该导入类节点a被一个非导入类节点b引用了,则该导入类节点a为有效节点,需要被保留;如果通过遍历非导入类节点,发现该导入类节点未被非导入类节点中的任意一个引用,则说明该导入类节点a对于源代码的逻辑而言是冗余的,是一个冗余的导入类节点。

S3:在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

具体的,确定了冗余的导入类后,整个抽象语法树中的所有节点被标记为三类:冗余导入类节点,非冗余导入类节点和非导入类节点。遍历整个抽象语法树的所有节点,若节点为非冗余的导入类节点,则将其置于一集合的前部,若节点为非导入类,则将其置于该集合的后部,从而得到一个集合,该集合包括了抽象语法树中的所有非冗余的导入类节点和非导入类节点。可以理解,该集合就是抽象语法树中删除了冗余的导入类节点的结果。例如一个抽象语法树共包括10个节点{a.b,c,d,e,f,g,h,I,j}其中非导入类节点为a,c,d,h,j,非冗余的导入类为b,I,冗余的导入类节点为e,f,g。在该具体的实施例中,遍历抽象语法树的10个节点,从a节点开始遍历,由于a为非导入类节点,所以将其放在新建的空集合的尾部,得到{a}。遍历至b节点,由于b未非冗余的导入类节点,故将其放在集合头部,得到{b,a}。遍历至c节点,由于c为一个非导入类节点,故将其放在集合尾部,得到{b,a,c}。遍历至d节点,由于其是在个非导入类的节点,故将其放在集合尾部,得到{b,a,c,d}。遍历至e节点,由于其为一个冗余的导入类节点,所以跳过,遍历至f节点,以此类推。最终得到集合{I,b,a,c,d,h,j},即为去除了冗余的导入类节点的抽象语法树节点集合。从上述过程中可以发现,对抽象语法树的所有节点进行了两次遍历,为了减少遍历带来的循环消耗,在另一个具体的实施例中,在第一次遍历语法树,将抽象语法树的所有节点划分为导入类节点和非导入类节点之后,如图2,执行如下步骤:

S31:将所有导入类节点归入导入类集合,将所有非导入类节点归入非导入集合;

具体的,假设一个抽象语法树共有8个节点{a.b,c,d,e,f,g,h},通过第一次遍历,将所有的节点分为导入类节点a,c,d和非导入类节点b,e,f,g,h。将所有的导入类节点归入导入类集合得到{a,c,d},将所有的非导入类节点归入非导入类集合得到{b,e,f,g,h}。

S32:剔除所述导入类集合中冗余的导入类节点;

具体的,如上述具体的实施例,根据导入类与非导入类的引用关系,确定了导入类中冗余的导入类节点是d,则将d进行剔除,得到集合{a,c},即为剔除冗余之后的导入类集合。

S33:所述将所有非冗余的导入类节点置于所述非导入类节点之前,包括:

将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部。

具体的,如上述具体的实施例,将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部,即将{a,c}置于{b,e,f,g,h}的头部,得到{a,c,b,e,f,g,h},至此也得到了去除了冗余的导入类节点的抽象语法树节点集合。该具体的实施例中,对抽象语法树只进行了一次遍历,减少了消耗。

S4:根据所述更新的抽象语法树,对应生成清理后的源代码。

具体的,重构以后的抽象语法树需要对应生成清理了冗余导入类的源代码,如图3,根据抽象语法树生成清理后的源代码的步骤包括:

S41:遍历更新的所述抽象语法树,得到所有节点;

具体的,更新后的抽象语法树中的所有节点包括了类根节点、包名节点、外部类类节点以及类主体节点。

S42:根据所有节点生成源代码。

具体的,获取到更新后的抽象语法树的所有节点后,将所有的节点按照节点的类型输出至字符流中,使用源代码的相应编译器对输出的字符流按照单元进行编译,最终生成源代码文本。例如对于JavaScript的源代码可以使用bable这个库进行抽象语法树的节点字符流向JavaScript源代码的生成。

生成源代码文本后,读取代码导出配置规则配置指定目录,即选择是否覆盖、重新导出到新目录。通过读取生成的清理后源代码文本到文件流中并写到硬盘指定目录中。

结合一个具体的实施场景,对本申请做进一步说明。

现有一个JavaScript项目的源代码需要清理其中冗余的导入类。在JavaScript的语法解析领域,一个流行的开源项目是Esprima,利用这个工具来完成任务。此外,需要借助Node来构建能够在命令行运行的JS代码。首先创建项目的基本目录结构,以及初始化NPM。借助Esprima解析代码非常简单,只要使用一个方法即可:var ast=esprima.parse(code);esprima.parse()方法接收两种类型的参数:字符串或Node的Buffer对象,它也可以收附加的选项作为参数。解析后返回结果即为抽象语法树(AST),抽象语法树遵守Mozilla SpiderMonkey的解析器的API。通过观察生成的语法树可以发现每个节点都有一个type,根节点的type为Program。type也是所有节点都共有的,其他的属性依赖于节点的type。

得到代码的抽象语法树后,对得到的抽象语法树进行遍历,我们可以借助Estraverse进行节点的遍历,标记出导入类节点和非导入类节点。创建了两个l对象分别用来存放导入类节点和非导入类节点,其中存放导入类节点的对象名为Inversion,存放非导入类节点的对象为NoInversion。

将所有节点划分为导入类节点和非导入类节点后,遍历非导入类节点中type为声明类的节点,如果该节点涉及其他类的调用,则判断该调用的类是否存在于导入类节点对象集合中,若存在则将比导入类节点标记为有效节点,即在节点中添加一个属性值effect,其值为true是有效节点,其值为false是冗余节点。在完成非导入类节点的遍历后,新建一个对象InversionEffect用于存放导入类节点中属性值effect为true的所有节点。然后进行抽象语法树的重构,将对象InversionEffect与对象NoInversion进行合并,组成一个新的对象newAST,其中新的对象newAST中头部是对象InversionEffect的节点,尾部是对象NoInversion的节点。最后将对象newAST中所有的节点按照类型输出为字符流,利用babel中的transform方法,对字符流进行编译后,生成源代码文本。

将生成的清理后源代码覆盖至原源代码的目录中,使得项目可以重新运行。

由以上描述可知,本发明提供的一种源代码的冗余导入类清理方法,方法包括:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

从软件层面来说,本申请提供一种用于执行所述源代码的冗余导入类清理方法中全部或部分内容的源代码的冗余导入类清理装置的实施例,参见图4,所述源代码的冗余导入类清理装置具体包含有如下内容:

节点划分模块1,根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

冗余节点确定模块2,根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

抽象语法树更新模块3,在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

源代码更新模块4,根据所述更新的抽象语法树,对应生成清理后的源代码。

由以上描述可知,本发明提供的源代码的冗余导入类清理装置,本装置根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

在本发明的实施例中,提供一种源代码的冗余导入类清理装置,用于执行如下步骤包括:

S1:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

具体的,在计算机科学中,抽象语法树是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因些,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。可以理解,一个抽象语法树是通过分析一个软件项目的源代码而生成的。一般地,采用文件流的形式扫描源代码,将所有的源代码形成代码文件流,再将代码文件流读取为文本,以文件为基本编译单元进行词法解析。在具体的实施例过程,所述以文件为基本编译单元进行词法解析的步骤包括首先将计算机内存中代码文件以字符形式按行读取到基本编译单元对象中,然后截止读取文件最后一行,该文件源代码读取完毕,基本编译单元对象准备完成,通过对基本编译单元对象数据解析,基于编程语言语法规定,对基本编译单元中的符号、语法关键字完成规则校验。最终将基本编译单元数据解析成类根节点、包名节点、外部类类节点集合、类主体节点集合,至此词法分析结束。未完成规则校验的则标记为词法解析不成功。在完成词法解析后,筛选词法解析成功的文件流集合中的基本编译单元,输出并导入至一个空的语法树,从而生成源代码的抽象语法树。从抽象语法树的生成过程中,可以理解,抽象语法树按照源代码的结构包括了类根节点、包名节点、外部类类节点和类主体节点。

在具体的实施例中,遍历生成的抽象语法树中的所有节点,若节点对应的是一个导入外部预设类函数结构,则将该节点标记为导入类节点,若节点不是对应的一个导入类函数结构,则将该节点标记为非导入类节点。例如一个用于矩阵运算的预设类函数是预先定义好的,源代码中直接导入了该矩阵运算类,则导入该矩阵运算类的节点就是一个导入类节点;再例如一个求和函数,其没有外部预设类的导入,则将该求和函数对应的节点标记为非导入类节点。通过上述方法可以将抽象语法树中所有的节点划分为导入类节点和非导入类节点两大类。

S2:根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

具体的,本申请的目标是将代码中没有起到作用的冗余外部类清除,可以理解,若一个外部导入类被非导入类引用了,则其对于源代码而言就是有效的导入类,而如果一个导入类没有被所有的非导入类引用,说明它是一个冗余的外部导入类,可以将其删除,对源代码的逻辑没有影响,同时可以减少源代码的数据量。确定一个导入类节点是否为冗余节点的步骤包括:若一个导入类节点未被所述非导入类节点引用,则将该导入类节点确定为冗余的导入类节点。例如对于一个导入类节点a,通过遍历非导入类节点,查找该导入类节点a是否被引用,假设该导入类节点a被一个非导入类节点b引用了,则该导入类节点a为有效节点,需要被保留;如果通过遍历非导入类节点,发现该导入类节点未被非导入类节点中的任意一个引用,则说明该导入类节点a对于源代码的逻辑而言是冗余的,是一个冗余的导入类节点。

S3:在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

具体的,确定了冗余的导入类后,整个抽象语法树中的所有节点被标记为三类:冗余导入类节点,非冗余导入类节点和非导入类节点。遍历整个抽象语法树的所有节点,若节点为非冗余的导入类节点,则将其置于一集合的前部,若节点为非导入类,则将其置于该集合的后部,从而得到一个集合,该集合包括了抽象语法树中的所有非冗余的导入类节点和非导入类节点。可以理解,该集合就是抽象语法树中删除了冗余的导入类节点的结果。例如一个抽象语法树共包括10个节点{a.b,c,d,e,f,g,h,I,j}其中非导入类节点为a,c,d,h,j,非冗余的导入类为b,I,冗余的导入类节点为e,f,g。在该具体的实施例中,遍历抽象语法树的10个节点,从a节点开始遍历,由于a为非导入类节点,所以将其放在新建的空集合的尾部,得到{a}。遍历至b节点,由于b未非冗余的导入类节点,故将其放在集合头部,得到{b,a}。遍历至c节点,由于c为一个非导入类节点,故将其放在集合尾部,得到{b,a,c}。遍历至d节点,由于其是在个非导入类的节点,故将其放在集合尾部,得到{b,a,c,d}。遍历至e节点,由于其为一个冗余的导入类节点,所以跳过,遍历至f节点,以此类推。最终得到集合{I,b,a,c,d,h,j},即为去除了冗余的导入类节点的抽象语法树节点集合。从上述过程中可以发现,对抽象语法树的所有节点进行了两次遍历,为了减少遍历带来的循环消耗,在另一个具体的实施例中,在第一次遍历语法树,将抽象语法树的所有节点划分为导入类节点和非导入类节点之后,执行如下步骤:

S31:将所有导入类节点归入导入类集合,将所有非导入类节点归入非导入集合;

具体的,假设一个抽象语法树共有8个节点{a.b,c,d,e,f,g,h},通过第一次遍历,将所有的节点分为导入类节点a,c,d和非导入类节点b,e,f,g,h。将所有的导入类节点归入导入类集合得到{a,c,d},将所有的非导入类节点归入非导入类集合得到{b,e,f,g,h}。

S32:剔除所述导入类集合中冗余的导入类节点;

具体的,如上述具体的实施例,根据导入类与非导入类的引用关系,确定了导入类中冗余的导入类节点是d,则将d进行剔除,得到集合{a,c},即为剔除冗余之后的导入类集合。

S33:所述将所有非冗余的导入类节点置于所述非导入类节点之前,包括:

将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部。

具体的,如上述具体的实施例,将剔除冗余之后的所述导入类集合置于所述非导入类集合的头部,即将{a,c}置于{b,e,f,g,h}的头部,得到{a,c,b,e,f,g,h},至此也得到了去除了冗余的导入类节点的抽象语法树节点集合。该具体的实施例中,对抽象语法树只进行了一次遍历,减少了消耗。

S4:根据所述更新的抽象语法树,对应生成清理后的源代码。

具体的,重构以后的抽象语法树需要对应生成清理了冗余导入类的源代码,根据抽象语法树生成清理后的源代码,也就是源代码更新模块,用于执行如下步骤包括:

S41:遍历更新的所述抽象语法树,得到所有节点;

具体的,更新后的抽象语法树中的所有节点包括了类根节点、包名节点、外部类类节点以及类主体节点。

S42:根据所有节点生成源代码。

具体的,获取到更新后的抽象语法树的所有节点后,将所有的节点按照节点的类型输出至字符流中,使用源代码的相应编译器对输出的字符流按照单元进行编译,最终生成源代码文本。例如对于JavaScript的源代码可以使用bable这个库进行抽象语法树的节点字符流向JavaScript源代码的生成。

生成源代码文本后,读取代码导出配置规则配置指定目录,即选择是否覆盖、重新导出到新目录。通过读取生成的清理后源代码文本到文件流中并写到硬盘指定目录中。

结合一个具体的实施场景,对本申请做进一步说明。

现有一个JavaScript项目的源代码需要清理其中冗余的导入类。在JavaScript的语法解析领域,一个流行的开源项目是Esprima,利用这个工具来完成任务。此外,需要借助Node来构建能够在命令行运行的JS代码。首先创建项目的基本目录结构,以及初始化NPM。借助Esprima解析代码非常简单,只要使用一个方法即可:var ast=esprima.parse(code);esprima.parse()方法接收两种类型的参数:字符串或Node的Buffer对象,它也可以收附加的选项作为参数。解析后返回结果即为抽象语法树(AST),抽象语法树遵守Mozilla SpiderMonkey的解析器的API。通过观察生成的语法树可以发现每个节点都有一个type,根节点的type为Program。type也是所有节点都共有的,其他的属性依赖于节点的type。

得到代码的抽象语法树后,对得到的抽象语法树进行遍历,我们可以借助Estraverse进行节点的遍历,标记出导入类节点和非导入类节点。创建了两个l对象分别用来存放导入类节点和非导入类节点,其中存放导入类节点的对象名为Inversion,存放非导入类节点的对象为NoInversion。

将所有节点划分为导入类节点和非导入类节点后,遍历非导入类节点中type为声明类的节点,如果该节点涉及其他类的调用,则判断该调用的类是否存在于导入类节点对象集合中,若存在则将比导入类节点标记为有效节点,即在节点中添加一个属性值effect,其值为true是有效节点,其值为false是冗余节点。在完成非导入类节点的遍历后,新建一个对象InversionEffect用于存放导入类节点中属性值effect为true的所有节点。然后进行抽象语法树的重构,将对象InversionEffect与对象NoInversion进行合并,组成一个新的对象newAST,其中新的对象newAST中头部是对象InversionEffect的节点,尾部是对象NoInversion的节点。最后将对象newAST中所有的节点按照类型输出为字符流,利用babel中的transform方法,对字符流进行编译后,生成源代码文本。

将生成的清理后源代码覆盖至原源代码的目录中,使得项目可以重新运行。

由以上描述可知,本发明提供的一种源代码的冗余导入类清理装置,本装置根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;根据所述更新的抽象语法树,对应生成清理后的源代码。本申请明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

从硬件层面来说,本申请提供一种用于实现源代码的冗余导入类清理方法中的全部或部分内容的电子设备的实施例,所述电子设备具体包含有如下内容:

图5为本申请实施例的电子设备9600的系统构成的示意框图。如图5所示,该电子设备9600可以包括中央处理器9100和存储器9140;存储器9140耦合到中央处理器9100。值得注意的是,该图5是示例性的;还可以使用其他类型的结构,来补充或代替该结构,以实现电信功能或其他功能。

在一实施例中,源代码的冗余导入类清理功能可以被集成到中央处理器中。

其中,中央处理器可以被配置为进行如下控制:

S1:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

S2:根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

S3:在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

S4:根据所述更新的抽象语法树,对应生成清理后的源代码。

从上述描述可知,本申请实施例提供的电子设备,明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

在另一个实施方式中,源代码的冗余导入类清理装置可以与中央处理器9100分开配置,例如可以源代码的冗余导入类清理装置配置为与中央处理器9100连接的芯片,通过中央处理器的控制来实现源代码的冗余导入类清理功能。

如图5所示,该电子设备9600还可以包括:通信模块9110、输入单元9120、音频处理器9130、显示器9160、电源9170。值得注意的是,电子设备9600也并不是必须要包括图5中所示的所有部件;此外,电子设备9600还可以包括图5中没有示出的部件,可以参考现有技术。

如图5所示,中央处理器9100有时也称为控制器或操作控件,可以包括微处理器或其他处理器装置和/或逻辑装置,该中央处理器9100接收输入并控制电子设备9600的各个部件的操作。

其中,存储器9140,例如可以是缓存器、闪存、硬驱、可移动介质、易失性存储器、非易失性存储器或其它合适装置中的一种或更多种。可储存上述与失败有关的信息,此外还可存储执行有关信息的程序。并且中央处理器9100可执行该存储器9140存储的该程序,以实现信息存储或处理等。

输入单元9120向中央处理器9100提供输入。该输入单元9120例如为按键或触摸输入装置。电源9170用于向电子设备9600提供电力。显示器9160用于进行图像和文字等显示对象的显示。该显示器例如可为LCD显示器,但并不限于此。

该存储器9140可以是固态存储器,例如,只读存储器(ROM)、随机存取存储器(RAM)、SIM卡等。还可以是这样的存储器,其即使在断电时也保存信息,可被选择性地擦除且设有更多数据,该存储器的示例有时被称为EPROM等。存储器9140还可以是某种其它类型的装置。存储器9140包括缓冲存储器9141(有时被称为缓冲器)。存储器9140可以包括应用/功能存储部9142,该应用/功能存储部9142用于存储应用程序和功能程序或用于通过中央处理器9100执行电子设备9600的操作的流程。

存储器9140还可以包括数据存储部9143,该数据存储部9143用于存储数据,例如联系人、数字数据、图片、声音和/或任何其他由电子设备使用的数据。存储器9140的驱动程序存储部9144可以包括电子设备的用于通信功能和/或用于执行电子设备的其他功能(如消息传送应用、通讯录应用等)的各种驱动程序。

通信模块9110即为经由天线9111发送和接收信号的发送机/接收机9110。通信模块(发送机/接收机)9110耦合到中央处理器9100,以提供输入信号和接收输出信号,这可以和常规移动通信终端的情况相同。

基于不同的通信技术,在同一电子设备中,可以设置有多个通信模块9110,如蜂窝网络模块、蓝牙模块和/或无线局域网模块等。通信模块(发送机/接收机)9110还经由音频处理器9130耦合到扬声器9131和麦克风9132,以经由扬声器9131提供音频输出,并接收来自麦克风9132的音频输入,从而实现通常的电信功能。音频处理器9130可以包括任何合适的缓冲器、解码器、放大器等。另外,音频处理器9130还耦合到中央处理器9100,从而使得可以通过麦克风9132能够在本机上录音,且使得可以通过扬声器9131来播放本机上存储的声音。

本申请的实施例还提供能够实现上述实施例中的源代码的冗余导入类清理方法中全部步骤的一种计算机可读存储介质,所述计算机可读存储介质上存储有计算机程序,该计算机程序被处理器执行时实现上述实施例中的执行主体为服务器或客户端的源代码的冗余导入类清理方法的全部步骤,例如,所述处理器执行所述计算机程序时实现下述步骤:

S1:根据一预设的抽象语法树,将该抽象语法树上的所有节点划分为导入类节点和非导入类节点;

S2:根据非导入类节点与导入类节点的引用关系,确定冗余的导入类节点;

S3:在所述抽象语法树中,将所有非冗余的导入类节点置于所述非导入类节点之前,生成更新的抽象语法树;

S4:根据所述更新的抽象语法树,对应生成清理后的源代码。

从上述描述可知,本申请实施例提供的计算机可读存储介质,明显地提高了开发人员在重构存量代码工作效率,大幅度降低了开发人员的工作量,使得开发人员在重构存量代码时无需考虑删除多余代码导入删除逻辑和检验逻辑,为降低应用技术债务提供了技术支撑。

本领域内的技术人员应明白,本发明的实施例可提供为方法、装置、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。

本发明是参照根据本发明实施例的方法、设备(装置)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。

这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。

这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。

本发明中应用了具体实施例对本发明的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本发明的方法及其核心思想;同时,对于本领域的一般技术人员,依据本发明的思想,在具体实施方式及应用范围上均会有改变之处,综上所述,本说明书内容不应理解为对本发明的限制。

相关技术
  • 一种源代码的冗余导入类清理方法及装置
  • 基于FOG数据的源代码导入及解析的方法和装置
技术分类

06120112881106