def parse_functions(main_cpp_name, main_cpp_path, silent=False): p = subprocess.Popen( "clang-check -ast-dump %s --extra-arg='-fno-color-diagnostics' --" % main_cpp_path, shell=True, stdout=subprocess.PIPE) main_cpp_found = False functions = {} if not silent: print('parsing function declarations:') while p.poll() is None: line = p.stdout.readline().decode('utf-8') if main_cpp_name in line: main_cpp_found = True if main_cpp_found and 'FunctionDecl' in line and 'line' in line: line = line.strip() func_decl = FunctionDeclaration(line) if not func_decl.error: func_prototype = str(func_decl) if not silent: print('[line %d-%d] %s' % (func_decl.start, func_decl.end, func_decl)) if func_prototype not in functions: functions[func_prototype] = Function(func_decl) else: functions[func_prototype].add_declaration(func_decl) elif not silent: print('error occurred in %s', line) if not silent: print('\nparsing cpp file:') main_cpp_contents = read_file(main_cpp_path, silent=silent) for i, func_decl in enumerate(FunctionDeclaration.function_declares): if func_decl.end <= len(main_cpp_contents): if i > 1: start = max( FunctionDeclaration.get_by_id(i - 1).end, func_decl.start - 20) else: start = max(0, func_decl.start - 20) end = func_decl.end func_decl.set_body([(x, main_cpp_contents[x]) for x in range(start, end)]) return functions
def parse_functions_new(project_dir, files, silent=False, functions=None): if not functions: functions = dict() split_sources_headers(files) sources, headers, _ = split_sources_headers(files) files = sources + headers sources_path = build_full_paths(project_dir, sources) files_path = build_full_paths(project_dir, files) p = subprocess.Popen( "clang-check -ast-dump %s --extra-arg='-fno-color-diagnostics' --" % ' '.join(sources_path), shell=True, stdout=subprocess.PIPE, stderr=silent and subprocess.PIPE or None) # print(sources_path) current_file = None if not silent: print('parsing function declarations:') func_decl_lines = [] while p.poll() is None: line = p.stdout.readline().decode('utf-8').strip() result = re.findall(r'<(?!(line|col))(.*?), (line|col):.*?>', line) if result: file_name = result[0][1] flag = False for i, file_path in enumerate(files_path): if file_path in file_name: # print(files[i], line) current_file = files[i] flag = True break if not flag: current_file = None if current_file and 'line' in line and ' default ' not in line and \ ('FunctionDecl' in line or 'CXXConstructorDecl' in line or 'CXXDestructorDecl' in line or 'CXXMethodDecl' in line): # print(line) line = line.strip() func_decl_lines.append((line, current_file)) file_func_decls = {x: [] for x in files} for line, file in func_decl_lines: func_decl = FunctionDeclaration(line, file) if not func_decl.error: func_prototype = str(func_decl) if not silent: print('[%s:%d-%d] %s' % (func_decl.file, func_decl.start, func_decl.end, func_decl)) if func_prototype not in functions: functions[func_prototype] = Function(func_decl) else: functions[func_prototype].add_declaration(func_decl) file_func_decls[file].append(func_decl) elif not silent: print('error occurred in %s' % line) if not silent: print('\nparsing cpp files:') for i, file in enumerate(files): try: file_contents = read_file(files_path[i], silent=silent) func_decls = sorted(file_func_decls[file], key=lambda x: x.start) for j, func_decl in enumerate(func_decls): if func_decl.end <= len(file_contents): # print(j, func_decl) if j > 0: start = max(func_decls[j - 1].end, func_decl.start - 20) else: start = max(0, func_decl.start - 20) end = min(func_decl.end, len(file_contents) - 1) func_decl.calculate_length( file_contents[func_decl.start:end + 1]) func_decl.set_body([(x, file_contents[x]) for x in range(start, end + 1)]) except Exception as e: if not silent: print(e.args) for function in functions.values(): function.calculate_length() return functions
def main(project_dir, silent=False): main_cpp_name = 'p2.cpp' main_cpp_path = os.path.join(project_dir, main_cpp_name) main_cpp_found = False functions = {} clang_check_score = 6 p = subprocess.Popen("clang-check -ast-dump %s --" % main_cpp_path, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not silent: print('parsing function declarations:') while p.poll() is None: line = p.stdout.readline().decode('utf-8') if main_cpp_name in line: main_cpp_found = True if main_cpp_found and 'FunctionDecl' in line and 'line' in line: line = re.sub(r'\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))', '', line).strip() func_decl = FunctionDeclaration(line) if not func_decl.error: func_prototype = str(func_decl) if not silent: print('[line %d-%d] %s' % (func_decl.start, func_decl.end, func_decl)) if func_prototype not in functions: functions[func_prototype] = Function(func_decl) else: functions[func_prototype].add_declaration(func_decl) elif not silent: print('error occurred in %s', line) if not silent: print('\nparsing cpp file:') main_cpp_contents = read_file(main_cpp_path, silent=silent) for i, func_decl in enumerate(FunctionDeclaration.function_declares): if func_decl.end <= len(main_cpp_contents): if i > 1: start = max(FunctionDeclaration.get_by_id(i - 1).end, func_decl.start - 5) else: start = max(0, func_decl.start - 5) end = func_decl.end func_decl.set_body([(x, main_cpp_contents[x]) for x in range(start, end)]) if not silent: print('\ncounting function lines:') for func_prototype, func in functions.items(): if not silent: print(func) line_count = func.count_lines() print('total lines: %d' % line_count) if line_count > 50 and clang_check_score > 0: clang_check_score -= 1 if not silent: print('\nclang-check score: %d' % clang_check_score) clang_tidy_warnings = {} clang_tidy_warnings_count = 0 clang_tidy_score = 0 p = subprocess.Popen("clang-tidy %s -checks=-*,misc-*,performance-*,clang-analyzer-*," "readability-function-size,readability-identifier-naming,readability-named-parameter," "readability-redundant-*,readability-simplify-boolean-expr,readability-mis*," "--extra-arg='-fno-color-diagnostics' --" % main_cpp_path, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not silent: print('\nparsing clang-tidy results:') while p.poll() is None: line = p.stdout.readline().decode('utf-8') line = re.sub(r'\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))', '', line).strip() res = re.findall(r'warning:.*?\[(.*?)\]', line) if res: if res[0] in clang_tidy_warnings: clang_tidy_warnings[res[0]] += 1 else: clang_tidy_warnings[res[0]] = 1 clang_tidy_warnings_count += 1 if clang_tidy_warnings_count <= 10: clang_tidy_score += 2 elif clang_tidy_warnings_count <= 25: clang_tidy_score += 1 if len(clang_tidy_warnings) <= 3: clang_tidy_score += 2 elif len(clang_tidy_warnings) <= 6: clang_tidy_score += 1 if not silent: pprint(clang_tidy_warnings) print('\nclang-tidy score: %d' % clang_tidy_score) if silent: print('%d,%d' % (clang_check_score, clang_tidy_score))