!9900 漏标检测工具代码功能性优化

Merge pull request !9900 from 姜前进/311
This commit is contained in:
openharmony_ci 2024-03-12 12:26:04 +00:00 committed by Gitee
commit bc9ef98bf3
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 213 additions and 107 deletions

View File

@ -1,30 +0,0 @@
# missing _mark _detection
#### Description
漏标检查
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature

View File

@ -1,31 +0,0 @@
# missing _mark _detection
#### 介绍
漏标检查
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技

View File

@ -0,0 +1,32 @@
# 元服务API集标签检测工具
## 简介
对于元服务标签@atomicservice的漏标误标场景做出识别辅助API标签排查将不符合规定标签详情信息汇总至Excel表格中输出
## 目录
```
├─src #存放源码
└─test #本地运行使用文件
```
## 环境
1)python-3.11.4-amd64
2)PyCharm Community Edition 2023.2
3)需要把src目录设置为sources root(找到src目录点击右键将目标标记为里面)
4)在interface_sdk-js目录下运行的是src目录下的mian.py文件
## 运行
检测工具内置在 基础api解析工具通过命令行形式运行。具体命令格式为
```
python 检测工具main函数位置 -N 工具名称 -P 基础api解析工具结果json文件地址 -O 输Excel出地址
例如python E:\\api_label_detection\\src\\main.py -N detection -P E:\\collect_2024_02_29.json -O D:\\error.xlsx
```

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@ -13,4 +13,64 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import enum
from coreImpl import detection_label
class ToolNameType(enum.Enum):
DETECTION = 'detection'
tool_name_type_set = [
member.value for name_tool,
member in ToolNameType.__members__.items()
]
class FormatType(enum.Enum):
JSON = 'json'
EXCEL = 'excel'
format_set = [
member.value for name_format,
member in FormatType.__members__.items()
]
def run_tools(options):
tool_name = options.tool_name
if tool_name == ToolNameType["DETECTION"].value:
detection_label.detection_label(options.result_json_path, options.output_path)
class Config(object):
name = 'parser'
version = '0.1.0'
description = 'Compare the parser the NDKS'
commands = [
{
"name": "--tool-name",
"abbr": "-N",
"required": True,
"choices": tool_name_type_set,
"type": str,
"default": ToolNameType["DETECTION"],
"help": "工具名称"
},
{
"name": "--result-json-path",
"abbr": "-P",
"required": True,
"type": str,
"help": "解析结果json文件路径"
},
{
"name": "--output-path",
"abbr": "-O",
"required": False,
"type": str,
"help": "输出路径"
}
]

View File

