免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: abcfy2
打印 上一主题 下一主题

请教python分析groovy代码文件的写法 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2013-05-24 22:45 |只看该作者
本帖最后由 GhostFromHeaven 于 2013-05-24 22:46 编辑

回复 9# abcfy2

switch不同case里的save不会被重复计数,但会把switch各分支中最多的save数加到函数里面。

打印格式为:文件名:行号:内容

可以处理多个文件。
  1. #-*- coding:utf-8 -*-
  2. import os
  3. import re
  4. import string

  5. pattern_func_def = re.compile('''(?<!\S)def\s+.*?\s+\{\s*''')
  6. pattern_save = re.compile('''\.save\s*\(.*?\)''')

  7. pattern_switch = re.compile('''(?<!\S)switch\s*\(.*?\)\s*{''')
  8. pattern_case = re.compile('''(?<!\S)(case\s+\S+)|(default)\s*:''')
  9. pattern_break = re.compile('''(?<!\S)break(?!\S)''')

  10. pattern_left_brace = re.compile('''.*?\{.*?''')
  11. pattern_right_brace = re.compile('''.*?\}.*?''')

  12. class GroovyParser(object):
  13.     def __init__(self):
  14.         self.current_file_name = ""
  15.         self.current_file_handler = None
  16.         self.current_line = ""
  17.         self.current_line_index = 0
  18.         
  19.     def _get_line(self):
  20.         for self.current_line in open(self.current_file_name, "r"):
  21.             self.current_line_index += 1
  22.             self.current_line = self.current_line.strip('\n')
  23.             yield "%s" % self.current_line
  24.    
  25.     def print_line(self):
  26.         print "%10s:%04d:%s" % (os.path.basename(self.current_file_name),
  27.                                 self.current_line_index,
  28.                                 self.current_line)
  29.    
  30.     # 处理{}
  31.     def _handle_brace(self, line):
  32.         # 假设每行最多一个{
  33.         _brace_count = 0
  34.         if pattern_left_brace.search(line):
  35.             _brace_count -= 1

  36.         # 假设每行最多一个}
  37.         if pattern_right_brace.search(line):
  38.             _brace_count += 1
  39.         return _brace_count
  40.    
  41.     # 处理xx.save(yy)
  42.     def _handle_save(self, line, save_count):
  43.         _save_count_in_1_function = save_count
  44.         # 假设每行最多一个.save()
  45.         if pattern_save.search(line):
  46.             _save_count_in_1_function += 1
  47.             # 如果有多个save,则打印出来
  48.             if _save_count_in_1_function > 1:
  49.                 self.print_line()
  50.             return 1
  51.         return 0
  52.         
  53.     def parse_func_def(self):
  54.         _brace_count = -1
  55.         _save_count_in_1_function = 0
  56.         for line in self.line_reader:
  57.             #line = self.get_line()
  58.             if not line:
  59.                 break

  60.             # function
  61.             if pattern_func_def.search(line):
  62.                 self.parse_func_def()
  63.             
  64.             # switch
  65.             if pattern_switch.search(line):
  66.                _save_count_in_1_function = self.parse_switch_def(_save_count_in_1_function)
  67.             
  68.             # {}
  69.             _brace_count += self._handle_brace(line)
  70.             
  71.             # xx.save(yy)
  72.             _save_count_in_1_function += self._handle_save(line, _save_count_in_1_function)
  73.             
  74.             # 函数定义结束
  75.             if _brace_count == 0:
  76.                 return

  77.     def parse_switch_def(self, save_count):
  78.         _brace_count = -1
  79.         _save_count_in_1_function = save_count
  80.         _max_save_count = save_count
  81.         _all_save_count = save_count
  82.         for line in self.line_reader:
  83.             if not line:
  84.                 break
  85.             # switch
  86.             if pattern_switch.search(line):
  87.                 _all_save_count = self.parse_switch_def(_save_count_in_1_function)
  88.             
  89.             if pattern_case.search(line):
  90.                 _get_brace_count, _all_save_count = self.parse_case_def(_save_count_in_1_function)
  91.                 _brace_count += _get_brace_count
  92.             
  93.             if _max_save_count < _all_save_count:
  94.                _max_save_count = _all_save_count
  95.             
  96.             # {}
  97.             _brace_count += self._handle_brace(line)
  98.             
  99.             # xx.save(yy)
  100.             #_save_count_in_1_function += self._handle_save(line, _save_count_in_1_function)
  101.             # 定义结束
  102.             if _brace_count == 0:
  103.                 break
  104.         return _max_save_count
  105.    
  106.     def parse_case_def(self, save_count):
  107.         _brace_count = 0
  108.         _save_count_in_1_function = save_count
  109.         for line in self.line_reader:
  110.             if not line:
  111.                 break
  112.             
  113.             # xx.save(yy)
  114.             _save_count_in_1_function += self._handle_save(line, _save_count_in_1_function)
  115.             
  116.             # break
  117.             if pattern_break.search(line):
  118.                 break

  119.             # {}
  120.             _brace_count = self._handle_brace(line)
  121.             if _brace_count == -1:
  122.                 break
  123.         return (_brace_count, _save_count_in_1_function)

  124.     def parse(self, file_list):
  125.         for self.current_file_name in file_list:
  126.             self.line_reader = self._get_line()
  127.             self.current_line_index = 0
  128.             for line in self.line_reader:
  129.                 if not line:
  130.                     break
  131.                 if pattern_func_def.search(line):
  132.                     self.parse_func_def()
  133.         
  134. if __name__ == "__main__":
  135.     file_list = [r'C:\Users\fgl\Desktop\test\to_parse_2.groovy']#, 'to_parse_1.groovy']
  136.     gp = GroovyParser()
  137.     gp.parse(file_list)

  138.         
  139.         
