diff --git a/build-tools/capi_parser/requirements.txt b/build-tools/capi_parser/requirements.txt index d4185940174f0f7c7369b30a840b57329dd7e4d5..fe15e3ba08ca5cd720bccf53bcb11daca2727f14 100644 Binary files a/build-tools/capi_parser/requirements.txt and b/build-tools/capi_parser/requirements.txt differ diff --git a/build-tools/capi_parser/src/bin/config.py b/build-tools/capi_parser/src/bin/config.py index fd04dc67caad498ba0720a683ae633a30532f756..9eabf4c138c1eaf41ecaea91938b8bf0ad24cc7f 100644 --- a/build-tools/capi_parser/src/bin/config.py +++ b/build-tools/capi_parser/src/bin/config.py @@ -50,7 +50,7 @@ def run_tools(options): if tool_name == ToolNameType["COLLECT"].value: parser.parser(options.parser_path) elif tool_name == ToolNameType["DIFF"].value: - diff.process_dir(options.diff_path_old, options.diff_path_new) + diff.process_dir(options.diff_path_old, options.diff_path_new, options.output_path) elif tool_name == ToolNameType["CHECK"].value: check.curr_entry(options.path, options.root_path, options.checker, options.output) elif tool_name == ToolNameType['COLLECT_H'].value: @@ -87,7 +87,7 @@ class Config(object): "abbr": "-O", "required": False, "type": str, - "help": "collect_file工具输出文件路径" + "help": "工具输出文件路径" }, { "name": "--codecheck--path", diff --git a/build-tools/capi_parser/src/bin/write_md.py b/build-tools/capi_parser/src/bin/write_md.py index defde7281e30743df0ca000428a71a59a86f5c50..1d7368508c8192c12db7a12e3ce2d2f6e75a3103 100644 --- a/build-tools/capi_parser/src/bin/write_md.py +++ b/build-tools/capi_parser/src/bin/write_md.py @@ -18,14 +18,14 @@ import stat import pandas as pd -def sort_by_kit(result_info_list: list): +def sort_by_kit(result_info_list: list, output_path): """ Description:列表按kit排序 """ sort_by_kit_list = [] if 1 == len(result_info_list): sort_by_kit_list.extend(result_info_list) - write_data_in_md(result_info_list[0].kit_name, result_info_list) + write_data_in_md(result_info_list[0].kit_name, result_info_list, output_path) return sort_by_kit_list if result_info_list: kit_list = sorted(result_info_list, key=lambda obj: obj.kit_name) @@ -36,13 +36,13 @@ def sort_by_kit(result_info_list: list): same_element.append(obj_element) else: sorted_data = sort_by_file_path(same_element) - write_data_in_md(first_kit_name, sorted_data) + write_data_in_md(first_kit_name, sorted_data, output_path) sort_by_kit_list.extend(sorted_data) first_kit_name = obj_element.kit_name same_element = [] if same_element: sorted_data = sort_by_file_path(same_element) - write_data_in_md(first_kit_name, sorted_data) + write_data_in_md(first_kit_name, sorted_data, output_path) sort_by_kit_list.extend(sorted_data) return sort_by_kit_list @@ -115,7 +115,7 @@ def change_list_obj_to_dict(list_of_obj: list): return data_list -def write_data_in_md(kit_name: str, write_data: list): +def write_data_in_md(kit_name: str, write_data: list, output_path): """ Description:生成.md表格 """ @@ -125,7 +125,8 @@ def write_data_in_md(kit_name: str, write_data: list): list_element_dict = change_list_obj_to_dict(write_data) md_data = create_md_table_with_pandas(list_element_dict) if md_data: - path_str = r'diff合集' + diff_str = r'diff合集' + path_str = os.path.abspath(os.path.join(output_path, diff_str)) if not os.path.exists(path_str): os.mkdir(path_str) md_name = os.path.abspath(os.path.join(path_str, file_name)) @@ -135,9 +136,9 @@ def write_data_in_md(kit_name: str, write_data: list): os.close(fd) -def write_md_entrance(result_info_list): +def write_md_entrance(result_info_list, output_path): """ Description:将数据生成.md表格入口 """ - sorted_data = sort_by_kit(result_info_list) + sorted_data = sort_by_kit(result_info_list, output_path) return sorted_data diff --git a/build-tools/capi_parser/src/coreImpl/diff/diff.py b/build-tools/capi_parser/src/coreImpl/diff/diff.py index dd32e0e1f725e247666ff55435fe03ce15152dd1..43f15d2cacb0b87ad2fe5b1d080b505f6adbd6df 100644 --- a/build-tools/capi_parser/src/coreImpl/diff/diff.py +++ b/build-tools/capi_parser/src/coreImpl/diff/diff.py @@ -21,8 +21,8 @@ def process_pr(pr_id): print("开发中...") -def process_dir(old_dir, new_dir): - start_diff_file(old_dir, new_dir) +def process_dir(old_dir, new_dir, output_path): + start_diff_file(old_dir, new_dir, output_path) def get_dir_by_pr(pr: str): diff --git a/build-tools/capi_parser/src/coreImpl/diff/diff_file.py b/build-tools/capi_parser/src/coreImpl/diff/diff_file.py index dfce73c1e946b02ef6d0cef955ad11d621ef814c..861a47bc039d1ffbeedd4ab6591af71e496021fe 100644 --- a/build-tools/capi_parser/src/coreImpl/diff/diff_file.py +++ b/build-tools/capi_parser/src/coreImpl/diff/diff_file.py @@ -20,8 +20,8 @@ import stat from collections import OrderedDict import openpyxl as op from coreImpl.parser.parser import parser_include_ast -from coreImpl.diff.diff_processor_node import judgment_entrance -from typedef.diff.diff import OutputJson +from coreImpl.diff.diff_processor_node import judgment_entrance, change_data_total +from typedef.diff.diff import OutputJson, ApiChangeData from bin.write_md import write_md_entrance global_old_dir = '' @@ -29,13 +29,117 @@ global_new_dir = '' diff_info_list = [] -def start_diff_file(old_dir, new_dir): +def get_modification_type_dict(): + modification_type_dict = { + 'API新增': 0, + 'API删除': 0, + 'API废弃': 0, + 'API修改': 0, + 'API修改(原型修改)': 0, + 'API修改(约束变化)': 0 + } + return modification_type_dict + + +def get_compatible_dict(): + compatible_dict = { + '兼容': 0, + '不兼容': 0 + } + return compatible_dict + + +def change_to_json(data): + data_of_json = json.dumps(data, ensure_ascii=False, indent=4) + return data_of_json + + +def get_api_change_obj(api_data): + modification_type_dict = get_modification_type_dict() + compatible_dict = get_compatible_dict() + change_data_obj = ApiChangeData() + key = 0 + for element in api_data: + if element.is_api_change: + change_type = 'API变更' + else: + change_type = '非API变更' + if 0 == key: + change_data_obj.set_api_name(element.api_node_name) + change_data_obj.set_kit_name(element.kit_name) + change_data_obj.set_sub_system(element.sub_system) + change_data_obj.set_is_api_change(element.is_api_change) + change_data_obj.set_diff_type(element.diff_type.name) + change_data_obj.set_change_type(change_type) + change_data_obj.set_old_all_text(element.old_api_full_text) + change_data_obj.set_new_all_text(element.new_api_full_text) + change_data_obj.set_compatible_total(element.is_compatible) + key = 1 + else: + old_all_text = '{}#&#{}'.format(change_data_obj.old_all_text, element.old_api_full_text) + new_all_text = '{}#&#{}'.format(change_data_obj.new_all_text, element.new_api_full_text) + diff_type_all = '{}#&#{}'.format(change_data_obj.get_diff_type(), element.diff_type.name) + change_type_all = '{}#&#{}'.format(change_data_obj.get_change_type(), change_type) + compatible_data_all = '{}#&#{}'.format(change_data_obj.get_compatible_total(), element.is_compatible) + change_data_obj.set_old_all_text(old_all_text) + change_data_obj.set_new_all_text(new_all_text) + change_data_obj.set_diff_type(diff_type_all) + change_data_obj.set_change_type(change_type_all) + change_data_obj.set_compatible_total(compatible_data_all) + if element.is_compatible and (0 == compatible_dict.get('兼容')): + compatible_dict['兼容'] = 1 + elif not element.is_compatible and (0 == compatible_dict.get('不兼容')): + compatible_dict['不兼容'] = 1 + if element.api_modification_type in modification_type_dict: + modification_type_dict[element.api_modification_type] = 1 + compatible_str = change_to_json(compatible_dict) + modification_type_str = change_to_json(modification_type_dict) + change_data_obj.set_compatible(compatible_str) + change_data_obj.set_change_num(modification_type_str) + + return change_data_obj + + +def collect_api_change(change_data: list): + api_change_data = [] + for list_element in change_data: + change_obj = get_api_change_obj(list_element) + api_change_data.append(change_obj) + + return api_change_data + + +def collect_node_api_change(api_change_info_list): + change_data = [] + for api_change_info in api_change_info_list: + info_data = [ + api_change_info.api_name, + api_change_info.kit_name, + api_change_info.sub_system, + api_change_info.is_api_change, + api_change_info.diff_type, + api_change_info.change_type, + api_change_info.compatible, + api_change_info.change_num, + api_change_info.old_all_text, + api_change_info.new_all_text, + api_change_info.compatible_total + ] + change_data.append(info_data) + + return change_data + + +def start_diff_file(old_dir, new_dir, output_path): result_info_list = global_assignment(old_dir, new_dir) - generate_excel(result_info_list) - write_md_entrance(result_info_list) + total = change_data_total + collect_api_change_data = collect_api_change(total) + generate_excel(result_info_list, collect_api_change_data, output_path) + write_md_entrance(result_info_list, output_path) result_json = result_to_json(result_info_list) - write_in_txt(result_json, r'./ndk_diff.txt') - print(result_json) + diff_result_path = r'./diff_result.txt' + output_path_txt = os.path.abspath(os.path.join(output_path, diff_result_path)) + write_in_txt(result_json, output_path_txt) def disposal_result_data(result_info_list): @@ -59,17 +163,28 @@ def disposal_result_data(result_info_list): return data -def generate_excel(result_info_list): +def generate_excel(result_info_list, api_change_data, output_path): data = disposal_result_data(result_info_list) wb = op.Workbook() ws = wb['Sheet'] + ws.title = 'api差异' ws.append(['操作标记', '差异项-旧版本', '差异项-新版本', '兼容', '.h文件', '归属子系统', 'kit', 'API变化', 'API修改类型']) for title in data: d = title[0], title[1], title[2], title[3], title[4],\ title[5], title[6], title[7], title[8] ws.append(d) - wb.save('diff.xlsx') + + change_data_list = collect_node_api_change(api_change_data) + ws_of_change = wb.create_sheet('api变更次数统计') + ws_of_change.append(['api名称', 'kit名称', '归属子系统', '是否是api', '操作标记', '变更类型', + '兼容性', '变更次数', '差异性-旧版本', '差异性-新版本', '兼容性列表']) + for element in change_data_list: + change_data = element[0], element[1], element[2], element[3], element[4], element[5],\ + element[6], element[7], element[8], element[9], element[10], + ws_of_change.append(change_data) + output_path_xlsx = os.path.abspath(os.path.join(output_path, 'diff.xlsx')) + wb.save(output_path_xlsx) def global_assignment(old_dir, new_dir): diff --git a/build-tools/capi_parser/src/coreImpl/diff/diff_processor_node.py b/build-tools/capi_parser/src/coreImpl/diff/diff_processor_node.py index e9580d71dbfc35e4ac573886523c3a81fb124b1e..82729055a87d407e30aff2c549f88a5e8981ca7b 100644 --- a/build-tools/capi_parser/src/coreImpl/diff/diff_processor_node.py +++ b/build-tools/capi_parser/src/coreImpl/diff/diff_processor_node.py @@ -22,14 +22,26 @@ from coreImpl.diff.diff_processor_permission import compare_permission, RangeCha from typedef.diff.diff import TAGS, DiffType, DiffInfo, Scene current_file = os.path.dirname(__file__) +change_data_total = [] + + +def get_not_api_kind_list(): + not_api_kind_list = [ + 'MACRO_DEFINITION', + 'TRANSLATION_UNIT', + 'MACRO_INSTANTIATION', + 'INCLUSION_DIRECTIVE' + ] + return not_api_kind_list def wrap_diff_info(old_info, new_info, diff_info: DiffInfo): + not_api_kind_list = get_not_api_kind_list() if old_info is not None: if 'temporary_name' in old_info['name']: old_info['name'] = '' if (not diff_info.is_api_change) and 'kind' in old_info \ - and 'MACRO_DEFINITION' != old_info['kind'] and 'TRANSLATION_UNIT' != old_info['kind']: + and (old_info['kind'] not in not_api_kind_list): diff_info.set_is_api_change(True) diff_info.set_api_name(old_info['name']) diff_info.set_api_type(old_info['kind']) @@ -51,7 +63,7 @@ def wrap_diff_info(old_info, new_info, diff_info: DiffInfo): if 'temporary_name' in new_info['name']: new_info['name'] = '' if (not diff_info.is_api_change) and 'kind' in new_info \ - and 'MACRO_DEFINITION' != new_info['kind'] and 'TRANSLATION_UNIT' != new_info['kind']: + and (new_info['kind'] not in not_api_kind_list): diff_info.set_is_api_change(True) diff_info.set_api_name(new_info['name']) diff_info.set_api_type(new_info['kind']) @@ -481,11 +493,13 @@ def process_variable_value(old, new, diff_variable_list): DiffInfo(DiffType.VARIABLE_VALUE_CHANGE)) diff_variable_list.append(diff_info) + def process_constant_to_variable(old, new, diff_constant_list): if not new['is_const']: diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_CHANGE_TO_VARIABLE)) diff_constant_list.append(diff_info) + def process_constant_name(old, new, diff_constant_list): if old['name'] != new['name']: diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_NAME_CHANGE)) @@ -565,6 +579,12 @@ process_data = { } +def collect_change_data_total(data: dict, diff_info_list): + for element in diff_info_list: + element.set_api_node_name(data['name']) + change_data_total.append(diff_info_list) + + def judgment_entrance(old, new, data_type=0): """ Args: @@ -578,15 +598,21 @@ def judgment_entrance(old, new, data_type=0): if old is None: diff_type = DiffType.ADD_FILE if data_type == 1 else DiffType.ADD_API diff_info_list.append(wrap_diff_info(old, new, DiffInfo(diff_type))) + if diff_type == DiffType.ADD_API: + collect_change_data_total(new, diff_info_list) return diff_info_list if new is None: diff_type = DiffType.REDUCE_FILE if data_type == 1 else DiffType.REDUCE_API diff_info_list.append(wrap_diff_info(old, new, DiffInfo(diff_type))) + if diff_type == DiffType.REDUCE_API: + collect_change_data_total(old, diff_info_list) return diff_info_list kind = new['kind'] diff_info_list.extend(process_comment_str(old, new)) if kind in process_data: diff_info_list.extend(process_data[kind](old, new)) + if diff_info_list: + collect_change_data_total(new, diff_info_list) return diff_info_list diff --git a/build-tools/capi_parser/src/coreImpl/parser/parse_include.py b/build-tools/capi_parser/src/coreImpl/parser/parse_include.py index 87cef164f630f6e384fb7293446107c11379b7da..39bf9a6658f3efa6b5ab572978ee3cbe946c3a62 100644 --- a/build-tools/capi_parser/src/coreImpl/parser/parse_include.py +++ b/build-tools/capi_parser/src/coreImpl/parser/parse_include.py @@ -509,9 +509,7 @@ def open_file(include_path): def api_entrance(share_lib, include_path, gn_path=None, link_path=None): # 统计入口 # clang.cindex需要用到libclang.dll共享库 所以配置共享库 - if Config.loaded: - print("config.loaded == true") - else: + if not Config.loaded: Config.set_library_file(share_lib) print("lib.dll: install path") # 创建AST索引 @@ -537,7 +535,6 @@ def get_include_file(include_file_path, link_path, gn_path=None): # 库路径 libclang_path = StringConstant.LIB_CLG_PATH.value # c头文件的路径 file_path = include_file_path - print(file_path) # 头文件链接路径 link_include_path = link_path # 可以通过列表传入 data = api_entrance(libclang_path, file_path, gn_path, link_include_path) # 调用接口 diff --git a/build-tools/capi_parser/src/coreImpl/parser/parser.py b/build-tools/capi_parser/src/coreImpl/parser/parser.py index 59411067f8e63cf4c934604cc66eb7bc20a93104..67b5f0fbe7745d3cac5a5e818c33a2150778ed00 100644 --- a/build-tools/capi_parser/src/coreImpl/parser/parser.py +++ b/build-tools/capi_parser/src/coreImpl/parser/parser.py @@ -286,28 +286,21 @@ def parser(directory_path): # 目录路径 return data_total -def parser_include_ast(gn_file_path, include_path, flag=-1): # 对于单独的.h解析接口 +def parser_include_ast(dire_file_path, include_path, flag=-1): # 对于单独的.h解析接口 correct_include_path = [] link_include_path = [] copy_std_lib(link_include_path) find_include(link_include_path) - link_include(gn_file_path, StringConstant.FUNK_NAME.value, link_include_path) + link_include(dire_file_path, StringConstant.FUNK_NAME.value, link_include_path) if len(link_include_path) <= 1: - copy_self_include(link_include_path, gn_file_path, flag) - - modes = stat.S_IRWXO | stat.S_IRWXG | stat.S_IRWXU - fd = os.open('include_file_suffix.txt', os.O_WRONLY | os.O_CREAT, mode=modes) + copy_self_include(link_include_path, dire_file_path, flag) for item in include_path: split_path = os.path.splitext(item) if split_path[1] == '.h': # 判断.h结尾 correct_include_path.append(item) - else: - exc = 'The file does not end with.h: {}\n'.format(item) - os.write(fd, exc.encode()) - os.close(fd) - data = parse_include.get_include_file(correct_include_path, link_include_path, gn_file_path) + data = parse_include.get_include_file(correct_include_path, link_include_path, dire_file_path) for item in data: if 'children' in item: diff --git a/build-tools/capi_parser/src/typedef/diff/diff.py b/build-tools/capi_parser/src/typedef/diff/diff.py index 3d3cdd23a544ea5eec85148d12c8dc99d0bf9e81..1f093709a1161e47bad2f5f5e1c1d893757f8774 100644 --- a/build-tools/capi_parser/src/typedef/diff/diff.py +++ b/build-tools/capi_parser/src/typedef/diff/diff.py @@ -287,6 +287,7 @@ class DiffInfo: kit_name = '' sub_system = '' class_name = '' + api_node_name = '' def __init__(self, diff_type: DiffType): self.diff_type = diff_type @@ -395,6 +396,12 @@ class DiffInfo: def get_class_name(self): return self.class_name + def set_api_node_name(self, api_node_name): + self.api_node_name = api_node_name + + def get_api_node_name(self): + return self.api_node_name + class OutputJson: api_name: str = '' @@ -429,3 +436,83 @@ class OutputJson: self.kit_name = diff_info.kit_name self.sub_system = diff_info.sub_system self.class_name = diff_info.class_name + + +class ApiChangeData: + api_name: str = '' + kit_name: str = '' + sub_system: str = '' + is_api_change = False + diff_type: str = '' + change_type: str = '' + compatible = {} + change_num = {} + old_all_text: str = '' + new_all_text: str = '' + compatible_total = False + + def set_api_name(self, api_name): + self.api_name = api_name + + def get_api_name(self): + return self.api_name + + def set_kit_name(self, kit_name): + self.kit_name = kit_name + + def get_kit_name(self): + return self.kit_name + + def set_sub_system(self, sub_system): + self.sub_system = sub_system + + def get_sub_system(self): + return self.sub_system + + def set_is_api_change(self, is_api_change): + self.is_api_change = is_api_change + + def get_is_api_change(self): + return self.is_api_change + + def set_diff_type(self, diff_type): + self.diff_type = diff_type + + def get_diff_type(self): + return self.diff_type + + def set_change_type(self, change_type): + self.change_type = change_type + + def get_change_type(self): + return self.change_type + + def set_compatible(self, compatible): + self.compatible = compatible + + def get_compatible(self): + return self.compatible + + def set_change_num(self, change_num): + self.change_num = change_num + + def get_change_num(self): + return self.change_num + + def set_old_all_text(self, old_all_text): + self.old_all_text = old_all_text + + def get_old_all_text(self): + return self.old_all_text + + def set_new_all_text(self, new_all_text): + self.new_all_text = new_all_text + + def get_new_all_text(self): + return self.new_all_text + + def set_compatible_total(self, compatible_total): + self.compatible_total = compatible_total + + def get_compatible_total(self): + return self.compatible_total diff --git a/build-tools/capi_parser/src/utils/constants.py b/build-tools/capi_parser/src/utils/constants.py index 1f9eb05c03666ee037b1ab3be7147c4432880d2b..488ca3b313548ba7185398f6c2b2b5622d5e1313 100644 --- a/build-tools/capi_parser/src/utils/constants.py +++ b/build-tools/capi_parser/src/utils/constants.py @@ -32,7 +32,7 @@ class StringConstant(enum.Enum): SYSROOT = r'.\sysroot' RESULT_HEAD_NAME = "result_total.xlsx" PARSER_DIRECT_EXCEL_NAME = 'parser_direct_data.xlsx' - FILE_LEVEL_API_DATA = r'.\file_api_json.json' + FILE_LEVEL_API_DATA = r'.\api_kit_c.json' class RegularExpressions(enum.Enum):