forked from OSchip/llvm-project
136 lines
4.3 KiB
Python
Executable File
136 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
#===- check_clang_tidy.py - ClangTidy Test Helper ------------*- python -*--===#
|
|
#
|
|
# The LLVM Compiler Infrastructure
|
|
#
|
|
# This file is distributed under the University of Illinois Open Source
|
|
# License. See LICENSE.TXT for details.
|
|
#
|
|
#===------------------------------------------------------------------------===#
|
|
|
|
r"""
|
|
ClangTidy Test Helper
|
|
=====================
|
|
|
|
This script runs clang-tidy in fix mode and verify fixes, messages or both.
|
|
|
|
Usage:
|
|
check_clang_tidy.py [-resource-dir <resource-dir>] \
|
|
<source-file> <check-name> <temp-file> \
|
|
-- [optional clang-tidy arguments]
|
|
|
|
Example:
|
|
// RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs
|
|
"""
|
|
|
|
import argparse
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def write_file(file_name, text):
|
|
with open(file_name, 'w') as f:
|
|
f.write(text)
|
|
f.truncate()
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-resource-dir')
|
|
parser.add_argument('input_file_name')
|
|
parser.add_argument('check_name')
|
|
parser.add_argument('temp_file_name')
|
|
|
|
args, extra_args = parser.parse_known_args()
|
|
|
|
resource_dir = args.resource_dir
|
|
input_file_name = args.input_file_name
|
|
check_name = args.check_name
|
|
temp_file_name = args.temp_file_name
|
|
|
|
extension = '.cpp'
|
|
if (input_file_name.endswith('.c')):
|
|
extension = '.c'
|
|
if (input_file_name.endswith('.hpp')):
|
|
extension = '.hpp'
|
|
temp_file_name = temp_file_name + extension
|
|
|
|
clang_tidy_extra_args = extra_args
|
|
if len(clang_tidy_extra_args) == 0:
|
|
clang_tidy_extra_args = ['--', '--std=c++11'] if extension == '.cpp' \
|
|
else ['--']
|
|
if resource_dir is not None:
|
|
clang_tidy_extra_args.append('-resource-dir=%s' % resource_dir)
|
|
|
|
with open(input_file_name, 'r') as input_file:
|
|
input_text = input_file.read()
|
|
|
|
has_check_fixes = input_text.find('CHECK-FIXES') >= 0
|
|
has_check_messages = input_text.find('CHECK-MESSAGES') >= 0
|
|
|
|
if not has_check_fixes and not has_check_messages:
|
|
sys.exit('Neither CHECK-FIXES nor CHECK-MESSAGES found in the input')
|
|
|
|
# Remove the contents of the CHECK lines to avoid CHECKs matching on
|
|
# themselves. We need to keep the comments to preserve line numbers while
|
|
# avoiding empty lines which could potentially trigger formatting-related
|
|
# checks.
|
|
cleaned_test = re.sub('// *CHECK-[A-Z-]*:[^\r\n]*', '//', input_text)
|
|
|
|
write_file(temp_file_name, cleaned_test)
|
|
|
|
original_file_name = temp_file_name + ".orig"
|
|
write_file(original_file_name, cleaned_test)
|
|
|
|
args = ['clang-tidy', temp_file_name, '-fix', '--checks=-*,' + check_name] + \
|
|
clang_tidy_extra_args
|
|
print('Running ' + repr(args) + '...')
|
|
try:
|
|
clang_tidy_output = \
|
|
subprocess.check_output(args, stderr=subprocess.STDOUT).decode()
|
|
except subprocess.CalledProcessError as e:
|
|
print('clang-tidy failed:\n' + e.output.decode())
|
|
raise
|
|
|
|
print('------------------------ clang-tidy output -----------------------\n' +
|
|
clang_tidy_output +
|
|
'\n------------------------------------------------------------------')
|
|
|
|
try:
|
|
diff_output = subprocess.check_output(
|
|
['diff', '-u', original_file_name, temp_file_name],
|
|
stderr=subprocess.STDOUT)
|
|
except subprocess.CalledProcessError as e:
|
|
diff_output = e.output
|
|
|
|
print('------------------------------ Fixes -----------------------------\n' +
|
|
diff_output.decode() +
|
|
'\n------------------------------------------------------------------')
|
|
|
|
if has_check_fixes:
|
|
try:
|
|
subprocess.check_output(
|
|
['FileCheck', '-input-file=' + temp_file_name, input_file_name,
|
|
'-check-prefix=CHECK-FIXES', '-strict-whitespace'],
|
|
stderr=subprocess.STDOUT)
|
|
except subprocess.CalledProcessError as e:
|
|
print('FileCheck failed:\n' + e.output.decode())
|
|
raise
|
|
|
|
if has_check_messages:
|
|
messages_file = temp_file_name + '.msg'
|
|
write_file(messages_file, clang_tidy_output)
|
|
try:
|
|
subprocess.check_output(
|
|
['FileCheck', '-input-file=' + messages_file, input_file_name,
|
|
'-check-prefix=CHECK-MESSAGES',
|
|
'-implicit-check-not={{warning|error}}:'],
|
|
stderr=subprocess.STDOUT)
|
|
except subprocess.CalledProcessError as e:
|
|
print('FileCheck failed:\n' + e.output.decode())
|
|
raise
|
|
|
|
if __name__ == '__main__':
|
|
main()
|