复制代码
to_parse_2.zip (534 Bytes, 下载次数: 1)
   

论坛徽章:
0
12 [报告]
发表于 2013-05-25 17:56 |只看该作者
本帖最后由 abcfy2 于 2013-05-25 17:57 编辑

回复 11# GhostFromHeaven


    需求是BOSS口头提出来的,并未形成统一的文档,所以暂时没有需求文档。
我将这个脚本整合到了系统的定时计划中,每天定时扫描所有的代码库,然后将结果以邮件的形式发送,发现哪里 有问题就改哪里。

上次我将你这个脚本改了一下,大致的邮件格式是这样的:

*Controller.groovy同时保存多domain class扫描结果:
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:58:                                result=systemCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:62:                                result=systemCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:67:                                result=systemCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:71:                                result=systemCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/AlarmCodeController.groovy:63:                                result=alarmCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/support/AlarmCodeController.groovy:70:                                result=alarmCodeInstance.save(flush: true)
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/knowledge/RuleController.groovy:112:                if (ruleInstance.save(flush: true)) {
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/knowledge/RuleController.groovy:189:                        if(ruleInstance .validate() && ruleInstance .save()) {
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/service/ServicePlanController.groovy:295:                if (!serviceRequest.save(flush: true)) {
CISJOB/workspace/cis/grails-app/controllers/com/si/ciots/crm/ContractCompressorController.groovy:189:        if(contractCompressor.save()){
CISJOB/workspace/cis/grails-app/controllers/com/si/c2/business/DeliveryAddressController.groovy:44:                if (deliveryAddressInstance.save(flush: true)){
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/compressor/CompressorController.groovy:1474:            if(compressor .validate() && compressor .save()) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/compressor/CompressorController.groovy:1485:            if(compressor .validate() && compressor .save()) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/compressor/SamplerController.groovy:131:            if(sampler.validate() && sampler.save()) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:57:                                result=systemCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:61:                                result=systemCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:66:                                result=systemCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/SystemCodeController.groovy:70:                                result=systemCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/AlarmCodeController.groovy:63:                                result=alarmCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/support/AlarmCodeController.groovy:70:                                result=alarmCodeInstance.save(flush: true)
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/knowledge/RuleController.groovy:112:                if (ruleInstance.save(flush: true)) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/knowledge/RuleController.groovy:189:                        if(ruleInstance .validate() && ruleInstance .save()) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/service/ServicePlanController.groovy:292:                if (!serviceRequest.save(flush: true)) {
KaishanCis/workspace/lgcis/grails-app/controllers/com/si/ciots/crm/ContractCompressorController.groovy:190:        if(contractCompressor.save()){
c2/workspace/grails-app/controllers/com/si/c2/business/PayRecordController.groovy:50:                    if(payRecordInstance.save()){


目前发现的问题是这样,那几个result实际上是switch-case语句中的,不应该被筛选出来,还有就是if中的save()方法如果是空参也不筛选出来。

论坛徽章:
0
13 [报告]
发表于 2013-05-25 23:36 |只看该作者
回复 12# abcfy2
1、switch的问题已经解决了,昨天就猜到if应该也要处理。你可以用最新的脚本试试。

2、你的意思是如果是if(xx.save && yy.save())这样的save都不算进去吗?

3、if (xx) {
          xx.save(yyy)
   } else {
         zzz.save(aaa)
   }

这样的怎么计算?
   

论坛徽章:
0
14 [报告]
发表于 2013-05-26 09:44 |只看该作者
回复 13# GhostFromHeaven


    所以程序还需要慢慢修,因为groovy代码我懂的也不是很多,可以说几乎不懂。
BOSS是为了要代码可读性更高,提出来的一类需求,然后用脚本去扫描代码,所以不一定要尽善尽美,反正扫描出来还是需要人为去修改的。
BOSS的意思也就是说先扫描,然后让程序猿们去改,发现扫描结果不对再反馈。至于第二种if情况暂不考虑,先把比较明显的扫描问题先解决了就行了。
比如switch-case语句和if(xxxx.save())语句。至于if-else语句,暂时不清楚BOSS怎么算的,这个等我跟BOSS沟通一下吧。

论坛徽章:
0
15 [报告]
发表于 2013-05-26 17:29 |只看该作者
本帖最后由 GhostFromHeaven 于 2013-05-26 17:34 编辑

回复 14# abcfy2
1、已经可以判断一行有多个save,多个{}

2、if的问题的解决了。
    思路是如果找到save(m个)就判断是否是if语句,如果是if语句就搜索.save()(n个),如果m>n就找到新的需要计数的save,否则不算。
  1. def fuction4 = {
  2.     dosomething
  3.     something.save(abc1).save(dxy)
  4.     something.save(def2)
  5.     if (xx.save() && yy.save())
  6.     {
  7.         xxa.save()
  8.     }
  9.    
  10.     if(xx.save() && yy.save())
  11.     {
  12.         xxa.save()
  13.     }
  14.    
  15.     if(xx.save(xx) && yy.save())
  16.     {
  17.         xxa.save()
  18.     }
  19.    
  20.     if(xx.save(xx) && yy.save(yy))
  21.     {
  22.         xxa.save()
  23.     }
  24. }
复制代码


parse_groovy.zip (22.12 KB, 下载次数: 4)
   

论坛徽章:
0
16 [报告]
发表于 2013-05-27 13:17 |只看该作者
回复 15# GhostFromHeaven


    多谢给出参考。这个脚本是在linux服务器运行的,你这个是在windows下写的,换行符不一样,一开始执行不了,我已经用dos2unix转换换行符了,执行没有问题,稍微修改了一下,如下。
开头加上了命令解释器
#!/usr/bin/python

最后改成了

def help():
    print """用法:
    sys.argv[0] dir1 [dir2] [dir3] ..."""

if __name__ == "__main__":
    if len(sys.argv) <= 1:
        help()
        exit(1)
    else:
        for dir in sys.argv[1:]:
            filelist = os.popen('find '+ dir + ' -type f -name *Controller.groovy').read().rstrip('\n').split('\n')
        if filelist != ['']:
            gp = GroovyParser()
            gp.parse(filelist)
调用系统中的find命令查找这一类文件,find将查找到的结果以\n为分隔符换行显示在终端上,转换为列表递给程序,执行起来基本没什么问题,感谢辛苦了

论坛徽章:
0
17 [报告]
发表于 2013-05-27 14:49 |只看该作者
本帖最后由 abcfy2 于 2013-05-27 14:49 编辑

回复 11# GhostFromHeaven


    结果还是有点问题啊,原本筛选出那么多,这次一个都筛选不出来了。
我在你那个测试样例加了下面一段:
  1.   def handlePayFinish(String tradeNo, String orderNo, double totalFee, String alipayAccount){
  2.         log.debug("handlerAlipayReturn: tradeNo= ${tradeNo}, orderNo= ${orderNo}, totalFee= ${totalFee}, alipayAccount= ${alipayAccount}")
  3.         if(!PayRecord.countByAlipayTradeNo(tradeNo)){
  4.         log.info("handlerAlipayReturn: begin add PayRecord")
  5.                def goodsOrder = GoodsOrder.findByOrderNo(orderNo)
  6.                      def payRecord = new PayRecord(alipayAccount:alipayAccount
  7.                                                     ,  goodsOrder:goodsOrder
  8.                                                     ,  alipayTradeNo:tradeNo
  9.                                                     ,  amount:totalFee
  10.                                                     ,  payDate:new Date()
  11.                                                     ,  type:PayType.findByCodeNum('JSDZ'))
  12.                    payRecord.save(flush:true)
  13.                    goodsOrder.orderStatus = OrderStatus.findByCodeNum("YFK")
  14.                    goodsOrder.payDate = payRecord.payDate
  15.                    goodsOrder.save(flush: true)
  16.                    log.info("handlerAlipayReturn: finish add PayRecord")
  17.          }else{
  18.       log.debug("the payRecord which tradeNo is ${tradeNo} already exists !")
  19.       }   
复制代码
明显在def payRecord = 这段中有两个save方法 payRecord.save(flush:true)和goodsOrder.save(flush: true),但是没有被筛选出来。

论坛徽章:
0
18 [报告]
发表于 2013-05-27 16:10 |只看该作者
本帖最后由 GhostFromHeaven 于 2013-05-27 16:18 编辑

回复 17# abcfy2

1、函数定义的模式匹配要修改一下,\s+要求函数名和{直接必须有空白字符,改成:
pattern_func_def = re.compile('''(?<!\S)def\s+.*?\s*\{\s*''')

pattern_func_def = re.compile('''(?<!\S)def\s+.*?\{\s*''')


2、还有下面这样的语句都删掉:

                if not line:
                    break

论坛徽章:
0
19 [报告]
发表于 2013-05-27 16:52 |只看该作者
回复 18# GhostFromHeaven


    还是有一些问题
发现扫出来的结果中有vulcan/javadoc/vulcan/grails-app/controllers/com/si/vulcan/ProjectController.groovy:1355:                !projectInstance.save(flush: true)?renderMsg('放弃连杆校验,请联系管理员!'):renderSuccess()
打开了一下代码文件,这段代码块是这样的,只有一个save()方法,为什么会被扫出来?
  1.    def giveUpConnectingRod(){
  2.         withPersonalProject{projectInstance->
  3.             try {
  4.                 ConnectingRod rod=projectInstance.connectingRod
  5.                 if (rod) {
  6.                     projectInstance.connectingRod=null
  7.                     rod.delete()
  8.                 }   
  9.                 projectInstance.rodStep=0
  10.                 !projectInstance.save(flush: true)?renderMsg('放弃连杆校验,请联系管理员!'):renderSuccess()
  11.             }catch (VulcanCustomeException e) {
  12.                 renderMsg('放弃连杆失败,请联系管理员!')
  13.             }   
  14.         }   
  15.     }   
复制代码

论坛徽章:
0
20 [报告]
发表于 2013-05-27 17:00 |只看该作者
回复 19# abcfy2

我试了下,没有扫出来。你再确认下。
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP