14 Parallel clang-tidy runner
15 ==========================
17 Runs clang-tidy over all files in a compilation database. Requires clang-tidy
18 and clang-apply-replacements in $PATH.
21 - Run clang-tidy on all files in the current working directory with a default
22 set of checks and show warnings in the cpp files and all project headers.
23 run-clang-tidy.py $PWD
25 - Fix all header guards.
26 run-clang-tidy.py -fix -checks=-*,llvm-header-guard
28 - Fix all header guards included from clang-tidy and header guards
29 for clang-tidy headers.
30 run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \
31 -header-filter=extra/clang-tidy
33 Compilation database setup:
34 http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
39 import multiprocessing
51 """Adjusts the directory until a compilation database is found."""
53 while not os.path.isfile(os.path.join(result, path)):
54 if os.path.realpath(result) ==
'/':
55 print 'Error: could not find compilation database.'
58 return os.path.realpath(result)
63 """Gets a command line for clang-tidy."""
64 start = [clang_tidy_binary]
65 if header_filter
is not None:
66 start.append(
'-header-filter=' + header_filter)
69 start.append(
'-header-filter=^' + build_path +
'/.*')
71 start.append(
'-checks=' + checks)
72 if tmpdir
is not None:
73 start.append(
'-export-fixes')
76 (handle, name) = tempfile.mkstemp(suffix=
'.yaml', dir=tmpdir)
79 start.append(
'-p=' + build_path)
85 """Calls clang-apply-fixes on a given directory. Deletes the dir when done."""
86 invocation = [args.clang_apply_replacements_binary]
88 invocation.append(
'-format')
89 invocation.append(tmpdir)
90 subprocess.call(invocation)
95 """Takes filenames out of queue and runs clang-tidy on them."""
99 tmpdir, build_path, args.header_filter)
100 sys.stdout.write(
' '.
join(invocation) +
'\n')
101 subprocess.call(invocation)
106 parser = argparse.ArgumentParser(description=
'Runs clang-tidy over all files '
107 'in a compilation database. Requires '
108 'clang-tidy and clang-apply-replacements in '
110 parser.add_argument(
'-clang-tidy-binary', metavar=
'PATH',
111 default=
'clang-tidy',
112 help=
'path to clang-tidy binary')
113 parser.add_argument(
'-clang-apply-replacements-binary', metavar=
'PATH',
114 default=
'clang-apply-replacements',
115 help=
'path to clang-apply-replacements binary')
116 parser.add_argument(
'-checks', default=
None,
117 help=
'checks filter, when not specified, use clang-tidy '
119 parser.add_argument(
'-header-filter', default=
None,
120 help=
'regular expression matching the names of the '
121 'headers to output diagnostics from. Diagnostics from '
122 'the main file of each translation unit are always '
124 parser.add_argument(
'-j', type=int, default=0,
125 help=
'number of tidy instances to be run in parallel.')
126 parser.add_argument(
'files', nargs=
'*', default=[
'.*'],
127 help=
'files to be processed (regex on path)')
128 parser.add_argument(
'-fix', action=
'store_true', help=
'apply fix-its')
129 parser.add_argument(
'-format', action=
'store_true', help=
'Reformat code '
130 'after applying fixes')
131 parser.add_argument(
'-p', dest=
'build_path',
132 help=
'Path used to read a compile command database.')
133 args = parser.parse_args()
135 db_path =
'compile_commands.json'
137 if args.build_path
is not None:
138 build_path = args.build_path
144 invocation = [args.clang_tidy_binary,
'-list-checks']
145 invocation.append(
'-p=' + build_path)
147 invocation.append(
'-checks=' + args.checks)
148 invocation.append(
'-')
149 print subprocess.check_output(invocation)
151 print >>sys.stderr,
"Unable to run clang-tidy."
155 database = json.load(open(os.path.join(build_path, db_path)))
156 files = [entry[
'file']
for entry
in database]
160 max_task = multiprocessing.cpu_count()
164 tmpdir = tempfile.mkdtemp()
167 file_name_re = re.compile(
'(' +
')|('.
join(args.files) +
')')
171 queue = Queue.Queue(max_task)
172 for _
in range(max_task):
173 t = threading.Thread(target=run_tidy,
174 args=(args, tmpdir, build_path, queue))
180 if file_name_re.search(name):
186 except KeyboardInterrupt:
189 print '\nCtrl-C detected, goodbye.'
191 shutil.rmtree(tmpdir)
195 print 'Applying fixes ...'
198 if __name__ ==
'__main__':
def find_compilation_database
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)