Index: run-clang-tidy.py =================================================================== --- run-clang-tidy.py +++ run-clang-tidy.py @@ -45,6 +45,8 @@ import sys import tempfile import threading +import yaml +import glob def find_compilation_database(path): @@ -87,14 +89,37 @@ return start +def merge_replacement_files(tmpdir, fixfile): + """Merge all replacement files in a directory into a single fixfile""" + merged={ 'MainSourceFile': None, 'Replacements': [] } + + for replacefile in glob.iglob(tmpdir + '/*.yaml'): + with open(replacefile, 'r') as f: + content = yaml.safe_load(f) + if not content: continue # Skip empty files + + try: + if not merged['MainSourceFile']: + merged['MainSourceFile'] = content['MainSourceFile'] + elif merged['MainSourceFile'] != content['MainSourceFile']: + # The values given for MainSourceFile are inconsistent. + # Just empty MainSourceFile blank: + merged['MainSourceFile']='' + merged['Replacements'].extend(content['Replacements']) + except KeyError: + pass # Ignore files with missing keys + + if merged['Replacements']: + with open(fixfile,'w') as out: + yaml.safe_dump(merged, out) + 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') invocation.append(tmpdir) subprocess.call(invocation) - shutil.rmtree(tmpdir) def run_tidy(args, tmpdir, build_path, queue): @@ -129,6 +154,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=['.*'], @@ -178,7 +206,7 @@ max_task = multiprocessing.cpu_count() tmpdir = None - if args.fix: + if args.fix or args.export_fixes: tmpdir = tempfile.mkdtemp() # Build up a big regexy filter from all command line arguments. @@ -205,13 +233,20 @@ # 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) + if args.export_fixes: + print 'Writing fixes to ' + args.export_fixes + merge_replacement_files(tmpdir,args.export_fixes) + if args.fix: print 'Applying fixes ...' apply_fixes(args, tmpdir) + if tmpdir: + shutil.rmtree(tmpdir) + if __name__ == '__main__': main()