在做一个项目时,需要分析git上代码有效提交行数,即:添加的行数 - 空行 - 注释行,网上未找到支持多种语言的分析代码,自己写了段代码分享出来。 该代码接收两个参数。filepath变更的文件名称, 文件的变化内容(可以通过git diff {commit_id} 查看)

该段代码特点: 1. 通过filepath的后缀,判断文件里包含的语言
2. 获取该次提交的代码,里面注释和空行的增加数和删除数
3. 支持文件类型,py,sh,java,rb,vue,html,js,xml,sql,css等 4. 如果需要支持更多的语言代码分析,在luanges里加入对应的key即可,single代表单行注释,multi代表多行注释。

def get_commit_diff_comment_rows(filepath,diff):
		endfix = filepath.split("/")[-1].split('.')[-1]
		diff_rows = diff.split("\n")
		if len(diff_rows) < 3:
				return {}
		luanges={
				'py':{
						'single':'#',
						'multi_start':["'''",'"""'],
						'multi_end':["'''",'"""']
				},
				'java':{
						'single':'//',
						'multi_start':["/*"],
						'multi_end':["*/"],        
				},
				'js':{
						'single':'//',
						'multi_start':["/*"],
						'multi_end':["*/"],        
				},        
				'vue':{
						'single':'//',
						'multi_start':["<!--",'/*'],
						'multi_end':["-->","*/"],        
				},        
				'html':{
						'single':'//',
						'multi_start':["<!--",'/*'],
						'multi_end':["-->","*/"],     
				},
				'jsx':{
						'multi_start':["/*","{/*"],
						'multi_end':["*/","*/}"],        
				},  
				'less':{
						'single':'//',
						'multi_start':["/*"],
						'multi_end':["*/"],        
				},  
				'rb':{
						'single':'#',
						'multi_start':["=begin"],
						'multi_end':["=end"],        
				},  
				'yml':{
						'single':'#',      
				},  

				'xml':{
						'multi_start':["<!--"],
						'multi_end':["-->"],      
				},  
				'sql':{
						'single':'--',
						'multi_start':["/*"],
						'multi_end':["*/"],                     
				},  
				'sh':{
						'single':'#',      
				}, 
				'css':{
						'multi_start':["/*"],
						'multi_end':["*/"],                     
				},  
		}
		luange = luanges.get(endfix)
		if not luange:
				return {}
		single_start = luange.get("single")
		multi_start = luange.get("multi_start")
		multi_end = luange.get("multi_end")    
		comment_add = 0 
		comment_del = 0 
		empty_add = 0 
		empty_del = 0 
		block_comment_flag=False  #块注释默认为空
		for row in diff_rows:
				if row.startswith("---") or row.startswith("+++") or row.startswith("@@"):
						continue
				if row.startswith("+"):
						node_type = '+'
				elif row.startswith("-"):
						node_type = '-'
				else:
						continue
				row = row[1:].strip()
				if row == '':
						if node_type == '+':
								empty_add += 1
						elif node_type == '-':
								empty_del += 1
				else:        
						add_number = 0 
						if single_start:    
								if row.startswith(single_start):
										add_number = 1 
						if multi_start:
								for i in multi_start:
										if row.startswith(i):
												add_number = 1 
												block_comment_flag=True
						if multi_end:
								for i in multi_end:
										if row.endswith(i):
												add_number = 1 
												block_comment_flag=False
						if block_comment_flag:
								add_number = 1 

						if node_type == '+':
								comment_add += add_number  
						elif node_type == '-':
								comment_del += add_number 

		return {"comment_add":comment_add, 
						"comment_del":comment_del,
						"empty_add":empty_add,
						"empty_del":empty_del
						}