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 re 17import os 18import subprocess 19import openpyxl as op 20from typedef.check.check import ApiResultInfo, ErrorType, LogType, ErrorLevel 21 22 23def check_syntax(file_path): 24 cmd_list = ['clang'] 25 if os.path.exists(r'.\sysroot'): 26 args = ['-I{}'.format(dir_path) for dir_path, _, _ in os.walk(r'.\sysroot')] 27 cmd_list.extend(args) 28 cmd_list.append('-std=c99') 29 result_list = [] 30 command = cmd_list + [file_path] 31 run_result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 32 result_list.extend(processing_data(run_result, file_path)) 33 return result_list 34 35 36def get_all_dependent_file_path(dependent_file_path): 37 link_path = [] 38 for dir_path, _, _ in os.walk(dependent_file_path): 39 if 'build-tools' not in dir_path: 40 link_path.append(dir_path) 41 42 return link_path 43 44 45def process_result_data(result_info_list): 46 syntax_info_data = [] 47 for syntax_info in result_info_list: 48 info_data = [ 49 syntax_info.api_name, 50 syntax_info.file_name, 51 syntax_info.error_info, 52 syntax_info.location_line, 53 syntax_info.error_content, 54 ] 55 syntax_info_data.append(info_data) 56 57 return syntax_info_data 58 59 60def general_syntax_excel(syntax_data_list, output_path): 61 data = process_result_data(syntax_data_list) 62 wb = op.Workbook() 63 ws = wb['Sheet'] 64 ws.title = '语法错误信息' 65 ws.append(['当前文件路径', '错误文件路径', '错误信息', '行号', '代码片段']) 66 for title in data: 67 d = title[0], title[1], title[2], title[3], title[4] 68 ws.append(d) 69 70 wb.save(output_path) 71 72 73def get_dir_file_path(file_path): 74 file_path_total = [] 75 for dir_path, _, filenames in os.walk(file_path): 76 for file_name in filenames: 77 if 'build-tools' not in dir_path and 'sysroot_myself' not in dir_path and file_name.endswith('.h'): 78 file_path_total.append(os.path.join(dir_path, file_name)) 79 80 return file_path_total 81 82 83def get_all_object_file_path(file_path): 84 file_path_total = [] 85 if os.path.isdir(file_path): 86 file_path_total = get_dir_file_path(file_path) 87 else: 88 if file_path.endswith('.h'): 89 file_path_total.append(file_path) 90 91 return file_path_total 92 93 94def check_syntax_entrance(file_path, dependent_file_path, output_path): 95 cmd_list = ['clang'] 96 link_path = get_all_dependent_file_path(dependent_file_path) 97 args = ['-I{}'.format(path) for path in link_path] 98 cmd_list.extend(args) 99 cmd_list.append('-std=c99') 100 cmd_list.append('--target=aarch64-linux-musl') 101 result_list = [] 102 all_files_list = get_all_object_file_path(file_path) 103 for element_file in all_files_list: 104 command = cmd_list + [element_file] 105 run_result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 106 result_list.extend(processing_data(run_result, element_file)) 107 general_syntax_excel(result_list, output_path) 108 return result_list 109 110 111def processing_data(run_result, current_file): 112 api_result_info_list = [] 113 for run_result_child in run_result.stderr.decode().split('^'): 114 split_error_message = run_result_child.split('\r\n') 115 error_content = ''.join(split_error_message[-2:-3:-1]) 116 result_child = run_result_child.replace('~', '') 117 ret = re.findall('\\d+:\\d+', result_child) 118 error_file_message = re.search(r'([^"]+):\d:\d:', result_child) 119 error_file_name = current_file 120 if error_file_message: 121 error_file_list = error_file_message.group(1).split('\r\n') 122 if len(error_file_list) >= 1: 123 error_file_name = os.path.normpath(error_file_list[len(error_file_list) - 1]) 124 if len(ret) != 0: 125 error_message = get_specified_string(result_child) 126 if len(error_message) == 1: 127 continue 128 position = ret[0] 129 api_result_info = ApiResultInfo(ErrorType.SYNTAX_ERRORS.value, 130 error_message[1], current_file) 131 line_column = get_line_and_column(position) 132 api_result_info.set_location_line(line_column[0]) 133 api_result_info.set_location_column(line_column[1]) 134 api_result_info.set_location(current_file) 135 api_result_info.set_type(LogType.LOG_API.value) 136 api_result_info.set_level(ErrorLevel.LOW.value) 137 api_result_info.set_file_name(error_file_name) 138 api_result_info_list.append(api_result_info) 139 api_result_info.set_error_content(error_content) 140 return api_result_info_list 141 142 143def get_line_and_column(location): 144 if location is not None: 145 return location.split(':') 146 return ['', ''] 147 148 149def get_original(result_child: str): 150 if len(result_child) == 0: 151 return result_child 152 original = result_child.lstrip().split("\r\n") 153 if len(original) == 2: 154 return '' 155 if len(original) == 3: 156 return original[1] 157 if len(original) == 4: 158 return original[2] 159 return '' 160 161 162def get_specified_string(target_string): 163 message_type = 'error' 164 function_result = [] 165 pattern = r'error: (.*?)\r\n' 166 matches = re.findall(pattern, target_string, re.DOTALL) 167 if len(matches) == 0: 168 pattern = r'warning: (.*?)\r\n' 169 matches = re.findall(pattern, target_string, re.DOTALL) 170 message_type = 'warning' 171 if len(matches) == 0: 172 pattern = r'note: (.*?)\r\n' 173 matches = re.findall(pattern, target_string, re.DOTALL) 174 message_type = 'note' 175 function_result.append(message_type) 176 for match in matches: 177 function_result.append(match) 178 if len(function_result[1]) == 0: 179 function_result.append('') 180 return function_result 181 182 183def get_file_path(file_path: str): 184 if len(file_path) == 0: 185 return file_path 186 path_split_len = len(file_path.split('\r\n')) 187 path_list = file_path.split('\r\n') 188 if path_split_len == 1: 189 return file_path 190 if path_split_len == 2: 191 return path_list[1] 192 if path_split_len == 3: 193 return path_list[2] 194 return '' 195