• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2023 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import json
17import subprocess
18import os
19import re
20from collections import OrderedDict
21from clang.cindex import CursorKind
22from coreImpl.diff.diff_processor_permission import compare_permission, RangeChange
23from typedef.diff.diff import TAGS, DiffType, DiffInfo, Scene
24from utils.constants import RegularExpressions
25
26current_file = os.path.dirname(__file__)
27change_data_total = []
28
29
30def get_not_api_kind_list():
31    not_api_kind_list = [
32        'MACRO_DEFINITION',
33        'TRANSLATION_UNIT',
34        'MACRO_INSTANTIATION',
35        'INCLUSION_DIRECTIVE'
36    ]
37    return not_api_kind_list
38
39
40def set_result_common_infor(node_infor, diff_info: DiffInfo):
41    diff_info.set_api_name(node_infor['name'])
42    diff_info.set_api_type(node_infor['kind'])
43    diff_info.set_api_line(node_infor['location']['location_line'])
44    diff_info.set_api_column(node_infor['location']['location_column'])
45    diff_info.set_api_file_path(node_infor['location']['location_path'])
46    diff_info.set_kit_name(node_infor['kit_name'])
47    diff_info.set_sub_system(node_infor['sub_system'])
48    diff_info.set_class_name(node_infor.get('class_name'))
49    diff_info.set_unique_id(node_infor.get('unique_id'))
50
51
52def wrap_diff_info(old_info, new_info, diff_info: DiffInfo):
53    struct_union_enum = [Scene.STRUCT_DECL.value, Scene.ENUM_DECL.value, Scene.UNION_DECL.value,
54                         Scene.TYPEDEF_DECL.value]
55    if old_info is not None:
56        if 'temporary_name' in old_info['name']:
57            old_info['name'] = ''
58        set_result_common_infor(old_info, diff_info)
59        if 'NA' == old_info.get('is_system_api'):
60            diff_info.set_is_system_api(False)
61        else:
62            diff_info.set_is_system_api(True)
63        if 'content' in old_info['node_content']:
64            if old_info['kind'] in struct_union_enum:
65                api_declare = old_info['type']
66            else:
67                api_declare = old_info['node_content']['content']
68
69        else:
70            api_declare = old_info['name']
71        if old_info['kind'] != 'TRANSLATION_UNIT':
72            diff_info.set_old_api_declara(api_declare)
73        old_content = '类名:{};\nAPI声明:{};\n差异内容:{}\n'.format(diff_info.class_name, api_declare,
74                                                            diff_info.old_differ_content)
75        diff_info.set_old_api_full_text(old_content)
76
77    if new_info is not None:
78        if 'temporary_name' in new_info['name']:
79            new_info['name'] = ''
80        set_result_common_infor(new_info, diff_info)
81        if 'NA' == new_info.get('is_system_api'):
82            diff_info.set_is_system_api(False)
83        else:
84            diff_info.set_is_system_api(True)
85        if 'content' in new_info['node_content']:
86            if new_info['kind'] in struct_union_enum:
87                api_declare = new_info['type']
88            else:
89                api_declare = new_info['node_content']['content']
90        else:
91            api_declare = new_info['name']
92        if new_info['kind'] != 'TRANSLATION_UNIT':
93            diff_info.set_new_api_declara(api_declare)
94        new_content = '类名:{};\nAPI声明:{};\n差异内容:{}\n'.format(diff_info.class_name, api_declare,
95                                                            diff_info.new_differ_content)
96
97        diff_info.set_new_api_full_text(new_content)
98
99    return diff_info
100
101
102def parse_file_result(result):
103    result_map = {}
104    key = 1
105    for member in result:
106        if member["name"] == '':
107            name = 'temporary_name'
108            member["name"] = '{}{}'.format(name, key)
109            key += 1
110        result_map.setdefault(f'{member["name"]}-{member["kind"]}', member)
111    return result_map
112
113
114def get_member_result_diff(old_target, new_target):
115    old_member_result_map = parse_file_result(old_target)
116    new_member_result_map = parse_file_result(new_target)
117    merged_dict = OrderedDict(list(old_member_result_map.items()) + list(new_member_result_map.items()))
118    all_key_list = merged_dict.keys()
119    return old_member_result_map, new_member_result_map, all_key_list
120
121
122def get_initial_result_obj(diff_type: DiffType, old_differ_content, new_differ_content):
123    result_message_obj = DiffInfo(diff_type, old_differ_content, new_differ_content)
124
125    return result_message_obj
126
127
128def process_function(old, new):
129    diff_info_list = []
130    process_func_return(old, new, diff_info_list)  # 处理返回值
131    process_func_param(old, new, diff_info_list)  # 处理参数
132    return diff_info_list
133
134
135def process_func_return(old, new, diff_info_list):
136    if old['return_type'] != new['return_type']:
137        old_return_content = old['return_type']
138        new_return_content = new['return_type']
139        result_message_obj = get_initial_result_obj(DiffType.FUNCTION_RETURN_CHANGE,
140                                                    old_return_content, new_return_content)
141        diff_info = wrap_diff_info(old, new, result_message_obj)
142        diff_info_list.append(diff_info)
143
144
145def process_func_param_location(old_param_list, new_param_list, old, new):
146    result_list = []
147    old_param_str_list = get_param_name_and_type(old_param_list)
148    new_param_str_list = get_param_name_and_type(new_param_list)
149    old_param_str_content = ' '.join(old_param_str_list)
150    new_param_str_content = ' '.join(new_param_str_list)
151    if old_param_str_content == new_param_str_content:
152        return result_list
153    old_len = len(old_param_list)
154    for i, element in enumerate(old_param_str_list):
155        if element not in new_param_str_list:
156            return result_list
157        if i != new_param_str_list.index(element) and i + 1 <= old_len:
158            old_differ_content = old_param_list[i]['node_content']['content']
159            new_differ_content = new_param_list[i]['node_content']['content']
160            result_obj = wrap_diff_info(old, new, DiffInfo(DiffType.FUNCTION_PARAM_POS_CHANGE,
161                                                           old_differ_content, new_differ_content))
162            result_list.append(result_obj)
163    return result_list
164
165
166def get_param_name_and_type(param_list):
167    param_str_list = []
168    for param in param_list:
169        if 'name' in param and 'type' in param:
170            param_str = '{} {}'.format(param.get('type'), param.get('name'))
171            param_str_list.append(param_str)
172    return param_str_list
173
174
175def process_each_param(old, new, old_len, new_len, diff_info_list):
176    for i in range(max(old_len, new_len)):
177        if (i + 1) > new_len:  # 减少参数
178            old_param_content = old['parm'][i]['node_content']['content']
179            new_param_content = 'NA'
180            result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_REDUCE,
181                                                        old_param_content, new_param_content)
182            diff_info = wrap_diff_info(old, new, result_message_obj)
183            diff_info_list.append(diff_info)
184
185        elif (i + 1) > old_len:  # 增加参数
186            old_param_content = 'NA'
187            new_param_content = new['parm'][i]['node_content']['content']
188            result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_ADD,
189                                                        old_param_content, new_param_content)
190            diff_info = wrap_diff_info(old, new, result_message_obj)
191            diff_info_list.append(diff_info)
192
193        else:
194            diff_info_result = process_param_scene(old['parm'], new['parm'], i, old, new)
195            diff_info_list.extend(diff_info_result)
196
197
198def get_param_content(param_infor: list):
199    if not param_infor:
200        param_content = 'NA'
201        return param_content
202    if 1 == len(param_infor):
203        param_content = '({})'.format(param_infor[0]['node_content']['content'])
204        return param_content
205    param_content = '('
206    for element in param_infor:
207        param_content = '{},{}'.format(param_content, element['node_content']['content'])
208    param_content = '{}{}'.format(param_content, ')')
209    return param_content
210
211
212def process_func_param(old, new, diff_info_list):
213    if 'parm' in old and 'parm' in new:
214        old_len = len(old['parm'])
215        new_len = len(new['parm'])
216        result_obj_list = []
217        if old_len == new_len:
218            result_obj_list = process_func_param_location(old['parm'], new['parm'], old, new)
219            diff_info_list.extend(result_obj_list)
220        if not result_obj_list:
221            process_each_param(old, new, old_len, new_len, diff_info_list)
222
223    elif 'parm' not in old and 'parm' in new:  # 旧无新有
224        old_param_content = 'NA'
225        new_param_content = get_param_content(new['parm'])
226        if new_param_content != 'NA':
227            result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_ADD,
228                                                        old_param_content, new_param_content)
229            diff_info = wrap_diff_info(old, new, result_message_obj)
230            diff_info_list.append(diff_info)
231
232    elif 'parm' in old and 'parm' not in new:  # 旧有新无
233        old_param_content = get_param_content(old['parm'])
234        new_param_content = 'NA'
235        if old_param_content != 'NA':
236            result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_REDUCE,
237                                                        old_param_content, new_param_content)
238            diff_info = wrap_diff_info(old, new, result_message_obj)
239            diff_info_list.append(diff_info)
240
241
242def process_param_scene(old_param, new_param, index, parent_old, parent_new):
243    diff_info_list = []
244    if old_param[index]['type'] != new_param[index]['type']:
245        old_param_type_content = old_param[index]['type']
246        new_param_type_content = new_param[index]['type']
247        result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_TYPE_CHANGE,
248                                                    old_param_type_content, new_param_type_content)
249        diff_info = wrap_diff_info(parent_old, parent_new, result_message_obj)
250        diff_info_list.append(diff_info)
251
252    if old_param[index]['name'] != new_param[index]['name']:
253        old_param_name_content = old_param[index]['name']
254        new_param_name_content = new_param[index]['name']
255        result_message_obj = get_initial_result_obj(DiffType.FUNCTION_PARAM_NAME_CHANGE,
256                                                    old_param_name_content, new_param_name_content)
257        diff_info = wrap_diff_info(parent_old, parent_new, result_message_obj)
258        diff_info_list.append(diff_info)
259
260    return diff_info_list
261
262
263def process_define(old, new):
264    diff_define_list = []
265    process_define_name(old, new, diff_define_list)  # 处理宏名
266    process_define_text(old, new, diff_define_list)  # 处理宏文本
267    return diff_define_list
268
269
270def process_define_name(old, new, diff_define_list):
271    if old['name'] != new['name']:
272        old_define_name = old['name']
273        new_define_name = new['name']
274        result_message_obj = get_initial_result_obj(DiffType.DEFINE_NAME_CHANGE,
275                                                    old_define_name, new_define_name)
276        diff_info = wrap_diff_info(old, new, result_message_obj)
277        diff_define_list.append(diff_info)
278
279
280def process_define_text(old, new, diff_define_list):
281    if 'text' not in old and 'text' in new:  # 旧无新有
282        old_define_text = 'NA'
283        new_define_text = new['text']
284        result_message_obj = get_initial_result_obj(DiffType.DEFINE_TEXT_CHANGE,
285                                                    old_define_text, new_define_text)
286        diff_info = wrap_diff_info(old, new, result_message_obj)
287        diff_define_list.append(diff_info)
288    elif 'text' in old and 'text' not in new:  # 旧有新无
289        old_define_text = old['text']
290        new_define_text = 'NA'
291        result_message_obj = get_initial_result_obj(DiffType.DEFINE_TEXT_CHANGE,
292                                                    old_define_text, new_define_text)
293        diff_info = wrap_diff_info(old, new, result_message_obj)
294        diff_define_list.append(diff_info)
295    elif 'text' in old and 'text' in new:
296        if old['text'] != new['text']:
297            old_define_text = old['text']
298            new_define_text = new['text']
299            result_message_obj = get_initial_result_obj(DiffType.DEFINE_TEXT_CHANGE,
300                                                        old_define_text, new_define_text)
301            diff_info = wrap_diff_info(old, new, result_message_obj)
302            diff_define_list.append(diff_info)
303
304
305def process_struct(old, new):
306    diff_struct_list = []
307    process_struct_name(old, new, diff_struct_list)  # 处理结构体名
308    process_struct_member(old, new, diff_struct_list)  # 处理结构体成员
309    return diff_struct_list
310
311
312def process_struct_name(old, new, diff_struct_list):
313    if old['name'] != new['name']:
314        old_struct_name = old['name']
315        new_struct_name = new['name']
316        result_message_obj = get_initial_result_obj(DiffType.STRUCT_NAME_CHANGE,
317                                                    old_struct_name, new_struct_name)
318        diff_info = wrap_diff_info(old, new, result_message_obj)
319        diff_struct_list.append(diff_info)
320
321
322def get_member_content(member_infor: list):
323    if not member_infor:
324        member_content = 'NA'
325        return member_content
326    if member_infor[0]['type'] == 'FIELD_DECL':
327        end_float = ';'
328    else:
329        end_float = ','
330    if 1 == len(member_infor):
331        member_content = '{}'.format(member_infor[0]['node_content']['content'])
332        return member_content
333    member_content = ''
334    for element in member_infor:
335        member_content = '{}{}{}'.format(member_content, end_float, element['node_content']['content'])
336    return member_content
337
338
339def process_struct_member(old, new, diff_struct_list):
340    if 'members' in old and 'members' in new:  # 都有
341        old_member_result, new_member_result, all_key_result = get_member_result_diff(old['members'],
342                                                                                      new['members'])
343        for key in all_key_result:
344            if old_member_result.get(key) is None:
345                old_member_content = 'NA'
346                new_member_content = new_member_result.get(key)['node_content']['content']
347                result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_ADD,
348                                                            old_member_content, new_member_content)
349                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
350                                           result_message_obj)
351                diff_struct_list.append(diff_info)
352            elif new_member_result.get(key) is None:
353                old_member_content = old_member_result.get(key)['node_content']['content']
354                new_member_content = 'NA'
355                result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_REDUCE,
356                                                            old_member_content, new_member_content)
357                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
358                                           result_message_obj)
359                diff_struct_list.append(diff_info)
360            else:
361                process_struct_member_scene(old_member_result.get(key),
362                                            new_member_result.get(key), diff_struct_list)
363
364    elif 'members' not in old and 'members' in new:  # 旧无新有
365        old_member_content = 'NA'
366        new_member_content = get_member_content(new['members'])
367        if new_member_content != 'NA':
368            result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_ADD,
369                                                        old_member_content, new_member_content)
370            diff_info = wrap_diff_info(old, new, result_message_obj)
371            diff_struct_list.append(diff_info)
372
373    elif 'members' in old and 'members' not in new:  # 旧有新无
374        old_member_content = get_member_content(old['members'])
375        new_member_content = 'NA'
376        if old_member_content != 'NA':
377            result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_REDUCE,
378                                                        old_member_content, new_member_content)
379            diff_info = wrap_diff_info(old, new, result_message_obj)
380            diff_struct_list.append(diff_info)
381
382
383def process_struct_member_scene(old_member, new_member, diff_struct_list):
384    special_data = []  # 存储嵌套的体系
385    if (old_member['kind'] == Scene.STRUCT_DECL.value) and \
386            (new_member['kind'] == Scene.STRUCT_DECL.value):  # 结构体套结构体
387        special_data = process_struct(old_member, new_member)
388
389    elif (old_member['kind'] == Scene.UNION_DECL.value) and \
390            (new_member['kind'] == Scene.UNION_DECL.value):  # 结构体套联合体
391        special_data = process_union(old_member, new_member)
392
393    elif (old_member['kind'] == Scene.ENUM_DECL.value) and \
394            (new_member['kind'] == Scene.ENUM_DECL.value):  # 结构体套枚举
395        special_data = process_enum(old_member, new_member)
396    diff_struct_list.extend(special_data)
397
398    if (not (old_member['location']['location_path'] in old_member['type'])) and \
399            (not (new_member['location']['location_path'] in new_member['type'])):
400        if old_member['type'] != new_member['type']:
401            old_member_type = old_member['type']
402            new_member_type = new_member['type']
403            result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_TYPE_CHANGE,
404                                                        old_member_type, new_member_type)
405            diff_info = wrap_diff_info(old_member, new_member,
406                                       result_message_obj)
407            diff_struct_list.append(diff_info)
408
409    if old_member['name'] != new_member['name']:
410        old_member_name = old_member['name']
411        new_member_name = new_member['name']
412        result_message_obj = get_initial_result_obj(DiffType.STRUCT_MEMBER_NAME_CHANGE,
413                                                    old_member_name, new_member_name)
414        diff_info = wrap_diff_info(old_member, new_member,
415                                   result_message_obj)
416        diff_struct_list.append(diff_info)
417
418
419def process_union(old, new):
420    diff_union_list = []
421    process_union_name(old, new, diff_union_list)  # 处理联合体名
422    process_union_member(old, new, diff_union_list)  # 处理联合体成员
423    return diff_union_list
424
425
426def process_union_name(old, new, diff_union_list):
427    if old['name'] != new['name']:
428        old_union_name = old['name']
429        new_union_name = new['name']
430        result_message_obj = get_initial_result_obj(DiffType.UNION_NAME_CHANGE,
431                                                    old_union_name, new_union_name)
432        diff_info = wrap_diff_info(old, new, result_message_obj)
433        diff_union_list.append(diff_info)
434
435
436def process_union_member(old, new, diff_union_list):
437    if 'members' in old and 'members' in new:  # 都有
438        old_member_result, new_member_result, all_key_result = get_member_result_diff(old['members'],
439                                                                                      new['members'])
440        for key in all_key_result:
441            if old_member_result.get(key) is None:
442                old_member_content = 'NA'
443                new_member_content = new_member_result.get(key)['node_content']['content']
444                result_message_obj = get_initial_result_obj(DiffType.UNION_MEMBER_ADD,
445                                                            old_member_content, new_member_content)
446
447                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
448                                           result_message_obj)
449                diff_union_list.append(diff_info)
450            elif new_member_result.get(key) is None:
451                old_member_content = old_member_result.get(key)['node_content']['content']
452                new_member_content = 'NA'
453                result_message_obj = get_initial_result_obj(DiffType.UNION_MEMBER_REDUCE,
454                                                            old_member_content, new_member_content)
455
456                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
457                                           result_message_obj)
458                diff_union_list.append(diff_info)
459            else:
460                process_union_member_scene(old_member_result.get(key),
461                                           new_member_result.get(key), diff_union_list)
462
463    elif 'members' not in old and 'members' in new:  # 旧无新有
464        old_member_content = 'NA'
465        new_member_content = get_member_content(new['members'])
466        if new_member_content != 'NA':
467            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.UNION_MEMBER_ADD,
468                                                          old_member_content, new_member_content))
469            diff_union_list.append(diff_info)
470
471    elif 'members' in old and 'members' not in new:  # 旧有新无
472        old_member_content = get_member_content(old['members'])
473        new_member_content = 'NA'
474        if old_member_content != 'NA':
475            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.UNION_MEMBER_REDUCE,
476                                                          old_member_content, new_member_content))
477            diff_union_list.append(diff_info)
478
479
480def process_union_member_scene(old_member, new_member, diff_union_list):
481    special_data = []  # 存储嵌套的体系
482    if (old_member['kind'] == Scene.STRUCT_DECL.value) and \
483            (new_member['kind'] == Scene.STRUCT_DECL.value):  # 联合体套结构体
484        special_data = process_struct(old_member, new_member)
485
486    elif (old_member['kind'] == Scene.UNION_DECL.value) and \
487            (new_member['kind'] == Scene.UNION_DECL.value):  # 联合体套联合体
488        special_data = process_union(old_member, new_member)
489
490    elif (old_member['kind'] == Scene.ENUM_DECL.value) and \
491            (new_member['kind'] == Scene.ENUM_DECL.value):  # 联合体套枚举
492        special_data = process_enum(old_member, new_member)
493    diff_union_list.extend(special_data)
494
495    if (not (old_member['location']['location_path'] in old_member['type'])) and \
496            (not (new_member['location']['location_path'] in new_member['type'])):
497        if old_member['type'] != new_member['type']:
498            old_member_type = old_member['type']
499            new_member_type = new_member['type']
500            diff_info = wrap_diff_info(old_member, new_member, DiffInfo(DiffType.UNION_MEMBER_TYPE_CHANGE,
501                                                                        old_member_type, new_member_type))
502            diff_union_list.append(diff_info)
503
504    if old_member['name'] != new_member['name']:
505        old_member_name = old_member['name']
506        new_member_name = new_member['name']
507        diff_info = wrap_diff_info(old_member, new_member, DiffInfo(DiffType.UNION_MEMBER_NAME_CHANGE,
508                                                                    old_member_name, new_member_name))
509        diff_union_list.append(diff_info)
510
511
512def process_enum(old, new):
513    diff_enum_list = []
514    process_enum_name(old, new, diff_enum_list)  # 处理枚举名
515    process_enum_member(old, new, diff_enum_list)  # 处理枚举成员
516    return diff_enum_list
517
518
519def process_enum_name(old, new, diff_enum_list):
520    if old['name'] != new['name']:
521        old_enum_name = old['name']
522        new_enum_name = new['name']
523        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.ENUM_NAME_CHANGE, old_enum_name, new_enum_name))
524        diff_enum_list.append(diff_info)
525
526
527def process_enum_member(old, new, diff_enum_list):
528    if 'members' in old and 'members' in new:  # 都有
529        old_member_result, new_member_result, all_key_result = get_member_result_diff(old['members'],
530                                                                                      new['members'])
531        for key in all_key_result:
532            if old_member_result.get(key) is None:
533                old_member_content = 'NA'
534                new_member_content = new_member_result.get(key)['node_content']['content']
535                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
536                                           DiffInfo(DiffType.ENUM_MEMBER_ADD, old_member_content,
537                                                    new_member_content))
538                diff_enum_list.append(diff_info)
539            elif new_member_result.get(key) is None:
540                old_member_content = old_member_result.get(key)['node_content']['content']
541                new_member_content = 'NA'
542                diff_info = wrap_diff_info(old_member_result.get(key), new_member_result.get(key),
543                                           DiffInfo(DiffType.ENUM_MEMBER_REDUCE, old_member_content,
544                                                    new_member_content))
545                diff_enum_list.append(diff_info)
546            else:
547                process_enum_member_scene(old_member_result.get(key),
548                                          new_member_result.get(key), diff_enum_list)
549
550    elif 'members' not in old and 'members' in new:  # 旧无新有
551        old_member_content = 'NA'
552        new_member_content = get_member_content(new['members'])
553        if new_member_content != 'NA':
554            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.ENUM_MEMBER_ADD,
555                                                          old_member_content, new_member_content))
556            diff_enum_list.append(diff_info)
557
558    elif 'members' in old and 'members' not in new:  # 旧有新无
559        old_member_content = get_member_content(new['members'])
560        new_member_content = 'NA'
561        if old_member_content != 'NA':
562            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.ENUM_MEMBER_REDUCE,
563                                                          old_member_content, new_member_content))
564            diff_enum_list.append(diff_info)
565
566
567def process_enum_member_scene(old_member, new_member, diff_union_list):
568    if old_member['value'] != new_member['value']:
569        old_enum_value = old_member['value']
570        new_enum_value = new_member['value']
571        diff_info = wrap_diff_info(old_member, new_member,
572                                   DiffInfo(DiffType.ENUM_MEMBER_VALUE_CHANGE, old_enum_value, new_enum_value))
573        diff_union_list.append(diff_info)
574
575    if old_member['name'] != new_member['name']:
576        old_member_name = old_member['name']
577        new_member_name = new_member['name']
578        diff_info = wrap_diff_info(old_member, new_member,
579                                   DiffInfo(DiffType.ENUM_MEMBER_NAME_CHANGE, old_member_name, new_member_name))
580        diff_union_list.append(diff_info)
581
582
583def process_variable_const(old, new):
584    diff_var_or_con = []
585    if 'is_const' in old:
586        if old['is_const']:  # 处理常量
587            if 'is_const' in new and new['is_const']:
588                process_constant_type(old, new, diff_var_or_con)  # 处理常量类型
589            elif 'is_const' in new and (not new['is_const']):  # 处理常量变变量
590                process_const_change_variable(old, new, diff_var_or_con)
591            process_constant_name(old, new, diff_var_or_con)  # 处理常量名
592            process_constant_value(old, new, diff_var_or_con)  # 处理常量值
593
594        else:  # 处理变量
595            if 'is_const' in new and new['is_const']:
596                process_variable_change_const(old, new, diff_var_or_con)  # 处理变量变常量
597            elif 'is_const' in new and (not new['is_const']):
598                process_variable_type(old, new, diff_var_or_con)  # 处理变量类型
599            process_variable_name(old, new, diff_var_or_con)  # 处理变量名
600            process_variable_value(old, new, diff_var_or_con)  # 处理变量值
601
602    return diff_var_or_con
603
604
605def process_const_change_variable(old, new, diff_variable_list):
606    if 'is_const' in new and (not new['is_const']):
607        old_const_type = old['type']
608        new_const_type = new['type']
609        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_CHANGE_TO_VARIABLE,
610                                                      old_const_type, new_const_type))
611        diff_variable_list.append(diff_info)
612
613
614def process_variable_change_const(old, new, diff_variable_list):
615    if 'is_const' in new and new['is_const']:
616        old_variable_type = old['type']
617        new_variable_type = new['type']
618        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_CHANGE_TO_CONSTANT,
619                                                      old_variable_type, new_variable_type))
620        diff_variable_list.append(diff_info)
621
622
623def process_variable_name(old, new, diff_variable_list):
624    if old['name'] != new['name']:
625        old_variable_name = old['name']
626        new_variable_name = new['name']
627        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_NAME_CHANGE,
628                                                      old_variable_name, new_variable_name))
629        diff_variable_list.append(diff_info)
630
631
632def process_variable_type(old, new, diff_variable_list):
633    if old['type'] != new['type']:
634        old_variable_type = old['type']
635        new_variable_type = new['type']
636        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_TYPE_CHANGE,
637                                                      old_variable_type, new_variable_type))
638        diff_variable_list.append(diff_info)
639
640
641def process_variable_value(old, new, diff_variable_list):
642    if 'children' in old and 'children' in new:
643        if len(old['children']) and len(new['children']) \
644                and old['children'][0]['node_content']['content'] != new['children'][0]['node_content']['content']:
645            old_variable_value = old['children'][0]['node_content']['content']
646            new_variable_value = new['children'][0]['node_content']['content']
647            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_VALUE_CHANGE,
648                                                          old_variable_value, new_variable_value))
649            diff_variable_list.append(diff_info)
650
651    elif 'children' not in old and 'children' in new and len(new['children']):
652        old_variable_value = 'NA'
653        new_variable_value = new['children'][0]['node_content']['content']
654        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_VALUE_CHANGE,
655                                                      old_variable_value, new_variable_value))
656        diff_variable_list.append(diff_info)
657
658    elif 'children' in old and 'children' not in new and len(old['children']):
659        old_variable_value = old['children'][0]['node_content']['content']
660        new_variable_value = 'NA'
661        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.VARIABLE_VALUE_CHANGE,
662                                                      old_variable_value, new_variable_value))
663        diff_variable_list.append(diff_info)
664
665
666def process_constant_to_variable(old, new, diff_constant_list):
667    if not new['is_const']:
668        old_const_type = old['type']
669        new_const_type = new['type']
670        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_CHANGE_TO_VARIABLE,
671                                                      old_const_type, new_const_type))
672        diff_constant_list.append(diff_info)
673
674
675def process_constant_name(old, new, diff_constant_list):
676    if old['name'] != new['name']:
677        old_const_name = old['name']
678        new_const_name = new['name']
679        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_NAME_CHANGE, old_const_name, new_const_name))
680        diff_constant_list.append(diff_info)
681
682
683def process_constant_type(old, new, diff_constant_list):
684    if old['type'] != new['type']:
685        old_const_type = old['type']
686        new_const_type = new['type']
687        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_TYPE_CHANGE, old_const_type, new_const_type))
688        diff_constant_list.append(diff_info)
689
690
691def process_constant_value(old, new, diff_constant_list):
692    if 'children' in old and 'children' in new:
693        if len(old['children']) and len(new['children']) \
694                and old['children'][0]['node_content']['content'] != new['children'][0]['node_content']['content']:
695            old_const_value = old['children'][0]['node_content']['content']
696            new_const_value = new['children'][0]['node_content']['content']
697            diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.CONSTANT_VALUE_CHANGE,
698                                                          old_const_value, new_const_value))
699            diff_constant_list.append(diff_info)
700
701    elif 'children' not in old and 'children' in new and len(new['children']):
702        old_none = None
703        old_const_value = 'NA'
704        new_const_value = new['children'][0]['node_content']['content']
705        diff_info = wrap_diff_info(old_none, new, DiffInfo(DiffType.CONSTANT_VALUE_CHANGE,
706                                                           old_const_value, new_const_value))
707        diff_constant_list.append(diff_info)
708
709    elif 'children' in old and 'children' not in new and len(old['children']):
710        new_none = None
711        old_const_value = old['children'][0]['node_content']['content']
712        new_const_value = 'NA'
713        diff_info = wrap_diff_info(old, new_none, DiffInfo(DiffType.CONSTANT_VALUE_CHANGE, old_const_value,
714                                                           new_const_value))
715        diff_constant_list.append(diff_info)
716
717
718def process_typedef(old, new):
719    diff_typedef_list = []
720    process_typedef_name(old, new, diff_typedef_list)  # 处理命名
721
722    if 'children' in old and 'children' in new:  # 处理子节点
723        process_typedef_child(old['children'], new['children'], diff_typedef_list)
724
725    return diff_typedef_list
726
727
728def process_typedef_name(old, new, diff_typedef_list):
729    if old['name'] != new['name']:
730        old_typedef_name = old['name']
731        new_typedef_name = new['name']
732        diff_info = wrap_diff_info(old, new, DiffInfo(DiffType.TYPEDEF_NAME_TYPE_CHANGE,
733                                                      old_typedef_name, new_typedef_name))
734        diff_typedef_list.append(diff_info)
735
736
737def process_typedef_child(old_child, new_child, diff_typedef_list):
738    special_data = []  # 存储嵌套的体系
739    for i, _ in enumerate(old_child):
740        if old_child[i]['name'] == '' and new_child[i]['name'] == '':
741            if old_child[i]['kind'] == Scene.STRUCT_DECL.value and \
742                    new_child[i]['kind'] == Scene.STRUCT_DECL.value:
743                special_data = process_struct(old_child[i], new_child[i])
744
745            elif old_child[i]['kind'] == Scene.UNION_DECL.value and \
746                    new_child[i]['kind'] == Scene.UNION_DECL.value:
747                special_data = process_union(old_child[i], new_child[i])
748
749            elif old_child[i]['kind'] == Scene.ENUM_DECL.value and \
750                    new_child[i]['kind'] == Scene.ENUM_DECL.value:
751                special_data = process_enum(old_child[i], new_child[i])
752
753            diff_typedef_list.extend(special_data)
754
755
756def process_anonymous_enum_member(old_info, new_info):
757    result_obj_list = []
758    if old_info and new_info:
759        if old_info['name'] != new_info['name']:
760            change_message_obj = DiffInfo(DiffType.ENUM_MEMBER_NAME_CHANGE, old_info['name'], new_info['name'])
761            result_obj_list.append(wrap_diff_info(old_info, new_info, change_message_obj))
762        if old_info['value'] != new_info['value']:
763            change_message_obj = DiffInfo(DiffType.ENUM_MEMBER_VALUE_CHANGE, old_info['value'], new_info['value'])
764            result_obj_list.append(wrap_diff_info(old_info, new_info, change_message_obj))
765    else:
766        if old_info:
767            change_message_obj = DiffInfo(DiffType.ENUM_MEMBER_REDUCE, old_info['node_content']['content'], 'NA')
768            result_obj_list.append(wrap_diff_info(old_info, new_info, change_message_obj))
769
770        elif new_info:
771            change_message_obj = DiffInfo(DiffType.ENUM_MEMBER_ADD, 'NA', new_info['node_content']['content'])
772            result_obj_list.append(wrap_diff_info(old_info, new_info, change_message_obj))
773
774    return result_obj_list
775
776
777process_data = {
778    Scene.FUNCTION_DECL.value: process_function,
779    Scene.MACRO_DEFINITION.value: process_define,
780    Scene.STRUCT_DECL.value: process_struct,
781    Scene.UNION_DECL.value: process_union,
782    Scene.ENUM_DECL.value: process_enum,
783    Scene.VAR_DECL.value: process_variable_const,
784    Scene.TYPEDEF_DECL.value: process_typedef,
785    Scene.ENUM_CONSTANT_DECL.value: process_anonymous_enum_member,
786}
787
788
789def get_ch_api_kind(dict_key):
790    if dict_key == Scene.ENUM_CONSTANT_DECL.value:
791        key = 'ENUM_DECL'
792    else:
793        key = dict_key
794    api_kind_dict = {
795        'FUNCTION_DECL': '函数类型',
796        'MACRO_DEFINITION': '宏定义类型',
797        'STRUCT_DECL': '结构体类型',
798        'UNION_DECL': '联合体类型',
799        'ENUM_DECL': '枚举类型',
800        'VAR_DECL': '常/变量类型',
801        'TYPEDEF_DECL': '重命名类型',
802        'TRANSLATION_UNIT': 'NA'
803    }
804    return api_kind_dict.get(key)
805
806
807def collect_change_data_total(data: dict, diff_info_list):
808    for element in diff_info_list:
809        element.set_api_node_name(data['name'])
810        if (data['kind'] == Scene.STRUCT_DECL.value or data['kind'] == Scene.UNION_DECL.value
811           or data['kind'] == Scene.ENUM_DECL.value) and (not data['name']):
812            element.set_api_node_name(data['type'])
813        element.set_current_api_unique_id(data['unique_id'])
814        element.set_open_close_api(data['open_close_api'])
815        element.set_is_third_party_api(data['is_third_party_api'])
816        element.set_current_api_type(get_ch_api_kind(data['kind']))
817    change_data_total.append(diff_info_list)
818
819
820def set_is_api_change_result(result_data, key_extern):
821    for element in result_data:
822        if key_extern:
823            element.set_is_api_change(True)
824
825
826def process_add_node(add_infor, key_extern, struct_union_enum):
827    diff_info_list = []
828    old_infor = None
829    if add_infor['kind'] == Scene.TRANSLATION_UNIT.value:
830        return diff_info_list
831    if 'is_extern' in add_infor and add_infor['is_extern']:
832        key_extern = True
833    if add_infor['kind'] == Scene.ENUM_CONSTANT_DECL.value:
834        result_obj_list = process_anonymous_enum_member(old_infor, add_infor)
835        diff_info_list.extend(result_obj_list)
836    else:
837        if add_infor['kind'] in struct_union_enum:
838            new_api_content = add_infor['type']
839        else:
840            new_api_content = add_infor['node_content']['content']
841        diff_info_list.append(wrap_diff_info(old_infor, add_infor, DiffInfo(DiffType.ADD_API,
842                                                                            'NA', new_api_content)))
843    set_is_api_change_result(diff_info_list, key_extern)
844    collect_change_data_total(add_infor, diff_info_list)
845
846    return diff_info_list
847
848
849def process_reduce_node(reduce_infor, key_extern, struct_union_enum):
850    diff_info_list = []
851    new_infor = None
852    if reduce_infor['kind'] == Scene.TRANSLATION_UNIT.value:
853        return diff_info_list
854    if 'is_extern' in reduce_infor and reduce_infor['is_extern']:
855        key_extern = True
856    if reduce_infor['kind'] == Scene.ENUM_CONSTANT_DECL.value:
857        result_obj_list = process_anonymous_enum_member(reduce_infor, new_infor)
858        diff_info_list.extend(result_obj_list)
859    else:
860        if reduce_infor['kind'] in struct_union_enum:
861            old_api_content = reduce_infor['type']
862        else:
863            old_api_content = reduce_infor['node_content']['content']
864        diff_info_list.append(wrap_diff_info(reduce_infor, new_infor, DiffInfo(DiffType.REDUCE_API,
865                                                                               old_api_content, 'NA')))
866    set_is_api_change_result(diff_info_list, key_extern)
867    collect_change_data_total(reduce_infor, diff_info_list)
868
869    return diff_info_list
870
871
872def judgment_entrance(old, new, data_type=0):
873    """
874    Args:
875        old: ***
876        new: ***
877        data_type(int): 数据处理类型。1-文件新增或删除;0-其他
878    """
879    diff_info_list = []
880    struct_union_enum = [Scene.STRUCT_DECL.value, Scene.UNION_DECL.value,
881                         Scene.ENUM_DECL.value, Scene.TYPEDEF_DECL.value]
882    key_extern = False
883    if old is None and new is None:
884        return diff_info_list
885    if old is None:
886        diff_info_list.extend(process_add_node(new, key_extern, struct_union_enum))
887        return diff_info_list
888    if new is None:
889        diff_info_list.extend(process_reduce_node(old, key_extern, struct_union_enum))
890        return diff_info_list
891    kind = new['kind']
892    if 'is_extern' in old and old['is_extern']:
893        key_extern = True
894    diff_info_list.extend(process_comment_str(old, new))
895    if kind in process_data:
896        diff_info_list.extend(process_data[kind](old, new))
897    if diff_info_list:
898        set_is_api_change_result(diff_info_list, key_extern)
899        collect_change_data_total(new, diff_info_list)
900    return diff_info_list
901
902
903def process_tag_addtogroup(old_tag, new_tag, old_info, new_info):
904    diff_info_list = []
905    if old_tag is None:
906        diff_info_list.append(
907            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_ADDTOGROUP_NA_TO_HAVE,
908                                                        'NA', new_tag['name'])))
909        return diff_info_list
910    if new_tag is None:
911        diff_info_list.append(
912            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_ADDTOGROUP_HAVE_TO_NA,
913                                                        old_tag['name'], 'NA')))
914        return diff_info_list
915    if old_tag['name'] != new_tag['name']:
916        diff_info_list.append(wrap_diff_info(old_info, new_info,
917                                             DiffInfo(DiffType.DOC_TAG_ADDTOGROUP_A_TO_B, old_tag['name'],
918                                                      new_tag['name'])))
919    return diff_info_list
920
921
922def process_tag_brief(old_tag, new_tag, old_info, new_info):
923    diff_info_list = []
924    if old_tag is None:
925        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_BRIEF_NA_TO_HAVE,
926                                                                          'NA',
927                                                                          f'{new_tag["name"]} '
928                                                                          f'{new_tag["description"]}')))
929        return diff_info_list
930    if new_tag is None:
931        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_BRIEF_HAVE_TO_NA,
932                                                                          f'{old_tag["name"]} '
933                                                                          f'{old_tag["description"]}',
934                                                                          'NA')))
935        return diff_info_list
936    old_brief = f'{old_tag["name"]} {old_tag["description"]}'
937    new_brief = f'{new_tag["name"]} {new_tag["description"]}'
938    if old_brief != new_brief:
939        diff_info_list.append(
940            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_BRIEF_A_TO_B, old_brief, new_brief)))
941    return diff_info_list
942
943
944def process_tag_deprecated(old_tag, new_tag, old_info, new_info):
945    diff_info_list = []
946    if old_tag is None:
947        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_DEPRECATED_NA_TO_HAVE,
948                                                                          'NA',
949                                                                          f'{new_tag["name"]} '
950                                                                          f'{new_tag["description"]}')))
951        return diff_info_list
952    if new_tag is None:
953        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_DEPRECATED_HAVE_TO_NA,
954                                                                          f'{old_tag["name"]} '
955                                                                          f'{old_tag["description"]}',
956                                                                          'NA')))
957        return diff_info_list
958    old_deprecated = f'{old_tag["name"]} {old_tag["description"]}'
959    new_deprecated = f'{new_tag["name"]} {new_tag["description"]}'
960    if old_deprecated != new_deprecated:
961        diff_info_list.append(wrap_diff_info(old_info, new_info,
962                                             DiffInfo(DiffType.DOC_TAG_DEPRECATED_A_TO_B, old_deprecated,
963                                                      new_deprecated)))
964    return diff_info_list
965
966
967def process_tag_file(old_tag, new_tag, old_info, new_info):
968    diff_info_list = []
969    if old_tag is None:
970        diff_info_list.append(
971            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_FILE_NA_TO_HAVE, 'NA', new_tag['name'])))
972        return diff_info_list
973    if new_tag is None:
974        diff_info_list.append(
975            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_FILE_HAVE_TO_NA, old_tag['name'], 'NA')))
976        return diff_info_list
977    if old_tag['name'] != new_tag['name']:
978        diff_info_list.append(wrap_diff_info(old_info, new_info,
979                                             DiffInfo(DiffType.DOC_TAG_FILE_A_TO_B, old_tag['name'], new_tag['name'])))
980    return diff_info_list
981
982
983def process_tag_library(old_tag, new_tag, old_info, new_info):
984    diff_info_list = []
985    if old_tag is None:
986        library_result_obj = DiffInfo(DiffType.DOC_TAG_LIBRARY_NA_TO_HAVE, 'NA', new_tag['name'])
987        set_file_doc_content_snippet(old_tag, new_tag, library_result_obj)
988        diff_info_list.append(wrap_diff_info(old_info, new_info, library_result_obj))
989        return diff_info_list
990    if new_tag is None:
991        library_result_obj = DiffInfo(DiffType.DOC_TAG_LIBRARY_HAVE_TO_NA, old_tag['name'], "NA")
992        set_file_doc_content_snippet(old_tag, new_tag, library_result_obj)
993        diff_info_list.append(wrap_diff_info(old_info, new_info, library_result_obj))
994        return diff_info_list
995    if old_tag['name'] != new_tag['name']:
996        library_result_obj = DiffInfo(DiffType.DOC_TAG_LIBRARY_A_TO_B, old_tag['name'], new_tag['name'])
997        set_file_doc_content_snippet(old_tag, new_tag, library_result_obj)
998        diff_info_list.append(wrap_diff_info(old_info, new_info, library_result_obj))
999    return diff_info_list
1000
1001
1002def process_tag_param(old_tag, new_tag, old_info, new_info):
1003    diff_info_list = []
1004    if old_tag is None:
1005        diff_info_list.append(
1006            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_PARAM_NA_TO_HAVE, 'NA', new_tag['name'])))
1007        return diff_info_list
1008    if new_tag is None:
1009        diff_info_list.append(
1010            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_PARAM_HAVE_TO_NA, old_tag["name"], 'NA')))
1011        return diff_info_list
1012    if old_tag["name"] != new_tag['name']:
1013        diff_info_list.append(wrap_diff_info(old_info, new_info,
1014                                             DiffInfo(DiffType.DOC_TAG_PARAM_NAME_A_TO_B, old_tag["name"],
1015                                                      new_tag['name'])))
1016    if old_tag["description"] != new_tag['description']:
1017        diff_info_list.append(wrap_diff_info(old_info, new_info,
1018                                             DiffInfo(DiffType.DOC_TAG_PARAM_A_TO_B, old_tag["description"],
1019                                                      new_tag['description'])))
1020    return diff_info_list
1021
1022
1023def set_file_doc_content_snippet(old_tag, new_tag, diff_obj):
1024    if old_tag is not None:
1025        if old_tag.get('source'):
1026            diff_obj.set_file_doc_line(old_tag.get('source')[0].get('number'))
1027            diff_obj.set_old_api_declara(old_tag.get('source')[0].get('source'))
1028    if new_tag is not None:
1029        if new_tag.get('source'):
1030            diff_obj.set_file_doc_line(new_tag.get('source')[0].get('number'))
1031            diff_obj.set_new_api_declara(new_tag.get('source')[0].get('source'))
1032
1033
1034def process_tag_permission(old_tag, new_tag, old_info, new_info):
1035    diff_info_list = []
1036    if old_tag is None:
1037        permission_result_obj = DiffInfo(DiffType.DOC_TAG_PERMISSION_NA_TO_HAVE, 'NA', f'{new_tag["name"]} '
1038                                                                                       f'{new_tag["description"]}')
1039        set_file_doc_content_snippet(old_tag, new_tag, permission_result_obj)
1040        diff_info_list.append(wrap_diff_info(old_info, new_info, permission_result_obj))
1041        return diff_info_list
1042    if new_tag is None:
1043        permission_result_obj = DiffInfo(DiffType.DOC_TAG_PERMISSION_HAVE_TO_NA, f'{old_tag["name"]} '
1044                                                                                 f'{old_tag["description"]}', 'NA')
1045        set_file_doc_content_snippet(old_tag, new_tag, permission_result_obj)
1046        diff_info_list.append(wrap_diff_info(old_info, new_info, permission_result_obj))
1047        return diff_info_list
1048    old_permission = f'{old_tag["name"]} {old_tag["description"]}'
1049    new_permission = f'{new_tag["name"]} {new_tag["description"]}'
1050    if old_permission != new_permission:
1051        compare_value = compare_permission(old_permission, new_permission)
1052        if compare_value.state_range == RangeChange.DOWN.value:
1053            permission_result_obj = DiffInfo(DiffType.DOC_TAG_PERMISSION_RANGE_SMALLER, old_permission, new_permission)
1054            set_file_doc_content_snippet(old_tag, new_tag, permission_result_obj)
1055            diff_info_list.append(wrap_diff_info(old_info, new_info, permission_result_obj))
1056        elif compare_value.state_range == RangeChange.UP.value:
1057            permission_result_obj = DiffInfo(DiffType.DOC_TAG_PERMISSION_RANGE_BIGGER, old_permission, new_permission)
1058            set_file_doc_content_snippet(old_tag, new_tag, permission_result_obj)
1059            diff_info_list.append(wrap_diff_info(old_info, new_info, permission_result_obj))
1060        elif compare_value.state_range == RangeChange.CHANGE.value:
1061            permission_result_obj = DiffInfo(DiffType.DOC_TAG_PERMISSION_RANGE_CHANGE, old_permission, new_permission)
1062            set_file_doc_content_snippet(old_tag, new_tag, permission_result_obj)
1063            diff_info_list.append(wrap_diff_info(old_info, new_info, permission_result_obj))
1064    return diff_info_list
1065
1066
1067def process_tag_return(old_tag, new_tag, old_info, new_info):
1068    diff_info_list = []
1069    return diff_info_list
1070
1071
1072def process_tag_since(old_tag, new_tag, old_info, new_info):
1073    diff_info_list = []
1074    if old_tag is None:
1075        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_SINCE_NA_TO_HAVE,
1076                                                                          'NA',
1077                                                                          f'{new_tag["name"]} '
1078                                                                          f'{new_tag["description"]}')))
1079        return diff_info_list
1080    if new_tag is None:
1081        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_SINCE_HAVE_TO_NA,
1082                                                                          f'{old_tag["name"]} '
1083                                                                          f'{old_tag["description"]}',
1084                                                                          'NA')))
1085        return diff_info_list
1086    old_since = f'{old_tag["name"]} {old_tag["description"]}'
1087    new_since = f'{new_tag["name"]} {new_tag["description"]}'
1088    if old_since != new_since:
1089        diff_info_list.append(
1090            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_SINCE_A_TO_B, old_since, new_since)))
1091    return diff_info_list
1092
1093
1094def process_tag_syscap(old_tag, new_tag, old_info, new_info):
1095    diff_info_list = []
1096    if old_tag is None:
1097        syscap_result_obj = DiffInfo(DiffType.DOC_TAG_SYSCAP_NA_TO_HAVE, 'NA', f'{new_tag["name"]} '
1098                                                                               f'{new_tag["description"]}')
1099        set_file_doc_content_snippet(old_tag, new_tag, syscap_result_obj)
1100        diff_info_list.append(wrap_diff_info(old_info, new_info, syscap_result_obj))
1101        return diff_info_list
1102    if new_tag is None:
1103        syscap_result_obj = DiffInfo(DiffType.DOC_TAG_SYSCAP_HAVE_TO_NA, f'{old_tag["name"]} '
1104                                                                         f'{old_tag["description"]}', 'NA')
1105        set_file_doc_content_snippet(old_tag, new_tag, syscap_result_obj)
1106        diff_info_list.append(wrap_diff_info(old_info, new_info, syscap_result_obj))
1107        return diff_info_list
1108    old_syscap = f'{old_tag["name"]} {old_tag["description"]}'
1109    new_syscap = f'{new_tag["name"]} {new_tag["description"]}'
1110    if old_syscap != new_syscap:
1111        syscap_result_obj = DiffInfo(DiffType.DOC_TAG_SYSCAP_A_TO_B, old_syscap, new_syscap)
1112        set_file_doc_content_snippet(old_tag, new_tag, syscap_result_obj)
1113        diff_info_list.append(wrap_diff_info(old_info, new_info, syscap_result_obj))
1114    return diff_info_list
1115
1116
1117def process_tag_left_brace(old_tag, new_tag, old_info, new_info):
1118    diff_info_list = []
1119    if old_tag is None:
1120        diff_info_list.append(
1121            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_LEFT_BRACE_NA_TO_HAVE, 'NA', new_tag["name"])))
1122        return diff_info_list
1123    if new_tag is None:
1124        diff_info_list.append(
1125            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.DOC_TAG_LEFT_BRACE_HAVE_TO_NA, old_tag['name'], 'NA')))
1126        return diff_info_list
1127    return diff_info_list
1128
1129
1130def process_tag_right_brace(old_tag, new_tag, old_info, new_info):
1131    diff_info_list = []
1132    if old_tag is None:
1133        diff_info_list.append(wrap_diff_info(old_info, new_info,
1134                                             DiffInfo(DiffType.DOC_TAG_RIGHT_BRACE_NA_TO_HAVE, 'NA', new_tag["name"])))
1135        return diff_info_list
1136    if new_tag is None:
1137        diff_info_list.append(wrap_diff_info(old_info, new_info,
1138                                             DiffInfo(DiffType.DOC_TAG_RIGHT_BRACE_HAVE_TO_NA, old_tag['name'], 'NA')))
1139        return diff_info_list
1140    return diff_info_list
1141
1142
1143process_tag_function = {
1144    TAGS['ADD_TO_GROUP'].value: process_tag_addtogroup,
1145    TAGS['BRIEF'].value: process_tag_brief,
1146    TAGS['DEPRECATED'].value: process_tag_deprecated,
1147    TAGS['FILE'].value: process_tag_file,
1148    TAGS['LIBRARY'].value: process_tag_library,
1149    TAGS['PARAM'].value: process_tag_param,
1150    TAGS['PERMISSION'].value: process_tag_permission,
1151    TAGS['RETURN'].value: process_tag_return,
1152    TAGS['SINCE'].value: process_tag_since,
1153    TAGS['SYSCAP'].value: process_tag_syscap,
1154    TAGS['LEFT_BRACE'].value: process_tag_left_brace,
1155    TAGS['RIGHT_BRACE'].value: process_tag_right_brace,
1156}
1157
1158
1159def process_comment(comment: str):
1160    '''
1161    处理comment数据,通过node调用comment-parser解析doc注释
1162    '''
1163    result_json = []
1164    if comment == "none_comment":
1165        return result_json
1166    result = subprocess.check_output(
1167        ['node', os.path.abspath(os.path.join(current_file, "../comment_parser.js")), comment])  # 解析comment
1168    result_json: list = json.loads(result.decode('utf-8'))
1169    return result_json
1170
1171
1172def get_tag_dict_from_list(tag_list):
1173    tag_dict = dict()
1174    for tag in tag_list:
1175        if tag['tag'] in tag_dict.keys():
1176            tag_dict[tag['tag']].append(tag)
1177        else:
1178            tag_dict[tag['tag']] = [tag]
1179    return tag_dict
1180
1181
1182def process_doc(old_doc, new_doc, old_info, new_info):
1183    diff_info_list = []
1184    old_tag_list = old_doc['tags']
1185    new_tag_list = new_doc['tags']
1186    old_tag_dict = get_tag_dict_from_list(old_tag_list)
1187    new_tag_dict = get_tag_dict_from_list(new_tag_list)
1188    for item in old_tag_dict.keys() | new_tag_dict.keys():
1189        if item not in process_tag_function.keys():
1190            continue
1191        old_tag = []
1192        new_tag = []
1193        if item in old_tag_dict.keys():
1194            old_tag = old_tag_dict.get(item)
1195        if item in new_tag_dict.keys():
1196            new_tag = new_tag_dict.get(item)
1197        max_length = max(len(old_tag), len(new_tag))
1198        while len(old_tag) < max_length:
1199            old_tag += [None] * (max_length - len(old_tag))
1200        while len(new_tag) < max_length:
1201            new_tag += [None] * (max_length - len(new_tag))
1202        tag_process = process_tag_function[item]
1203        index = 0
1204        while index < max_length:
1205            diff_info_list.extend(tag_process(old_tag[index], new_tag[index], old_info, new_info))
1206            index += 1
1207
1208    return diff_info_list
1209
1210
1211def process_doc_list(old_doc_list: list, new_doc_list: list, old_info, new_info):
1212    diff_info_list = []
1213    old_length = len(old_doc_list)
1214    new_length = len(new_doc_list)
1215    index = 0
1216    while index < max(old_length, new_length):
1217        if index >= old_length != new_length:
1218            diff_info_list.append(wrap_diff_info(old_info, new_info,
1219                                                 DiffInfo(DiffType.ADD_DOC, old_doc_list[index], new_doc_list[index])))
1220            break
1221        if index >= new_length != old_length:
1222            diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.REDUCE_DOC, old_doc_list[index],
1223                                                                              new_doc_list[index])))
1224            break
1225        diff_info_list.extend(process_doc(old_doc_list[index], new_doc_list[index], old_info, new_info))
1226        index += 1
1227
1228    return diff_info_list
1229
1230
1231def get_eligible_labels_doc(doc_element):
1232    addtogroup_doc_list_right = []
1233    file_doc_list_right = []
1234    if 'tags' in doc_element:
1235        for element in doc_element['tags']:
1236            if element.get('tag') and 'addtogroup' == element.get('tag'):
1237                addtogroup_doc_list_right.append(doc_element)
1238                break
1239            elif element.get('tag') and 'file' == element.get('tag'):
1240                file_doc_list_right.append(doc_element)
1241                break
1242    return addtogroup_doc_list_right, file_doc_list_right
1243
1244
1245def get_addtogroup_and_file_doc(doc_list: list):
1246    addtogroup_doc_list = []
1247    file_doc_list = []
1248    for doc_element in doc_list:
1249        result_of_addtogroup_list, result_of_file_list = get_eligible_labels_doc(doc_element)
1250        addtogroup_doc_list.extend(result_of_addtogroup_list)
1251        file_doc_list.extend(result_of_file_list)
1252
1253    return addtogroup_doc_list, file_doc_list
1254
1255
1256def filtrate_comments(comment: str):  # 获取每个头文件的最开始注释
1257    file_comment = ''
1258    if comment:
1259        pattern = RegularExpressions.START_COMMENT.value
1260        matches = re.finditer(pattern, comment, re.DOTALL | re.MULTILINE)
1261        for mat in matches:
1262            file_comment = '{}{}\n'.format(file_comment, mat.group())
1263    return file_comment
1264
1265
1266def process_addtogroup_and_file_list(old_list, new_list, old_info, new_info, num_key):
1267    old_len = len(old_list)
1268    new_len = len(new_list)
1269    result_list = []
1270    # addtogroup tag
1271    if 1 == num_key:
1272        if old_len > new_len:
1273            old_file_comment = filtrate_comments(old_info['comment'])
1274            new_file_comment = 'NA'
1275            result_list.append(wrap_diff_info(old_info, new_info,
1276                                              DiffInfo(DiffType.DOC_TAG_ADDTOGROUP_DECREASE, old_file_comment,
1277                                                       new_file_comment)))
1278        elif old_len < new_len:
1279            old_file_comment = 'NA'
1280            new_file_comment = filtrate_comments(new_info['comment'])
1281            result_list.append(wrap_diff_info(old_info, new_info,
1282                                              DiffInfo(DiffType.DOC_TAG_ADDTOGROUP_INCREASE, old_file_comment,
1283                                                       new_file_comment)))
1284        else:
1285            result_list.extend(process_doc_list(old_list, new_list, old_info, new_info))
1286    # file tag
1287    elif 0 == num_key:
1288        if old_len > new_len:
1289            old_file_comment = filtrate_comments(old_info['comment'])
1290            new_file_comment = 'NA'
1291            result_list.append(wrap_diff_info(old_info, new_info,
1292                                              DiffInfo(DiffType.DOC_TAG_FILE_DECREASE, old_file_comment,
1293                                                       new_file_comment)))
1294        elif old_len < new_len:
1295            old_file_comment = 'NA'
1296            new_file_comment = filtrate_comments(new_info['comment'])
1297            result_list.append(wrap_diff_info(old_info, new_info,
1298                                              DiffInfo(DiffType.DOC_TAG_FILE_INCREASE, old_file_comment,
1299                                                       new_file_comment)))
1300        else:
1301            result_list.extend(process_doc_list(old_list, new_list, old_info, new_info))
1302    return result_list
1303
1304
1305def process_comment_str(old_info, new_info):
1306    diff_info_list = []
1307    if old_info['comment'] == new_info['comment']:
1308        return diff_info_list
1309    if old_info['comment'] == 'none_comment':
1310        diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.ADD_DOC, "NA", new_info['comment'])))
1311        return diff_info_list
1312    if new_info['comment'] == 'none_comment':
1313        diff_info_list.append(
1314            wrap_diff_info(old_info, new_info, DiffInfo(DiffType.REDUCE_DOC, old_info['comment'], "NA")))
1315        return diff_info_list
1316    old_doc_list = process_comment(old_info['comment'])
1317    new_doc_list = process_comment(new_info['comment'])
1318    if new_info['kind'] == CursorKind.TRANSLATION_UNIT.name:
1319        old_addtogroup_doc_list, old_file_doc_list = get_addtogroup_and_file_doc(old_doc_list)
1320        new_addtogroup_doc_list, new_file_doc_list = get_addtogroup_and_file_doc(new_doc_list)
1321        diff_info_list.extend(process_addtogroup_and_file_list(old_addtogroup_doc_list, new_addtogroup_doc_list,
1322                                                               old_info, new_info, 1))
1323        diff_info_list.extend(process_addtogroup_and_file_list(old_file_doc_list, new_file_doc_list,
1324                                                               old_info, new_info, 0))
1325    else:
1326        if len(old_doc_list) > len(new_doc_list):
1327            diff_info_list.append(wrap_diff_info(old_info, new_info, DiffInfo(DiffType.REDUCE_DOC, old_info['comment'],
1328                                                                              new_info['comment'])))
1329        elif len(old_doc_list) < len(new_doc_list):
1330            diff_info_list.append(wrap_diff_info(old_info, new_info,
1331                                                 DiffInfo(DiffType.ADD_DOC, old_info['comment'], new_info['comment'])))
1332        else:
1333            diff_info_list.extend(process_doc_list(
1334                [old_doc_list[len(old_doc_list) - 1]], [new_doc_list[len(new_doc_list) - 1]],
1335                old_info, new_info))
1336    return diff_info_list
1337