@ -13,10 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from src.utils.util import (get_start_characters, get_remaining_characters, json_file_data, label_type_conversion,
get_check_labels, generate_excel, get_position_information, set_label_to_result)
from src.utils.constants import mutex_label_dist, contrast_function, label_name_dist
from src.typedef.detection import Output, ErrorMessage, ErrorType
from utils.util import (get_start_characters, get_remaining_characters, json_file_data, label_type_conversion,
get_check_labels, generate_excel, get_position_information,
set_label_to_result, get_js_doc_info)
from utils.constants import mutex_label_dist, contrast_function, label_name_dist, one_to_many_function
from typedef.detection import Output, ErrorMessage, ErrorType
result_list = []
@ -35,19 +37,24 @@ def judgement_dict_data(result, result_key):
dict_keys = dict_data.keys()
if 'childApis' in dict_keys: # 递归处理child
judgement_dict_data(dict_data, 'childApis')
# 命令控制是否校验成对函数漏标
if 1 == 1:
paired_function_omission_label(my_dict)
#校验成对函数漏标
paired_function_omission_label(my_dict)
def enum_label_detection(parent_enum_info: dict):
if 'jsDocInfos' not in parent_enum_info:
return
parent_js_doc_info = get_js_doc_info(parent_enum_info['jsDocInfos'])
if parent_js_doc_info is None:
return
if not parent_js_doc_info['isAtomicService']:
return
children_list = parent_enum_info['childApis']
count = 0
for child_info in children_list:
child_doc_info = get_js_doc_info(child_info['jsDocInfos'])
if child_doc_info is None:
continue
if child_doc_info['isAtomicService']:
count = count + 1
if count == 0:
@ -67,55 +74,76 @@ def paired_function_omission_label(my_dict: dict):
def is_pairing_function(defined_text, my_dict: dict):
api_type = my_dict[defined_text]['apiType']
target_api_info = my_dict[defined_text]
api_type = target_api_info['apiType']
if api_type != 'Method':
return False
start = get_start_characters(my_dict[defined_text]['apiName'])
start = get_start_characters(target_api_info['apiName'])
return start in contrast_function.keys()
def pairing(defined_text, my_dict, filter_duplicates_dist):
four_twin_list = ['off', 'on', 'emit', 'once']
function_name = my_dict[defined_text]['apiName']
start = get_start_characters(function_name)
api_name_list = []
# 4个中的其中之一
if start in four_twin_list:
dismantle_four_twin(my_dict, four_twin_list, start, function_name, api_name_list)
if start in one_to_many_function:
dismantle_one_to_many(my_dict, start, function_name, api_name_list)
else:
dismantle_ordinary(start, my_dict, function_name, api_name_list)
# 找到对应的函数
if len(api_name_list) != 0:
ff = my_dict[defined_text]
function_target_data = my_dict[defined_text]
for api_name in api_name_list:
api_info = my_dict[api_name]
handling_missing_labels(ff, api_info, filter_duplicates_dist)
handling_missing_labels(function_target_data, api_info, filter_duplicates_dist)
def dismantle_four_twin(my_dict: dict, four_twin_list, start, function_name, api_name_list):
for func in my_dict:
if get_start_characters(my_dict[func]['apiName']) in four_twin_list:
if (get_remaining_characters(get_start_characters(my_dict[func]['apiName']), my_dict[func]['apiName'])
def dismantle_one_to_many(my_dict: dict, start, function_name, api_name_list):
for defined_text in my_dict:
api_name = my_dict[defined_text]['apiName']
if get_start_characters(api_name) in one_to_many_function:
if (get_remaining_characters(get_start_characters(api_name), api_name)
== get_remaining_characters(start, function_name)):
api_name_list.append(func)
api_name_list.append(defined_text)
def dismantle_ordinary(start, my_dict: dict, function_name, api_name_list):
relative_function = contrast_function.get(start)
for api_name in my_dict:
if get_start_characters(my_dict[api_name]['apiName']) == relative_function:
if (get_remaining_characters(relative_function, my_dict[api_name]['apiName'])
for defined_text in my_dict:
api_name = my_dict[defined_text]['apiName']
if get_start_characters(api_name) == relative_function:
if (get_remaining_characters(relative_function, api_name)
== get_remaining_characters(start, function_name)):
api_name_list.append(api_name)
api_name_list.append(defined_text)
# 处理成对函数漏标问题
def handling_missing_labels(function_target_data: dict, function_relative_data: dict, filter_duplicates_dist):
target_doc_infos = function_target_data['jsDocInfos']
relative_doc_infos = function_relative_data['jsDocInfos']
target_doc_info = target_doc_infos[len(target_doc_infos) - 1]
relative_doc_info = relative_doc_infos[len(relative_doc_infos) - 1]
#目标函数与相对函数Doc信息都为空直接返回不做判断
if 'jsDocInfos' not in function_target_data and 'jsDocInfos' not in function_relative_data:
return
#目标函数Doc信息为空相对函数标记的标签全部为目标函数漏标
if 'jsDocInfos' not in function_target_data:
relative_doc_info = get_js_doc_info(function_relative_data['jsDocInfos'])
if relative_doc_info is None:
return
#判断相对函数中标记的标签
one_function_is_empty(function_relative_data, filter_duplicates_dist)
return
#相对函数Doc信息为空目标函数标记的标签全部为相对函数漏标
if 'jsDocInfos' not in function_relative_data:
relative_doc_info = get_js_doc_info(function_target_data['jsDocInfos'])
if relative_doc_info is None:
return
# 判断相对函数中标记的标签
one_function_is_empty(function_target_data, filter_duplicates_dist)
return
#目标函数和相对函数Doc信息都不为空
target_doc_info = get_js_doc_info(function_target_data['jsDocInfos'])
relative_doc_info = get_js_doc_info(function_relative_data['jsDocInfos'])
target_label_info = get_check_labels(target_doc_info)
relative_label_info = get_check_labels(relative_doc_info)
diff = target_label_info.keys() & relative_label_info
@ -129,6 +157,19 @@ def handling_missing_labels(function_target_data: dict, function_relative_data:
get_label_exclusivity_results(function_target_data, filter_duplicates_dist, val)
def one_function_is_empty(function_info: dict, filter_duplicates_dist):
doc_info = get_js_doc_info(function_info['jsDocInfos'])
if doc_info is None:
return
#判断需要校验的标签
if doc_info['isAtomicService']:
get_label_exclusivity_results(function_info, filter_duplicates_dist, 'isAtomicService')
if doc_info['isForm']:
get_label_exclusivity_results(function_info, filter_duplicates_dist, 'isForm')
if doc_info['isCrossPlatForm']:
get_label_exclusivity_results(function_info, filter_duplicates_dist, 'isCrossPlatForm')
def get_label_exclusivity_results(relative_data: dict, filter_duplicates_dist, val):
defined_text = relative_data['definedText'] + val
if defined_text not in filter_duplicates_dist:
@ -163,16 +204,9 @@ def is_label_consistent(doc_info: dict, label, mutex_label_list, api_info):
result_list.append(result)
def get_js_doc_info(js_doc_info_list: list):
if len(js_doc_info_list) > 0:
return js_doc_info_list[len(js_doc_info_list) - 1]
return None
# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
path = r'E:\python_workspace\collect_0_0.json'
data = json_file_data(path)
def detection_label(result_json_path, output_path):
data = json_file_data(result_json_path)
for key in data: # 代表每个ts文件
judgement_dict_data(data, key)
generate_excel(result_list, '')
generate_excel(result_list, output_path)

View File

@ -12,3 +12,27 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
from bin import config
def main_function():
parser = argparse.ArgumentParser(
prog=config.Config.name, description=config.Config.description)
for command in config.Config.commands:
arg_abbr = command.get("abbr")
arg_name = command.get("name")
arg_choices = command.get("choices")
arg_required = (True if command.get("required") else False)
arg_type = command.get("type")
default = command.get("default")
arg_help = command.get("help")
parser.add_argument(arg_abbr, arg_name, choices=arg_choices,
required=arg_required, type=arg_type, default=default, help=arg_help)
config.run_tools(parser.parse_args())
if __name__ == '__main__':
main_function()

View File

@ -36,9 +36,20 @@ class ErrorMessage(enum.Enum):
RELATIVE_LABEL = 'Functions that appear in pairs,[$] function missing [&] tag'
ENUM_LABEL = ('The enumeration type [$] is labeled with [&], but none of the enumeration '
'values are labeled with this label')
PARENT_HAVE_METHOD_NO = '[$] has a [&] label, but none of its methods have a [&] label'
METHOD_HAVE_PARENT_NO = '[$]does not have [&] labelbut the methods below it has [&] label'
METHOD_HAVE_INPUT_PARAM_NO = 'functions have [&] label, but the param do not have [&] label'
METHOD_HAVE_OUTPUT_PARAM_NO = 'functions have [&] label, but the return value has no [&] label'
METHOD_HAVE_OBJ_NO = 'functions have [&] label, but anonymous objects do not have [&] label'
class ErrorType(enum.Enum):
MUTEX_LABEL = 'mutex_label'
ENUM_LABEL = 'enum_value_missing_label'
RELATIVE_LABEL = 'paired_function_omission_label'
PARENT_NO_TAG = '$_missing_label'
CHILD_NO_TAG = 'method_missing_label'
PARAM_NO_TAG = 'param_missing_label'
RETURN_NO_TAG = 'return_missing_label'
OBJ_NO_TAG = 'anonymous_object_missing_label'

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python
# coding=utf-8
##############################################
# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
# -*- coding: utf-8 -*-
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@ -13,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################
mutex_label_dist = {
@ -21,6 +19,9 @@ mutex_label_dist = {
}
one_to_many_function = ['off', 'on', 'emit', 'once']
label_name_dist = {
'isAtomicService': '@atomicservice',
'deprecatedVersion': '@deprecated',

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python
# coding=utf-8
##############################################
# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
# -*- coding: utf-8 -*-
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@ -13,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################
import json
import re
@ -82,3 +80,10 @@ def get_position_information(pos: dict):
def set_label_to_result(message, label, mutex_label):
return message.replace('$', label).replace('&', mutex_label)
def get_js_doc_info(js_doc_info_list: list):
if len(js_doc_info_list) > 0:
return js_doc_info_list[len(js_doc_info_list) - 1]
return None