forked from qt-creator/qt-creator
Clang: Use the tree instead of the list for Clang-Tidy settings
List of checks does not give enough flexibility to select/unselect specific checks. The tree fixes that. Also remove Clang-Tidy checks line edit because it is now integrated into the tree mode as an alternative way of providing checks by pressing "Plain text edit" button. 'cpptools_clangtidychecks.h' is generated using python script 'generateClangTidyChecks.py' and clang-tidy from our LLVM/Clang 6.0 build. Change-Id: I2ed1738cb2cbbf8dac6aba563469f06f69b11593 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
179
scripts/generateClangTidyChecks.py
Normal file
179
scripts/generateClangTidyChecks.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/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 <vector>
|
||||
|
||||
namespace CppTools {
|
||||
namespace Constants {
|
||||
|
||||
struct TidyNode
|
||||
{
|
||||
const std::vector<TidyNode> children;
|
||||
const char *name = nullptr;
|
||||
TidyNode(const char *name, std::vector<TidyNode> &&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 = ['android-', 'boost-', 'bugprone-', 'cert-', 'clang-analyzer-',
|
||||
'cppcoreguidelines-', 'fuchsia-', 'google-', 'hicpp-', 'llvm-', 'misc-', 'modernize-',
|
||||
'mpi-', 'objc-', 'performance-', 'readability-']
|
||||
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()
|
||||
Reference in New Issue
Block a user