11cb0ef41Sopenharmony_ci#!/usr/bin/env python 21cb0ef41Sopenharmony_ci# 31cb0ef41Sopenharmony_ci# Copyright 2018 the V8 project authors. All rights reserved. 41cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 51cb0ef41Sopenharmony_ci# found in the LICENSE file. 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci# for py2/py3 compatibility 81cb0ef41Sopenharmony_cifrom __future__ import print_function 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciimport json 111cb0ef41Sopenharmony_ciimport multiprocessing 121cb0ef41Sopenharmony_ciimport optparse 131cb0ef41Sopenharmony_ciimport os 141cb0ef41Sopenharmony_ciimport re 151cb0ef41Sopenharmony_ciimport subprocess 161cb0ef41Sopenharmony_ciimport sys 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciCLANG_TIDY_WARNING = re.compile(r'(\/.*?)\ .*\[(.*)\]$') 191cb0ef41Sopenharmony_ciCLANG_TIDY_CMDLINE_OUT = re.compile(r'^clang-tidy.*\ .*|^\./\.\*') 201cb0ef41Sopenharmony_ciFILE_REGEXS = ['../src/*', '../test/*'] 211cb0ef41Sopenharmony_ciHEADER_REGEX = ['\.\.\/src\/.*|\.\.\/include\/.*|\.\.\/test\/.*'] 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ciTHREADS = multiprocessing.cpu_count() 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciclass ClangTidyWarning(object): 271cb0ef41Sopenharmony_ci """ 281cb0ef41Sopenharmony_ci Wraps up a clang-tidy warning to present aggregated information. 291cb0ef41Sopenharmony_ci """ 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci def __init__(self, warning_type): 321cb0ef41Sopenharmony_ci self.warning_type = warning_type 331cb0ef41Sopenharmony_ci self.occurrences = set() 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci def add_occurrence(self, file_path): 361cb0ef41Sopenharmony_ci self.occurrences.add(file_path.lstrip()) 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci def __hash__(self): 391cb0ef41Sopenharmony_ci return hash(self.warning_type) 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci def to_string(self, file_loc): 421cb0ef41Sopenharmony_ci s = '[%s] #%d\n' % (self.warning_type, len(self.occurrences)) 431cb0ef41Sopenharmony_ci if file_loc: 441cb0ef41Sopenharmony_ci s += ' ' + '\n '.join(self.occurrences) 451cb0ef41Sopenharmony_ci s += '\n' 461cb0ef41Sopenharmony_ci return s 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci def __str__(self): 491cb0ef41Sopenharmony_ci return self.to_string(False) 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci def __lt__(self, other): 521cb0ef41Sopenharmony_ci return len(self.occurrences) < len(other.occurrences) 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cidef GenerateCompileCommands(build_folder): 561cb0ef41Sopenharmony_ci """ 571cb0ef41Sopenharmony_ci Generate a compilation database. 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci Currently clang-tidy-4 does not understand all flags that are passed 601cb0ef41Sopenharmony_ci by the build system, therefore, we remove them from the generated file. 611cb0ef41Sopenharmony_ci """ 621cb0ef41Sopenharmony_ci ninja_ps = subprocess.Popen( 631cb0ef41Sopenharmony_ci ['ninja', '-t', 'compdb', 'cxx', 'cc'], 641cb0ef41Sopenharmony_ci stdout=subprocess.PIPE, 651cb0ef41Sopenharmony_ci cwd=build_folder) 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci out_filepath = os.path.join(build_folder, 'compile_commands.json') 681cb0ef41Sopenharmony_ci with open(out_filepath, 'w') as cc_file: 691cb0ef41Sopenharmony_ci while True: 701cb0ef41Sopenharmony_ci line = ninja_ps.stdout.readline() 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci if line == '': 731cb0ef41Sopenharmony_ci break 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci line = line.replace('-fcomplete-member-pointers', '') 761cb0ef41Sopenharmony_ci line = line.replace('-Wno-enum-compare-switch', '') 771cb0ef41Sopenharmony_ci line = line.replace('-Wno-ignored-pragma-optimize', '') 781cb0ef41Sopenharmony_ci line = line.replace('-Wno-null-pointer-arithmetic', '') 791cb0ef41Sopenharmony_ci line = line.replace('-Wno-unused-lambda-capture', '') 801cb0ef41Sopenharmony_ci line = line.replace('-Wno-defaulted-function-deleted', '') 811cb0ef41Sopenharmony_ci cc_file.write(line) 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_cidef skip_line(line): 851cb0ef41Sopenharmony_ci """ 861cb0ef41Sopenharmony_ci Check if a clang-tidy output line should be skipped. 871cb0ef41Sopenharmony_ci """ 881cb0ef41Sopenharmony_ci return bool(CLANG_TIDY_CMDLINE_OUT.search(line)) 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_cidef ClangTidyRunFull(build_folder, skip_output_filter, checks, auto_fix): 921cb0ef41Sopenharmony_ci """ 931cb0ef41Sopenharmony_ci Run clang-tidy on the full codebase and print warnings. 941cb0ef41Sopenharmony_ci """ 951cb0ef41Sopenharmony_ci extra_args = [] 961cb0ef41Sopenharmony_ci if auto_fix: 971cb0ef41Sopenharmony_ci extra_args.append('-fix') 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci if checks is not None: 1001cb0ef41Sopenharmony_ci extra_args.append('-checks') 1011cb0ef41Sopenharmony_ci extra_args.append('-*, ' + checks) 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci with open(os.devnull, 'w') as DEVNULL: 1041cb0ef41Sopenharmony_ci ct_process = subprocess.Popen( 1051cb0ef41Sopenharmony_ci ['run-clang-tidy', '-j' + str(THREADS), '-p', '.'] 1061cb0ef41Sopenharmony_ci + ['-header-filter'] + HEADER_REGEX + extra_args 1071cb0ef41Sopenharmony_ci + FILE_REGEXS, 1081cb0ef41Sopenharmony_ci cwd=build_folder, 1091cb0ef41Sopenharmony_ci stdout=subprocess.PIPE, 1101cb0ef41Sopenharmony_ci stderr=DEVNULL) 1111cb0ef41Sopenharmony_ci removing_check_header = False 1121cb0ef41Sopenharmony_ci empty_lines = 0 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci while True: 1151cb0ef41Sopenharmony_ci line = ct_process.stdout.readline() 1161cb0ef41Sopenharmony_ci if line == '': 1171cb0ef41Sopenharmony_ci break 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci # Skip all lines after Enbale checks and before two newlines, 1201cb0ef41Sopenharmony_ci # i.e., skip clang-tidy check list. 1211cb0ef41Sopenharmony_ci if line.startswith('Enabled checks'): 1221cb0ef41Sopenharmony_ci removing_check_header = True 1231cb0ef41Sopenharmony_ci if removing_check_header and not skip_output_filter: 1241cb0ef41Sopenharmony_ci if line == '\n': 1251cb0ef41Sopenharmony_ci empty_lines += 1 1261cb0ef41Sopenharmony_ci if empty_lines == 2: 1271cb0ef41Sopenharmony_ci removing_check_header = False 1281cb0ef41Sopenharmony_ci continue 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci # Different lines get removed to ease output reading. 1311cb0ef41Sopenharmony_ci if not skip_output_filter and skip_line(line): 1321cb0ef41Sopenharmony_ci continue 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci # Print line, because no filter was matched. 1351cb0ef41Sopenharmony_ci if line != '\n': 1361cb0ef41Sopenharmony_ci sys.stdout.write(line) 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_cidef ClangTidyRunAggregate(build_folder, print_files): 1401cb0ef41Sopenharmony_ci """ 1411cb0ef41Sopenharmony_ci Run clang-tidy on the full codebase and aggregate warnings into categories. 1421cb0ef41Sopenharmony_ci """ 1431cb0ef41Sopenharmony_ci with open(os.devnull, 'w') as DEVNULL: 1441cb0ef41Sopenharmony_ci ct_process = subprocess.Popen( 1451cb0ef41Sopenharmony_ci ['run-clang-tidy', '-j' + str(THREADS), '-p', '.'] + 1461cb0ef41Sopenharmony_ci ['-header-filter'] + HEADER_REGEX + 1471cb0ef41Sopenharmony_ci FILE_REGEXS, 1481cb0ef41Sopenharmony_ci cwd=build_folder, 1491cb0ef41Sopenharmony_ci stdout=subprocess.PIPE, 1501cb0ef41Sopenharmony_ci stderr=DEVNULL) 1511cb0ef41Sopenharmony_ci warnings = dict() 1521cb0ef41Sopenharmony_ci while True: 1531cb0ef41Sopenharmony_ci line = ct_process.stdout.readline() 1541cb0ef41Sopenharmony_ci if line == '': 1551cb0ef41Sopenharmony_ci break 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci res = CLANG_TIDY_WARNING.search(line) 1581cb0ef41Sopenharmony_ci if res is not None: 1591cb0ef41Sopenharmony_ci warnings.setdefault( 1601cb0ef41Sopenharmony_ci res.group(2), 1611cb0ef41Sopenharmony_ci ClangTidyWarning(res.group(2))).add_occurrence(res.group(1)) 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci for warning in sorted(warnings.values(), reverse=True): 1641cb0ef41Sopenharmony_ci sys.stdout.write(warning.to_string(print_files)) 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_cidef ClangTidyRunDiff(build_folder, diff_branch, auto_fix): 1681cb0ef41Sopenharmony_ci """ 1691cb0ef41Sopenharmony_ci Run clang-tidy on the diff between current and the diff_branch. 1701cb0ef41Sopenharmony_ci """ 1711cb0ef41Sopenharmony_ci if diff_branch is None: 1721cb0ef41Sopenharmony_ci diff_branch = subprocess.check_output(['git', 'merge-base', 1731cb0ef41Sopenharmony_ci 'HEAD', 'origin/master']).strip() 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci git_ps = subprocess.Popen( 1761cb0ef41Sopenharmony_ci ['git', 'diff', '-U0', diff_branch], stdout=subprocess.PIPE) 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci extra_args = [] 1791cb0ef41Sopenharmony_ci if auto_fix: 1801cb0ef41Sopenharmony_ci extra_args.append('-fix') 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci with open(os.devnull, 'w') as DEVNULL: 1831cb0ef41Sopenharmony_ci """ 1841cb0ef41Sopenharmony_ci The script `clang-tidy-diff` does not provide support to add header- 1851cb0ef41Sopenharmony_ci filters. To still analyze headers we use the build path option `-path` to 1861cb0ef41Sopenharmony_ci inject our header-filter option. This works because the script just adds 1871cb0ef41Sopenharmony_ci the passed path string to the commandline of clang-tidy. 1881cb0ef41Sopenharmony_ci """ 1891cb0ef41Sopenharmony_ci modified_build_folder = build_folder 1901cb0ef41Sopenharmony_ci modified_build_folder += ' -header-filter=' 1911cb0ef41Sopenharmony_ci modified_build_folder += '\'' + ''.join(HEADER_REGEX) + '\'' 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci ct_ps = subprocess.Popen( 1941cb0ef41Sopenharmony_ci ['clang-tidy-diff.py', '-path', modified_build_folder, '-p1'] + 1951cb0ef41Sopenharmony_ci extra_args, 1961cb0ef41Sopenharmony_ci stdin=git_ps.stdout, 1971cb0ef41Sopenharmony_ci stdout=subprocess.PIPE, 1981cb0ef41Sopenharmony_ci stderr=DEVNULL) 1991cb0ef41Sopenharmony_ci git_ps.wait() 2001cb0ef41Sopenharmony_ci while True: 2011cb0ef41Sopenharmony_ci line = ct_ps.stdout.readline() 2021cb0ef41Sopenharmony_ci if line == '': 2031cb0ef41Sopenharmony_ci break 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci if skip_line(line): 2061cb0ef41Sopenharmony_ci continue 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci sys.stdout.write(line) 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_cidef rm_prefix(string, prefix): 2121cb0ef41Sopenharmony_ci """ 2131cb0ef41Sopenharmony_ci Removes prefix from a string until the new string 2141cb0ef41Sopenharmony_ci no longer starts with the prefix. 2151cb0ef41Sopenharmony_ci """ 2161cb0ef41Sopenharmony_ci while string.startswith(prefix): 2171cb0ef41Sopenharmony_ci string = string[len(prefix):] 2181cb0ef41Sopenharmony_ci return string 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_cidef ClangTidyRunSingleFile(build_folder, filename_to_check, auto_fix, 2221cb0ef41Sopenharmony_ci line_ranges=[]): 2231cb0ef41Sopenharmony_ci """ 2241cb0ef41Sopenharmony_ci Run clang-tidy on a single file. 2251cb0ef41Sopenharmony_ci """ 2261cb0ef41Sopenharmony_ci files_with_relative_path = [] 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci compdb_filepath = os.path.join(build_folder, 'compile_commands.json') 2291cb0ef41Sopenharmony_ci with open(compdb_filepath) as raw_json_file: 2301cb0ef41Sopenharmony_ci compdb = json.load(raw_json_file) 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci for db_entry in compdb: 2331cb0ef41Sopenharmony_ci if db_entry['file'].endswith(filename_to_check): 2341cb0ef41Sopenharmony_ci files_with_relative_path.append(db_entry['file']) 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci with open(os.devnull, 'w') as DEVNULL: 2371cb0ef41Sopenharmony_ci for file_with_relative_path in files_with_relative_path: 2381cb0ef41Sopenharmony_ci line_filter = None 2391cb0ef41Sopenharmony_ci if len(line_ranges) != 0: 2401cb0ef41Sopenharmony_ci line_filter = '[' 2411cb0ef41Sopenharmony_ci line_filter += '{ \"lines\":[' + ', '.join(line_ranges) 2421cb0ef41Sopenharmony_ci line_filter += '], \"name\":\"' 2431cb0ef41Sopenharmony_ci line_filter += rm_prefix(file_with_relative_path, 2441cb0ef41Sopenharmony_ci '../') + '\"}' 2451cb0ef41Sopenharmony_ci line_filter += ']' 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci extra_args = ['-line-filter=' + line_filter] if line_filter else [] 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci if auto_fix: 2501cb0ef41Sopenharmony_ci extra_args.append('-fix') 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci subprocess.call(['clang-tidy', '-p', '.'] + 2531cb0ef41Sopenharmony_ci extra_args + 2541cb0ef41Sopenharmony_ci [file_with_relative_path], 2551cb0ef41Sopenharmony_ci cwd=build_folder, 2561cb0ef41Sopenharmony_ci stderr=DEVNULL) 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_cidef CheckClangTidy(): 2601cb0ef41Sopenharmony_ci """ 2611cb0ef41Sopenharmony_ci Checks if a clang-tidy binary exists. 2621cb0ef41Sopenharmony_ci """ 2631cb0ef41Sopenharmony_ci with open(os.devnull, 'w') as DEVNULL: 2641cb0ef41Sopenharmony_ci return subprocess.call(['which', 'clang-tidy'], stdout=DEVNULL) == 0 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_cidef CheckCompDB(build_folder): 2681cb0ef41Sopenharmony_ci """ 2691cb0ef41Sopenharmony_ci Checks if a compilation database exists in the build_folder. 2701cb0ef41Sopenharmony_ci """ 2711cb0ef41Sopenharmony_ci return os.path.isfile(os.path.join(build_folder, 'compile_commands.json')) 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_cidef DetectBuildFolder(): 2751cb0ef41Sopenharmony_ci """ 2761cb0ef41Sopenharmony_ci Tries to auto detect the last used build folder in out/ 2771cb0ef41Sopenharmony_ci """ 2781cb0ef41Sopenharmony_ci outdirs_folder = 'out/' 2791cb0ef41Sopenharmony_ci last_used = None 2801cb0ef41Sopenharmony_ci last_timestamp = -1 2811cb0ef41Sopenharmony_ci for outdir in [outdirs_folder + folder_name 2821cb0ef41Sopenharmony_ci for folder_name in os.listdir(outdirs_folder) 2831cb0ef41Sopenharmony_ci if os.path.isdir(outdirs_folder + folder_name)]: 2841cb0ef41Sopenharmony_ci outdir_modified_timestamp = os.path.getmtime(outdir) 2851cb0ef41Sopenharmony_ci if outdir_modified_timestamp > last_timestamp: 2861cb0ef41Sopenharmony_ci last_timestamp = outdir_modified_timestamp 2871cb0ef41Sopenharmony_ci last_used = outdir 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci return last_used 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_cidef GetOptions(): 2931cb0ef41Sopenharmony_ci """ 2941cb0ef41Sopenharmony_ci Generate the option parser for this script. 2951cb0ef41Sopenharmony_ci """ 2961cb0ef41Sopenharmony_ci result = optparse.OptionParser() 2971cb0ef41Sopenharmony_ci result.add_option( 2981cb0ef41Sopenharmony_ci '-b', 2991cb0ef41Sopenharmony_ci '--build-folder', 3001cb0ef41Sopenharmony_ci help='Set V8 build folder', 3011cb0ef41Sopenharmony_ci dest='build_folder', 3021cb0ef41Sopenharmony_ci default=None) 3031cb0ef41Sopenharmony_ci result.add_option( 3041cb0ef41Sopenharmony_ci '-j', 3051cb0ef41Sopenharmony_ci help='Set the amount of threads that should be used', 3061cb0ef41Sopenharmony_ci dest='threads', 3071cb0ef41Sopenharmony_ci default=None) 3081cb0ef41Sopenharmony_ci result.add_option( 3091cb0ef41Sopenharmony_ci '--gen-compdb', 3101cb0ef41Sopenharmony_ci help='Generate a compilation database for clang-tidy', 3111cb0ef41Sopenharmony_ci default=False, 3121cb0ef41Sopenharmony_ci action='store_true') 3131cb0ef41Sopenharmony_ci result.add_option( 3141cb0ef41Sopenharmony_ci '--no-output-filter', 3151cb0ef41Sopenharmony_ci help='Done use any output filterning', 3161cb0ef41Sopenharmony_ci default=False, 3171cb0ef41Sopenharmony_ci action='store_true') 3181cb0ef41Sopenharmony_ci result.add_option( 3191cb0ef41Sopenharmony_ci '--fix', 3201cb0ef41Sopenharmony_ci help='Fix auto fixable issues', 3211cb0ef41Sopenharmony_ci default=False, 3221cb0ef41Sopenharmony_ci dest='auto_fix', 3231cb0ef41Sopenharmony_ci action='store_true' 3241cb0ef41Sopenharmony_ci ) 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci # Full clang-tidy. 3271cb0ef41Sopenharmony_ci full_run_g = optparse.OptionGroup(result, 'Clang-tidy full', '') 3281cb0ef41Sopenharmony_ci full_run_g.add_option( 3291cb0ef41Sopenharmony_ci '--full', 3301cb0ef41Sopenharmony_ci help='Run clang-tidy on the whole codebase', 3311cb0ef41Sopenharmony_ci default=False, 3321cb0ef41Sopenharmony_ci action='store_true') 3331cb0ef41Sopenharmony_ci full_run_g.add_option('--checks', 3341cb0ef41Sopenharmony_ci help='Clang-tidy checks to use.', 3351cb0ef41Sopenharmony_ci default=None) 3361cb0ef41Sopenharmony_ci result.add_option_group(full_run_g) 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci # Aggregate clang-tidy. 3391cb0ef41Sopenharmony_ci agg_run_g = optparse.OptionGroup(result, 'Clang-tidy aggregate', '') 3401cb0ef41Sopenharmony_ci agg_run_g.add_option('--aggregate', help='Run clang-tidy on the whole '\ 3411cb0ef41Sopenharmony_ci 'codebase and aggregate the warnings', 3421cb0ef41Sopenharmony_ci default=False, action='store_true') 3431cb0ef41Sopenharmony_ci agg_run_g.add_option('--show-loc', help='Show file locations when running '\ 3441cb0ef41Sopenharmony_ci 'in aggregate mode', default=False, 3451cb0ef41Sopenharmony_ci action='store_true') 3461cb0ef41Sopenharmony_ci result.add_option_group(agg_run_g) 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci # Diff clang-tidy. 3491cb0ef41Sopenharmony_ci diff_run_g = optparse.OptionGroup(result, 'Clang-tidy diff', '') 3501cb0ef41Sopenharmony_ci diff_run_g.add_option('--branch', help='Run clang-tidy on the diff '\ 3511cb0ef41Sopenharmony_ci 'between HEAD and the merge-base between HEAD '\ 3521cb0ef41Sopenharmony_ci 'and DIFF_BRANCH (origin/master by default).', 3531cb0ef41Sopenharmony_ci default=None, dest='diff_branch') 3541cb0ef41Sopenharmony_ci result.add_option_group(diff_run_g) 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci # Single clang-tidy. 3571cb0ef41Sopenharmony_ci single_run_g = optparse.OptionGroup(result, 'Clang-tidy single', '') 3581cb0ef41Sopenharmony_ci single_run_g.add_option( 3591cb0ef41Sopenharmony_ci '--single', help='', default=False, action='store_true') 3601cb0ef41Sopenharmony_ci single_run_g.add_option( 3611cb0ef41Sopenharmony_ci '--file', help='File name to check', default=None, dest='file_name') 3621cb0ef41Sopenharmony_ci single_run_g.add_option('--lines', help='Limit checks to a line range. '\ 3631cb0ef41Sopenharmony_ci 'For example: --lines="[2,4], [5,6]"', 3641cb0ef41Sopenharmony_ci default=[], dest='line_ranges') 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci result.add_option_group(single_run_g) 3671cb0ef41Sopenharmony_ci return result 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_cidef main(): 3711cb0ef41Sopenharmony_ci parser = GetOptions() 3721cb0ef41Sopenharmony_ci (options, _) = parser.parse_args() 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci if options.threads is not None: 3751cb0ef41Sopenharmony_ci global THREADS 3761cb0ef41Sopenharmony_ci THREADS = options.threads 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci if options.build_folder is None: 3791cb0ef41Sopenharmony_ci options.build_folder = DetectBuildFolder() 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci if not CheckClangTidy(): 3821cb0ef41Sopenharmony_ci print('Could not find clang-tidy') 3831cb0ef41Sopenharmony_ci elif options.build_folder is None or not os.path.isdir(options.build_folder): 3841cb0ef41Sopenharmony_ci print('Please provide a build folder with -b') 3851cb0ef41Sopenharmony_ci elif options.gen_compdb: 3861cb0ef41Sopenharmony_ci GenerateCompileCommands(options.build_folder) 3871cb0ef41Sopenharmony_ci elif not CheckCompDB(options.build_folder): 3881cb0ef41Sopenharmony_ci print('Could not find compilation database, ' \ 3891cb0ef41Sopenharmony_ci 'please generate it with --gen-compdb') 3901cb0ef41Sopenharmony_ci else: 3911cb0ef41Sopenharmony_ci print('Using build folder:', options.build_folder) 3921cb0ef41Sopenharmony_ci if options.full: 3931cb0ef41Sopenharmony_ci print('Running clang-tidy - full') 3941cb0ef41Sopenharmony_ci ClangTidyRunFull(options.build_folder, 3951cb0ef41Sopenharmony_ci options.no_output_filter, 3961cb0ef41Sopenharmony_ci options.checks, 3971cb0ef41Sopenharmony_ci options.auto_fix) 3981cb0ef41Sopenharmony_ci elif options.aggregate: 3991cb0ef41Sopenharmony_ci print('Running clang-tidy - aggregating warnings') 4001cb0ef41Sopenharmony_ci if options.auto_fix: 4011cb0ef41Sopenharmony_ci print('Auto fix not working in aggregate mode, running without.') 4021cb0ef41Sopenharmony_ci ClangTidyRunAggregate(options.build_folder, options.show_loc) 4031cb0ef41Sopenharmony_ci elif options.single: 4041cb0ef41Sopenharmony_ci print('Running clang-tidy - single on ' + options.file_name) 4051cb0ef41Sopenharmony_ci if options.file_name is not None: 4061cb0ef41Sopenharmony_ci line_ranges = [] 4071cb0ef41Sopenharmony_ci for match in re.findall(r'(\[.*?\])', options.line_ranges): 4081cb0ef41Sopenharmony_ci if match is not []: 4091cb0ef41Sopenharmony_ci line_ranges.append(match) 4101cb0ef41Sopenharmony_ci ClangTidyRunSingleFile(options.build_folder, 4111cb0ef41Sopenharmony_ci options.file_name, 4121cb0ef41Sopenharmony_ci options.auto_fix, 4131cb0ef41Sopenharmony_ci line_ranges) 4141cb0ef41Sopenharmony_ci else: 4151cb0ef41Sopenharmony_ci print('Filename provided, please specify a filename with --file') 4161cb0ef41Sopenharmony_ci else: 4171cb0ef41Sopenharmony_ci print('Running clang-tidy') 4181cb0ef41Sopenharmony_ci ClangTidyRunDiff(options.build_folder, 4191cb0ef41Sopenharmony_ci options.diff_branch, 4201cb0ef41Sopenharmony_ci options.auto_fix) 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ciif __name__ == '__main__': 4241cb0ef41Sopenharmony_ci main() 425