• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2024 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
16
17from typedef.detection import Output, ErrorMessage, ErrorType
18from utils.util import get_position_information, get_js_doc_info
19from typedef.process_three_type import get_three_label_value
20from utils.constants import label_comparison_dist
21
22
23def process_struct_type(dict_data: dict, label='default') -> list:
24    missing_tag_class_list = judgment_is_default(dict_data, label)
25    return missing_tag_class_list
26
27
28def process_class_type(dict_data: dict, label='default') -> list:
29    missing_tag_class_list = judgment_is_default(dict_data, label)
30    return missing_tag_class_list
31
32
33def process_namespace_type(dict_data: dict, label='default') -> list:
34    missing_tag_namespace_list = judgment_is_default(dict_data, label)
35    return missing_tag_namespace_list
36
37
38def process_interface_type(dict_data: dict, label='default') -> list:
39    missing_tag_interface_list = judgment_is_default(dict_data, label)
40    return missing_tag_interface_list
41
42
43def process_method_type(dict_data: dict, label='default') -> list:
44    missing_tag_method_list = judgment_is_default(dict_data, label)
45    return missing_tag_method_list
46
47
48def judgment_is_default(dict_data: dict, label) -> list:
49    result_data_total = []
50    if 'default' == label:
51        result_data_total = default_processing_label(dict_data)
52    else:
53        if 'Method' == dict_data['apiType']:
54            for label_element in label:
55                change_label = label_comparison_dist[label_element]
56                result_data = process_method_tag(dict_data, change_label)
57                result_data_total.extend(result_data)
58        else:
59            for label_element in label:
60                change_label = label_comparison_dist[label_element]
61                result_data = process_tag(dict_data, change_label)
62                result_data_total.extend(result_data)
63
64    return result_data_total
65
66
67def process_method_tag(dict_data: dict, label):
68    missing_tag_data_list = []
69    # 父没,不考虑
70    if 'jsDocInfos' not in dict_data:
71        return missing_tag_data_list
72    parent_information = get_js_doc_info(dict_data['jsDocInfos'])
73    if not parent_information:
74        return missing_tag_data_list
75    process_key = {
76        'typeLocations': 'typeLocations',
77        'objLocations': 'objLocations'
78    }
79    if 'params' in dict_data and len(dict_data['params']) > 0:
80        # 处理入参
81        result_param_list = process_func_param(dict_data, process_key, label, parent_information)
82        missing_tag_data_list.extend(result_param_list)
83        # 处理出参
84    result_return_list = process_func_anonymous_obj(dict_data, process_key, label, parent_information)
85    missing_tag_data_list.extend(result_return_list)
86
87    return missing_tag_data_list
88
89
90def process_func_param(dict_data: dict, key_info: dict, label: str, parent_info):
91    message_param_result_list = []
92    # 处理每个参数
93    for param in dict_data['params']:
94        if 'typeLocations' in param and param['typeLocations']:
95            result_param_type = process_param_or_return(dict_data, key_info['typeLocations'],
96                                                        parent_info, label, param)
97            message_param_result_list.extend(result_param_type)
98        if 'objLocations' in param and param['objLocations']:
99            result_param_obj = process_param_or_return(dict_data, key_info['objLocations'],
100                                                       parent_info, label, param)
101            message_param_result_list.extend(result_param_obj)
102
103    return message_param_result_list
104
105
106def process_func_anonymous_obj(dict_data: dict, key_info: dict, label: str, parent_info):
107    message_obj_result_list = []
108    if 'typeLocations' in dict_data and dict_data['typeLocations']:
109        result_return_type = process_param_or_return(dict_data, key_info['typeLocations'], parent_info, label)
110        message_obj_result_list.extend(result_return_type)
111    if 'objLocations' in dict_data and dict_data['objLocations']:
112        result_return_obj = process_param_or_return(dict_data, key_info['objLocations'], parent_info, label)
113        message_obj_result_list.extend(result_return_obj)
114
115    return message_obj_result_list
116
117
118def process_param_or_return(dict_data: dict, key_info: str, parent_info: dict,
119                            label, process_data=None) -> list:
120    missing_tag_message_list = []
121    new_label = label.replace('is', '')
122    error_result = {}
123    message_of_error = diff_of_param_obj(key_info).split('#')
124    if not process_data:
125        process_data = dict_data
126        message_of_error = diff_of_param_obj(key_info, in_out=1).split('#')
127    for child_info in process_data[key_info]:
128        # 父有,参or对象没
129        if label in parent_info and label in child_info and \
130                parent_info[label] and (not child_info[label]):
131            error_type = message_of_error[0]
132            error_message = message_of_error[1].replace('&', new_label)
133            error_result.setdefault('error_type', error_type)
134            error_result.setdefault('error_message', error_message)
135            error_result.setdefault('error_quote_name', child_info.get('typeName'))
136            message_obj = get_message_obj(dict_data, error_result, process_data)
137            missing_tag_message_list.append(message_obj)
138            break
139
140    return missing_tag_message_list
141
142
143def diff_of_param_obj(key, in_out=0):
144    diff_data = {
145        'typeLocations': '{}#{}'.format(ErrorType.PARAM_NO_TAG.value,
146                                        ErrorMessage.METHOD_HAVE_INPUT_PARAM_NO.value),
147        'objLocations': '{}#{}'.format(ErrorType.PARAM_OBJ_NO_TAG.value,
148                                       ErrorMessage.METHOD_HAVE_PARAM_OBJ_NO.value)
149    }
150    if 1 == in_out:
151        diff_data['typeLocations'] = '{}#{}'.format(ErrorType.RETURN_NO_TAG.value,
152                                                    ErrorMessage.METHOD_HAVE_OUTPUT_PARAM_NO.value)
153        diff_data['objLocations'] = '{}#{}'.format(ErrorType.RETURN_OBJ_NO_TAG.value,
154                                                   ErrorMessage.METHOD_HAVE_RETURN_OBJ_NO.value)
155    error_info = ''
156    if key in diff_data:
157        error_info = diff_data[key]
158
159    return error_info
160
161
162def process_tag(dict_data: dict, label):
163    missing_tag_data_list = []
164    if 'childApis' not in dict_data:
165        return missing_tag_data_list
166    # 处理property
167    for child_data in dict_data['childApis']:
168        if 'apiType' in child_data and 'Property' == child_data.get('apiType'):
169            result_list = process_child_quote_of_three(child_data, label)
170            missing_tag_data_list.extend(result_list)
171    # 节点没有jsDocInfos
172    if 'jsDocInfos' not in dict_data:
173        error_result = process_no_js_info(dict_data, label)
174    else:
175        error_result = process_js_info(dict_data, label)
176    if error_result:
177        message_obj = get_message_obj(dict_data, error_result)
178        missing_tag_data_list.append(message_obj)
179
180    return missing_tag_data_list
181
182
183def process_child_quote_of_three(child_data, label):
184    missing_tag_data_list = []
185    if 'jsDocInfos' not in child_data:
186        return missing_tag_data_list
187    child_info = get_js_doc_info(child_data['jsDocInfos'])
188    if not child_info:
189        return missing_tag_data_list
190    if 'typeLocations' in child_data and child_data['typeLocations']:
191        process_key = 'typeLocations'
192        result_list_of_type = process_reference_type_child(child_data, child_info, label, process_key)
193        missing_tag_data_list.extend(result_list_of_type)
194    if 'objLocations' in child_data and child_data['objLocations']:
195        process_key = 'objLocations'
196        result_list_of_obj = process_reference_type_child(child_data, child_info, label, process_key)
197        missing_tag_data_list.extend(result_list_of_obj)
198
199    return missing_tag_data_list
200
201
202def process_reference_type_child(child_data, current_info, label, process_key):
203    missing_tag_message_list = []
204    new_label = label.replace('is', '')
205    for refer_info in child_data[process_key]:
206        error_result = {}
207        if label in current_info and label in refer_info:
208            # property有,引用没
209            if current_info[label] and (not refer_info[label]):
210                error_result = reference_obj_or_type(process_key, new_label)
211                error_result.setdefault('error_quote_name', refer_info.get('typeName'))
212
213        if error_result:
214            message_obj = get_message_obj(child_data, error_result)
215            missing_tag_message_list.append(message_obj)
216
217    return missing_tag_message_list
218
219
220def reference_obj_or_type(process_key, new_label):
221    error_result = {}
222    error_type = ''
223    error_message = ''
224    if 'typeLocations' == process_key:
225        # property有,引用没
226        error_type = ErrorType.PROPERTY_REFERENCE_NO_TAG.value
227        error_message = ErrorMessage.PROPERTY_HAVE_REFERENCE_NO.value.replace('&', new_label)
228
229    elif 'objLocations' == process_key:
230        # property有,引用对象没
231        error_type = ErrorType.PROPERTY_REFERENCE_OBJ_NO_TAG.value
232        error_message = ErrorMessage.PROPERTY_HAVE_REFERENCE_OBJ_NO.value.replace('&', new_label)
233
234    error_result.setdefault('error_type', error_type)
235    error_result.setdefault('error_message', error_message)
236
237    return error_result
238
239
240def process_no_js_info(dict_data: dict, label):
241    error_result = {}
242    new_label = label.replace('is', '')
243    for child_data in dict_data['childApis']:
244        if 'jsDocInfos' not in child_data:
245            continue
246        data_tag_info = get_js_doc_info(child_data['jsDocInfos'])
247        if not data_tag_info:
248            continue
249        if label in data_tag_info and data_tag_info[label]:
250            error_type = ErrorType.PARENT_NO_TAG.value.replace('$', dict_data['apiType'])
251            error_message = (ErrorMessage.METHOD_HAVE_PARENT_NO.value
252                             .replace('&', new_label)
253                             .replace('$', dict_data['apiType']))
254            error_result.setdefault('error_type', error_type)
255            error_result.setdefault('error_message', error_message)
256            break
257
258    return error_result
259
260
261def process_js_info(dict_data: dict, label):
262    new_label = label.replace('is', '')
263    parent_information = get_js_doc_info(dict_data['jsDocInfos'])
264    # 对应值是空值
265    if not parent_information:
266        error_result = process_no_js_info(dict_data, label)
267        return error_result
268    len_of_dict_data = len(dict_data['childApis'])
269    count_label, error_result = judgement_js_info(dict_data, parent_information, label, new_label)
270    # 父有,子一个都没有
271    if 0 != len_of_dict_data and count_label == len_of_dict_data:
272        error_type = ErrorType.CHILD_NO_TAG.value
273        error_message = (ErrorMessage.PARENT_HAVE_METHOD_NO.value
274                         .replace('$', dict_data['apiType'])
275                         .replace('&', new_label))
276        error_result.setdefault('error_type', error_type)
277        error_result.setdefault('error_message', error_message)
278
279    return error_result
280
281
282def judgement_js_info(dict_data, parent_information, label, new_label):
283    count_label = 0
284    error_result = {}
285    for child_data in dict_data['childApis']:
286        if 'jsDocInfos' not in child_data:
287            if parent_information[label]:
288                count_label += 1
289        else:
290            child_tag_infor = get_js_doc_info(child_data['jsDocInfos'])
291            if not child_tag_infor:
292                count_label += 1
293            elif label in parent_information and label in child_tag_infor and \
294                    parent_information[label] and child_tag_infor[label]:
295                break
296            elif label in parent_information and label in child_tag_infor and \
297                    parent_information[label] and (not child_tag_infor[label]):
298                count_label += 1
299                # 父没,子有
300            elif label in parent_information and label in child_tag_infor and \
301                    (not parent_information[label]) and child_tag_infor[label]:
302                error_type = ErrorType.PARENT_NO_TAG.value.replace('$', dict_data['apiType'])
303                error_message = (ErrorMessage.METHOD_HAVE_PARENT_NO.value
304                                 .replace('$', dict_data['apiType'])
305                                 .replace('&', new_label))
306                error_result.setdefault('error_type', error_type)
307                error_result.setdefault('error_message', error_message)
308                break
309    return count_label, error_result
310
311
312def get_message_obj(dict_data: dict, error_result: dict, in_or_out=None) -> Output:
313    if not in_or_out:
314        defined_text = dict_data['definedText']
315    elif in_or_out != dict_data:
316        defined_text = in_or_out['definedText']
317    else:
318        defined_text = dict_data['definedText']
319    if 'error_quote_name' in error_result:
320        error_message = '({});{}'.format(error_result.get('error_quote_name'),
321                                         error_result['error_message'])
322    else:
323        error_message = error_result['error_message']
324    message_obj = Output(dict_data['filePath'], error_result['error_type'], defined_text,
325                         get_position_information(dict_data['pos']), error_message)
326    return message_obj
327
328
329def default_processing_label(dict_data: dict):
330    missing_tag_total_list = []
331    label_dict = get_three_label_value()
332    for label in label_dict:
333        if 'Method' == dict_data['apiType']:
334            result_data = process_method_tag(dict_data, label_dict[label])
335        else:
336            result_data = process_tag(dict_data, label_dict[label])
337        missing_tag_total_list.extend(result_data)
338
339    return missing_tag_total_list
340
341
342def process_tag_dict(dict_data: dict, label: list):
343    # 绑定特定的节点对应标签处理函数
344    process_result_list = []
345    process_special_tag = {
346        'Class': process_class_type,
347        'Namespace': process_namespace_type,
348        'Interface': process_interface_type,
349        'Method': process_method_type,
350        'Struct': process_struct_type
351    }
352    if 'apiType' in dict_data:
353        api_type = dict_data['apiType']
354        if api_type in process_special_tag:
355            process_result = process_special_tag[api_type](dict_data, label)
356            process_result_list.extend(process_result)
357
358    return process_result_list
359