mfherbst updated this revision to Diff 107254. mfherbst added a comment. Adapt patch to the changes since the initial submission.
Most notably the introduction of clang-tidy-4.0 changed the format in which clang-tidy dumps the required changes. This needs to be taken into account when merging the suggested fixes. This patch is now adapted such that it can deal with both the old and the new format at the same time. Please review the patch once again as it differs quite a bit from the initial submission. https://reviews.llvm.org/D31326 Files: clang-tidy/tool/run-clang-tidy.py
Index: clang-tidy/tool/run-clang-tidy.py =================================================================== --- clang-tidy/tool/run-clang-tidy.py +++ clang-tidy/tool/run-clang-tidy.py @@ -36,6 +36,7 @@ from __future__ import print_function import argparse +import glob import json import multiprocessing import os @@ -47,6 +48,7 @@ import tempfile import threading import traceback +import yaml def find_compilation_database(path): @@ -89,6 +91,38 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # Clang-tidy < 4.0.0 uses "Replacements" as a key to the list + # of replacements. Clang-tidy >= 4.0.0 uses "Diagnostics" as the + # top-level key. + merged={ 'Replacements': [], 'Diagnostics': [], } + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): + content = yaml.safe_load(open(replacefile, 'r')) + if not content: + continue # Skip empty files. + for k in merged: + if content.get(k): + merged[k].extend(content[k]) + + # Remove empty lists from merged. + for k in list(merged.keys()): + if not merged[k]: + del merged[k] + + if merged: + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never used inside clang-apply-replacements, + # so we set it to '' here. + merged['MainSourceFile'] = '' + with open(mergefile, 'w') as out: + yaml.safe_dump(merged, out) + else: + # Empty the file: + open(mergefile, 'w').close() + + def check_clang_apply_replacements_binary(args): """Checks if invoking supplied clang-apply-replacements binary works.""" try: @@ -101,7 +135,7 @@ def apply_fixes(args, tmpdir): - """Calls clang-apply-fixes on a given directory. Deletes the dir when done.""" + """Calls clang-apply-fixes on a given directory.""" invocation = [args.clang_apply_replacements_binary] if args.format: invocation.append('-format') @@ -143,6 +177,9 @@ 'headers to output diagnostics from. Diagnostics from ' 'the main file of each translation unit are always ' 'displayed.') + parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes', + help='Create a yaml file to store suggested fixes in, ' + 'which can be applied with clang-apply-replacements.') parser.add_argument('-j', type=int, default=0, help='number of tidy instances to be run in parallel.') parser.add_argument('files', nargs='*', default=['.*'], @@ -194,7 +231,7 @@ max_task = multiprocessing.cpu_count() tmpdir = None - if args.fix: + if args.fix or args.export_fixes: check_clang_apply_replacements_binary(args) tmpdir = tempfile.mkdtemp() @@ -222,24 +259,32 @@ # This is a sad hack. Unfortunately subprocess goes # bonkers with ctrl-c and we start forking merrily. print('\nCtrl-C detected, goodbye.') - if args.fix: + if tmpdir: shutil.rmtree(tmpdir) os.kill(0, 9) + return_code = 0 + if args.export_fixes: + print('Writing fixes to ' + args.export_fixes + ' ...') + try: + merge_replacement_files(tmpdir, args.export_fixes) + except: + print('Error exporting fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + if args.fix: print('Applying fixes ...') - successfully_applied = False - try: apply_fixes(args, tmpdir) - successfully_applied = True except: print('Error applying fixes.\n', file=sys.stderr) traceback.print_exc() + return_code=1 + if tmpdir: shutil.rmtree(tmpdir) - if not successfully_applied: - sys.exit(1) + sys.exit(return_code) if __name__ == '__main__': main()
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits