def test_should_report_when_having_other_problem_and_continue(self, mock_stderr, mock_open): mock_open.side_effect = IOError("[Errno 2] No such file or directory") analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertIn("[Errno 2]", error_message) self.assertIn("*****@*****.**", error_message)
def test_should_report_when_having_other_problem_and_continue( self, mock_stderr, mock_open): mock_open.side_effect = IOError("[Errno 2] No such file or directory") analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertEqual("Error: Fail to read source file 'f1.c'\n", error_message)
def test_should_report_when_having_other_problem_and_continue( self, mock_stderr, mock_open): mock_open.side_effect = IOError("[Errno 2] No such file or directory") analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertIn("[Errno 2]", error_message) self.assertIn("*****@*****.**", error_message)
def get_file_data(name_list): file_data = [] for filename in name_list: file_data.append(lizard.analyze_file(filename)) return file_data
def lizard(self, file_names_commit, res_commit_api): """ :param file_name1: :param res_commit_api: :return: """ #print(file_names_commit) for file_data in res_commit_api['files']: if file_data['filename'] == file_names_commit: file_url = ((file_data['raw_url'])) filename, file_extension = os.path.splitext(file_url) # print(filename +' '+ file_extension) response = request.urlopen(file_url) html = response.read() html = html.decode() full_path = temp_dir_complexity + file_extension with open(full_path, 'w') as file_path: print(html, file=file_path) lizard_analyzer = lizard.analyze_file(full_path) try: commit.lizard_dict = lizard_analyzer.function_list[0].__dict__ os.remove(full_path) except: print('Code not generic so no complexity') pass
def analyseComplexity(self): ending = '' # sets an ending variable to differentate the source code files of Python and Java repos if self.repository.language == "Python": ending = '**/*.py' elif self.repository.language == "Java": ending = '**/*.java' else: print( "Error in analyse: language of repository matches neither Python nor Java" ) return directory_in_str = self.path + self.repository.name pathlist = Path(directory_in_str).glob(ending) sum = 0 function_count = 0 # loops through all folders in a repository to find all source code files and analyses their cyclomatic complexity for path in pathlist: # because path is object not string path_in_str = str(path) analysis = lizard.analyze_file(path_in_str) for element in analysis.function_list: sum += element.__dict__['cyclomatic_complexity'] function_count += 1 self.averageCC = sum / function_count print("Analysed Complexity of Repository: ", self.repository.name) return
def run_lizard(file_paths): """ This function runs the lizard tool (https://github.com/terryyin/lizard) on the given file paths. This tool can calculate number of lines of code, cyclomatic complexity, and a couple other metrics. It returns a dict like this: { 'my_filename': [FunctionInfo, ...] } """ function_infos = {} for file_path in file_paths: # Filter out anything lizard cant parse if not lizard_can_parse(file_path): # print('Lizard cant parse', file_path) continue lizard_analysis = lizard.analyze_file(file_path) function_infos[file_path] = lizard_analysis.function_list return function_infos
def calc_cyclo(config): result = {} # start = resource.getrusage(resource.RUSAGE_SELF) # resource metrics print("Got job {} Commit id {} ".format(config["fpath"], config["commitid"])) git_clone(config["repo_url"], config["repo_path"]) git_checkout(config["commitid"], config["repo_path"]) cyclomatic = lizard.analyze_file( config["fpath"]).average_cyclomatic_complexity result = { "fpath": config["fpath"], "result": cyclomatic, "commitid": config["commitid"] } # end = resource.getrusage(resource.RUSAGE_SELF) #resource metrics # diff_ucpu = end.ru_utime - start.ru_utime # print("time in user mode {}".format(diff_ucpu)) # print (resource.getrusage(resource.RUSAGE_THREAD).ru_maxrss / 1024, 'MB') # print (resource.getrusage(resource.RUSAGE_THREAD).ru_maxrss / 1024, 'MB') send_result(result) # return result
def search_after_method(elem_name): method_found = [] liz = lizard.analyze_file('after.java') for liz_elem in liz.function_list: if liz_elem.long_name == elem_name: method_found.append(liz_elem) break return method_found
def search_before_method(ref): method_found = [] liz = lizard.analyze_file('before.java') for liz_elem in liz.function_list: if (liz_elem.start_line <= ref[0]) and (liz_elem.end_line >= ref[1]): method_found.append(liz_elem) return method_found
def printMetrics(srcFiles, pathName): totSlocFolder = 0 numFiles = 0 newPath = convertPath(pathName) lizard.analyze_file.processors.insert(0, lizard.CPreExtension) # Insert file metrics as well as metrics for file's functions for currFile in srcFiles: totSloc = 0 totParams = 0 totTokens = 0 totComplexity = 0 fileMetrics = lizard.analyze_file(currFile) numFuncs = len(fileMetrics.function_list) fileName = getNewFileName(newPath, fileMetrics.filename) for func in fileMetrics.function_list: fields = [ func.name, func.length, func.nloc, fileName, "", func.cyclomatic_complexity, "", func.parameter_count, "", "", "", func.token_count, "", func.start_line, func.end_line ] scale.Write_Fields(map(lambda x: str(x), fields)) totSloc += func.nloc totParams += func.parameter_count totTokens += func.token_count totComplexity += func.cyclomatic_complexity if numFuncs != 0: avgSloc = round((float(totSloc) / numFuncs), 2) avgParams = round((float(totParams) / numFuncs), 2) avgTokens = round((float(totTokens) / numFuncs), 2) avgComplexity = round((float(totComplexity) / numFuncs), 2) fields = [ fileName, "", fileMetrics.nloc, "", numFuncs, "", avgComplexity, "", avgSloc, avgParams, "", "", avgTokens, "", "" ] else: fields = [ fileName, "", fileMetrics.nloc, "", 0, "", 0, "", 0, 0, "", "", 0, "", "" ] scale.Write_Fields(map(lambda x: str(x), fields)) totSlocFolder += fileMetrics.nloc numFiles += 1 if numFiles != 0: fields = [ newPath, "", totSlocFolder, "", "", "", "", "", "", "", "", float(totSlocFolder) / numFiles, "", "", "", "" ] scale.Write_Fields(map(lambda x: str(x), fields))
def complexity_analyzer_average(path): """function to get complexity and raw data analysis of the file/files mentioned in the path Args: path: path of the file/ files whose complexity is to be analyzed """ radon_complexity_value = lizard.analyze_file(path) return radon_complexity_value.average_cyclomatic_complexity
def test_should_report_when_having_problem_parsing_the_source(self, mock_GLOBAL, mock_stderr, mock_open): def fake_reader(token): if token == "exception": raise KeyError("") file_handle = mock_open.return_value.__enter__.return_value mock_GLOBAL.side_effect = fake_reader file_handle.read.return_value = '''line1 line2 exception lala line4''' analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertIn("f1.c", error_message) self.assertIn("3", error_message) self.assertIn("exception lala", error_message) self.assertIn("*****@*****.**", error_message) self.assertIn("https://github.com/terryyin/lizard", error_message)
def compute_complexity(file_dir, local_dir, repo_url, commit_hex, complexity): git_checkout(local_dir, commit_hex) complexity.put({ 'complexity': lizard.analyze_file(local_dir + file_dir).average_cyclomatic_complexity, 'file': file_dir, 'commit': commit_hex })
def main(ANALYZED_REPO, COMMIT_FILE_INFO_LOG): # Start of the main program flow repo = Repo(ANALYZED_REPO) assert not repo.bare all_commits = list(repo.iter_commits()) repo.git.checkout(all_commits[0]) with open(COMMIT_FILE_INFO_LOG,'r') as file_info: actual_commit = "" for line in file_info: commit_sha, status, old ,filepath = line.split("\n")[0].split(";") if commit_sha != actual_commit: actual_commit = commit_sha repo.git.checkout(actual_commit) i = lizard.analyze_file(ANALYZED_REPO+filepath) loc = i.__dict__['nloc'] cyc = 0 for f in i.function_list: #print(f.__dict__['cyclomatic_complexity']) cyc = cyc + f.__dict__['cyclomatic_complexity'] mod = repo.commit(actual_commit).stats.total['lines'] with open ("additional_info.log", "a") as f_i: print(line.split("\n")[0]+";"+str(loc)+";"+str(mod)+";"+str(cyc)) print(line.split("\n")[0]+";"+str(loc)+";"+str(mod)+";"+str(cyc), file=f_i) else: actual_commit = commit_sha #repo.git.checkout(actual_commit) i = lizard.analyze_file(ANALYZED_REPO+filepath) loc = i.__dict__['nloc'] cyc = 0 for f in i.function_list: #print(f.__dict__['cyclomatic_complexity']) cyc = cyc + f.__dict__['cyclomatic_complexity'] mod = repo.commit(actual_commit).stats.total['lines'] with open ("additional_info.log", "a") as f_i: print(line.split("\n")[0]+";"+str(loc)+";"+str(mod)+";"+str(cyc)) print(line.split("\n")[0]+";"+str(loc)+";"+str(mod)+";"+str(cyc), file=f_i) repo.git.checkout(all_commits[0])
def test_should_report_when_having_problem_parsing_the_source( self, mock_GLOBAL, mock_stderr, mock_open): def fake_reader(token): if token == "exception": raise KeyError("") file_handle = mock_open.return_value.__enter__.return_value mock_GLOBAL.side_effect = fake_reader file_handle.read.return_value = '''line1 line2 exception lala line4''' analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertIn("f1.c", error_message) self.assertIn("3", error_message) self.assertIn("exception lala", error_message) self.assertIn("*****@*****.**", error_message) self.assertIn("https://github.com/terryyin/lizard", error_message)
def _find_violated_function(file_, line): i = lizard.analyze_file(file_) violated_method = None for func in i.function_list: start_line = func.__dict__["start_line"] end_line = func.__dict__["end_line"] if line >= start_line and line <= end_line: violated_method = func break return violated_method
def main(): args = parsearg() file = args.f directory = args.d csv = args.csv extensions = args.l lfiles = [] # If neither are specified if file is None and directory is None: usageerror() return # If both are specified if file is not None and directory is not None: usageerror() return # If it is a file if file is not None: lfile = lizard.analyze_file(file) lfiles.append(lfile) # If it is a directory if directory is not None: for (root, subdir, files) in os.walk(directory): for file in files: fullpath = os.path.join(root, file) if extensions: for extension in extensions: if fullpath.endswith(extension): lfile = lizard.analyze_file(fullpath) lfiles.append(lfile) else: lfile = lizard.analyze_file(fullpath) lfiles.append(lfile) widths = getmaximumwidth(lfiles) if csv is True: printfilescsv(lfiles, widths) elif csv is False: printfiles(lfiles, widths)
def calc_cc(file_name): tmp = lizard.analyze_file(file_name) nloc = tmp.nloc ccs = [] for i in range(len(tmp.function_list)): ccs.append(tmp.function_list[i].cyclomatic_complexity) if not ccs: return nloc, 0 return nloc, statistics.mean(ccs)
def analyze(self, **kwargs): """Add code complexity information using Lizard. Current information includes cyclomatic complexity (ccn), avg lines of code and tokens, number of functions and tokens. Optionally, the following information can be included for every function: ccn, tokens, LOC, lines, name, args, start, end :param file_path: file path :param details: if True, it returns information about single functions :returns result: dict of the results of the analysis """ result = {} file_path = kwargs['file_path'] details = kwargs['details'] with warnings.catch_warnings(): warnings.simplefilter('ignore', DeprecationWarning) analysis = lizard.analyze_file(file_path) result['ccn'] = analysis.CCN result['avg_ccn'] = analysis.average_cyclomatic_complexity result['avg_loc'] = analysis.average_nloc result['avg_tokens'] = analysis.average_token_count result['num_funs'] = len(analysis.function_list) result['loc'] = analysis.nloc result['tokens'] = analysis.token_count result['ext'] = file_path.split(".")[-1] if not details: return result funs_data = [] for fun in analysis.function_list: fun_data = { 'ccn': fun.cyclomatic_complexity, 'tokens': fun.token_count, 'loc': fun.nloc, 'lines': fun.length, 'name': fun.name, 'args': fun.parameter_count, 'start': fun.start_line, 'end': fun.end_line } funs_data.append(fun_data) result['funs'] = funs_data return result
def analyse_file(source_path: Path): if not source_path.is_file(): return source_analysis = SourceAnalysis.from_file(source_path, scan_path) if not source_analysis.state == analysis.SourceState.analyzed: return i = lizard.analyze_file(str(source_path)) result = AnalysedFile(source_analysis) result.add_complexity(i.average_CCN, i.CCN) return result
def GET(self): fileobject = web.input(id='', filename="") repo = git.Repo(fileobject.repoURL) filecontent = repo.git.show("%s:%s" % (fileobject.id, fileobject.filename)) print("fileobject.filename", fileobject.filename) temp = str(fileobject.filename) + str(fileobject.id) with open(temp, "w") as tf: tf.write(filecontent) tf.close() i = lizard.analyze_file(temp) os.remove(temp) print("Average CC", i.average_cyclomatic_complexity) url = "http://localhost:8080/finish?cc=" + str( i.average_cyclomatic_complexity) finish_reply = requests.post(url)
def file_analysis(iface, scope): metrics = lizard.analyze_file(scope.path) iface.report_metric("ploc", metrics.nloc) if metrics.nloc > 400: iface.report_violation("max_file_length_400", "File length (PLOC) of " + str(metrics.nloc)) for fun in metrics.function_list: cc = fun.cyclomatic_complexity params = fun.parameter_count ploc = fun.nloc iface.report_metric("cyclomatic_complexity", cc, line=fun.start_line, function=fun.name) if cc > 10: iface.report_violation("max_cyclomatic_complexity_10", "function with cyclomatic complexity " + str(cc), line=fun.start_line, function=fun.name) if cc > 15: iface.report_violation("max_cyclomatic_complexity_15", "function with cyclomatic complexity " + str(cc), line=fun.start_line, function=fun.name) iface.report_metric("function_parameters", params, line=fun.start_line, function=fun.name) if params > 6: iface.report_violation("max_function_parameters_6", "function with " + str(params) + " parameters", line=fun.start_line, function=fun.name) iface.report_metric("ploc", ploc, line=fun.start_line, function=fun.name) if ploc > 40: iface.report_violation("max_function_length_40", "Function length of " + str(ploc), line=fun.start_line, function=fun.name)
def doWork(file, commit): folder_path = home_directory + "/.worker" + str(workerId) if(os.path.exists(folder_path) != True): print(git_repo_url) repo = Repo.clone_from(git_repo_url, folder_path) else: repo = Repo(folder_path) #checkout commit repo_checkout = repo.git.checkout(commit) path_to_file = folder_path + file score = lizard.analyze_file(path_to_file).average_cyclomatic_complexity print("File: ", path_to_file, "\nCommit: ", commit, "\nCC: ", score) submitWork(path_to_file, commit, score)
def parseFile(dataFileName, dataFile, counts): class complexityData: inIf = False inLoop = False nestedLoop = 0 # TODO halOperatorList = { } # Halstead complexity metrics data {operator:numOps} halOperandList = { } # Halstead complexity metrics data {operand:numOps} # Analyze each line of the file to populate counts line = dataFile.readline() while (line): analyzeLine(line, dataFile, complexityData, counts) line = dataFile.readline() # Calculate the cyclomatic complexity data for this file (split into functions) filenameDotC = dataFileName[:-4] + ".c" copyfile(dataFileName, filenameDotC) # shutil library cyclomaticFunctions = lizard.analyze_file( filenameDotC) # Function complexities # Calculate overall program cyclomatic complexity cyclomaticData = calcCyclomatic(cyclomaticFunctions.function_list, dataFile) counts["cyclomatic"] = cyclomaticData[0] counts["cyclAvg"] = float("{0:.2f}".format( cyclomaticData[1])) # 2 decimal places counts["cyclMed"] = cyclomaticData[2] remove(filenameDotC) # Remove the .c file used by the lizard # Calculate the halstead complexity data for this file based on recorded data halstead = calcHalstead.halsteadValues() # Initialize class halstead.calcHalstead(complexityData.halOperatorList, complexityData.halOperandList) counts["halsteadVolume"] = int(halstead.getVolume()) counts["halsteadDifficulty"] = float("{0:.2f}".format( halstead.getDifficulty())) counts["halsteadEffort"] = int(halstead.getEffort()) # Use the overall program cyclomatic and halstead complexities to determine maintainability index maintainability = calcMIndex(counts["lines"], counts["halsteadVolume"], counts["cyclomatic"]) counts["maintainability"] = float("{0:.2f}".format(maintainability))
def GET(self): #gets the file and calculate cyclomatic complexity of the file args_passed = web.input(id='', filename="") print(args_passed.id) repo = git.Repo("C:/Users/HP/Documents/GitHub/mlframework") file_content = repo.git.show("%s:%s" % (args_passed.id, args_passed.filename)) print("args_passed.filename", args_passed.filename) temp_filename = str(args_passed.filename) + str(args_passed.id) with open(temp_filename, "w") as tf: tf.write(file_content) #temp_file.write(file_content) tf.close() i = lizard.analyze_file(temp_filename) os.remove(temp_filename) print("CC", i.average_cyclomatic_complexity) url = "http://localhost:8080/work_done?cc=" + str( i.average_cyclomatic_complexity) workdone_response = requests.post(url)
def complex_analyze(self, root_path): res = { "mcc": 0.0, "fileNumber": 0, "functionNumber": 0, "loc": 0, "commentRate": 0.0, "tarskiModel": 0 } comment_lines = 0 mcc = 0.0 for root, dirs, files in os.walk(root_path): for file in files: ext = os.path.splitext(file)[1] file_full_path = os.path.join(root, file) # 迭代所有符合扩展名要求的文件 if ext in EXT_LIMITATION_COMPLEX: lizard_result = lizard.analyze_file(file_full_path) res["fileNumber"] += 1 mcc += lizard_result.CCN res["functionNumber"] += lizard_result.function_list.__len__( ) res["loc"] += lizard_result.nloc if ext == ".py": loc, cloc = CommentCounter.get_comment_analysis_for_python_file( file_full_path) comment_lines += cloc else: loc, cloc = CommentCounter.get_comment_analysis_for_C_file( file_full_path) comment_lines += cloc res["mcc"] = mcc / res["functionNumber"] res["commentRate"] = comment_lines / res["loc"] res["tarskiModel"] = res["loc"] return res
def _lizard_file(self, filename): columns = [ 'filename', 'function', 'cc', 'nloc', 'token', 'line_start', 'line_end' ] result = lizard.analyze_file(filename) if result is None: return None df = pandas.DataFrame(columns=columns) for function in result.function_list: line_start = int(function.start_line) line_end = int(function.end_line) sanitized_filename = filename[len( self._path_root):] # we remove the tmp dir df.loc[len(df)] = [ sanitized_filename, function.name, function.cyclomatic_complexity, function.nloc, function.token_count, function.start_line, function.end_line ] return df
def lizard(self, file_name1): print(file_name1) for j in res_commit_api['files']: if j['filename'] == file_name1: x = ((j['raw_url'])) filename, file_extension = os.path.splitext(x) # print(filename +' '+ file_extension) response = request.urlopen(x) html = response.read() html = html.decode() full_path = temp_dir_complexity + file_extension with open(full_path, 'w') as f: print(html, file=f) i = lizard.analyze_file(full_path) print(i.__dict__) try: self.temp1 = i.function_list os.remove(full_path) except: print('Code not generic so no complexity') pass
def GET(self): # get the passed parameters commit hex and filename from the url worker_input = web.input(commithex='',filename='') repo = Repo("C:/Users/meenuneenu/Documents/GitHub/mlframework") # Take the file content at the time of passed commit and save it in a .py file file_content = repo.git.show("%s:%s" % (worker_input.commithex, worker_input.filename)) #with tempfile.NamedTemporaryFile(suffix='.py',delete=True) as tmp: # tmp.write(file_content.encode()) filename_tmp = worker_input.commithex + worker_input.filename with open(filename_tmp,'w+') as fp: fp.write(file_content) fp.close() # Calculate the cyclomatic complexity of the file cyclomatic_complexity = lizard.analyze_file(filename_tmp).average_cyclomatic_complexity os.remove(filename_tmp) print("CC: ",cyclomatic_complexity) # Pass the result to master url = "http://localhost:8080/result?result="+str(cyclomatic_complexity) print(url) result = req.post(url) print("From Master after result",result.text)
def main_function(): arr = [] # array containing every analyzed file for subdir, dirs, files in os.walk( args.p): # go through every file within a given directory for file in files: file_path = subdir + os.sep + file if file_path.endswith('.cpp') or file_path.endswith( '.py') or file_path.endswith('.js') or file_path.endswith( '.java'): i = lizard.analyze_file(file_path) print(i.function_list[0].__dict__) my_json = json.dumps(i.function_list[0].__dict__, indent=4) arr.append(my_json) with open('data.json', 'w') as outfile: outfile.write("[\n") first = True for item in arr: if first == True: first = False else: outfile.write(",\n") outfile.write(item) outfile.write("\n]")
def get_complexity_info(self, f, import_type): funs = [] i = lizard.analyze_file(f) info_comments = self.get_comment_info(f) # if i.nloc != info_comments.get('loc'): # self._logger.warning("CLOC and Lizard report different LOC : " + str(i.nloc) + " (Lizard) " # + str(info_comments.get('loc')) + " (CLOC)") overall = { 'ccn': i.CCN, 'avg_ccn': i.average_cyclomatic_complexity, 'avg_loc': i.average_nloc, 'avg_tokens': i.average_token_count, 'funs': len(i.function_list), 'loc': i.nloc, 'tokens': i.token_count, 'comments': info_comments.get('comments'), 'blanks': info_comments.get('blanks') } if import_type == code2db_extract_commit_file.Code2DbCommitFile.FULL_IMPORT_TYPE: for fun in i.function_list: funs.append({ 'ccn': fun.cyclomatic_complexity, 'tokens': fun.token_count, 'loc': fun.nloc, 'lines': fun.length, 'name': fun.name, 'args': fun.parameter_count, 'start': fun.start_line, 'end': fun.end_line }) return overall, funs
def test_should_report_when_having_other_problem_and_continue(self, mock_stderr, mock_open): mock_open.side_effect = IOError("[Errno 2] No such file or directory") analyze_file("f1.c") self.assertEqual(1, mock_stderr.write.call_count) error_message = mock_stderr.write.call_args[0][0] self.assertEqual("Error: Fail to read source file 'f1.c'\n", error_message)
program = sys.argv[1] output = sys.argv[2] if len(sys.argv) == 3 else None filename, extension = os.path.splitext(program) bindir = os.path.dirname(os.path.realpath(__file__)) # count total number of lines lines = len(open(program, "r").readlines()) # call lizard ana = lizard.analyze_file(program) # call cloc cloc = commands.getstatusoutput("cloc --csv %s 2> /dev/null | tail -1" % program)[1].split(",") # call commentedCodeDetector.py halstead = {} if extension in [".cc", ".c", ".java"]: out = commands.getstatusoutput("%s/commentedCodeDetector.py -fm %s 2> /dev/null" % (bindir, program))[1] for line in out.split("\n"): key, val = map(str.strip, line.split()) halstead[key] = float(val) # build the output