#!/usr/bin/env python ############################################################################ # # Copyright (C) 2018 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. # # Commercial License Usage # Licensees holding valid commercial Qt licenses may use this file in # accordance with the commercial license agreement provided with the # Software or, alternatively, in accordance with the terms contained in # a written agreement between you and The Qt Company. For licensing terms # and conditions see https://www.qt.io/terms-conditions. For further # information use the contact form at https://www.qt.io/contact-us. # # GNU General Public License Usage # Alternatively, this file may be used under the terms of the GNU # General Public License version 3 as published by the Free Software # Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT # included in the packaging of this file. Please review the following # information to ensure the GNU General Public License requirements will # be met: https://www.gnu.org/licenses/gpl-3.0.html. # ############################################################################ import argparse import collections import os import re import subprocess import sys import common def next_common(string, common): remaining_string = string[len(common):] parts = re.split("[.\-]+", remaining_string) return string[:(len(common) + len(parts[0]) + 1)] def extract_similar(group, group_common): subgroups = {} for key, val in group.items(): common = next_common(key, group_common) if common == group_common or common == key: continue if key not in group: continue subgroup = {} for subkey, subval in group.items(): if not subkey.startswith(common): continue subgroup[subkey] = subval del group[subkey] if len(subgroup) == 1: group[key] = val else: extract_similar(subgroup, common) subgroups[common] = subgroup group.update(subgroups) if '' in group: del group[''] return group def print_formatted(group, group_name, indent): index = 0 for key in sorted(group): index += 1 comma = ',' if index == len(group): comma = '' if len(group[key]) == 0: print indent + '"' + key[len(group_name):] + '"' + comma else: print indent + '{' print indent + ' "' + key[len(group_name):] + '",' print indent + ' {' print_formatted(group[key], key, indent + ' ') print indent + ' }' print indent + '}' + comma def print_to_header_file(group): print '''/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #pragma once #include namespace CppTools { namespace Constants { struct TidyNode { const std::vector children; const char *name = nullptr; TidyNode(const char *name, std::vector &&children) : children(std::move(children)) , name(name) {} TidyNode(const char *name) : name(name) {} }; // CLANG-UPGRADE-CHECK: Run 'scripts/generateClangTidyChecks.py' after Clang upgrade to // update this header. static const TidyNode CLANG_TIDY_CHECKS_ROOT { "", {''' print_formatted(group, '', ' ') print ''' } }; } // namespace Constants } // namespace CppTools''' def parse_arguments(): parser = argparse.ArgumentParser(description="Clang-Tidy checks header file generator") parser.add_argument('--tidy-path', help='path to clang-tidy binary', default='clang-tidy.exe' if common.is_windows_platform() else 'clang-tidy', dest='tidypath') return parser.parse_args() def main(): arguments = parse_arguments() process = subprocess.Popen([arguments.tidypath, '-checks=*', '-list-checks'], stdout=subprocess.PIPE) lines = process.stdout.read().splitlines() lines.pop(0) # 'Enabled checks:' major_checks = ['abseil-', 'android-', 'boost-', 'bugprone-', 'cert-', 'clang-analyzer-', 'cppcoreguidelines-', 'fuchsia-', 'google-', 'hicpp-', 'llvm-', 'misc-', 'modernize-', 'mpi-', 'objc-', 'performance-', 'portability-', 'readability-', 'zircon-'] current_major = 0 major_groups = {} for line in lines: line = line.strip() if current_major < (len(major_checks) - 1) and line.startswith(major_checks[current_major + 1]): current_major += 1 if major_checks[current_major] not in major_groups: major_groups[major_checks[current_major]] = {} major_groups[major_checks[current_major]][line] = {} for major_check, group in major_groups.items(): major_groups[major_check] = extract_similar(group, major_check) current_path = os.path.dirname(os.path.abspath(__file__)) header_path = os.path.abspath(os.path.join(current_path, '..', 'src', 'plugins', 'cpptools', 'cpptools_clangtidychecks.h')) default_stdout = sys.stdout header_file = open(header_path, 'w') sys.stdout = header_file print_to_header_file(major_groups) sys.stdout = default_stdout header_file.close() if __name__ == "__main__": main()