[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst updated this revision to Diff 92986. mfherbst added a comment. Fixed typos (MainFile => MainSourceFile) https://reviews.llvm.org/D31326 Files: run-clang-tidy.py 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() 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 '
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst updated this revision to Diff 105592. mfherbst added a comment. Herald added a subscriber: JDevlieghere. - Adapted patch to changes suggested by alexfh - Added comment why setting MainSourceFile to an empty string if fixes are exported https://reviews.llvm.org/D31326 Files: run-clang-tidy.py Index: run-clang-tidy.py === --- run-clang-tidy.py +++ run-clang-tidy.py @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, fixfile): + """Merge all replacement files in a directory into a single fixfile""" + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never usid inside clang-apply-replacements, + # so we set it to '' here. + merged={ 'MainSourceFile': '', '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: + 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 +153,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 +205,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 +232,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() Index: run-clang-tidy.py === --- run-clang-tidy.py +++ run-clang-tidy.py @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, fixfile): + """Merge all replacement files in a directory into a single fixfile""" + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never usid inside clang-apply-replacements, + # so we set it to '' here. + merged={ 'MainSourceFile': '', '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: + 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
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst added inline comments. Comment at: run-clang-tidy.py:105 + elif merged['MainSourceFile'] != content['MainSourceFile']: +# The values given for MainSourceFile are inconsistent. +# Just empty MainSourceFile blank: alexfh wrote: > This is going to be the case for each non-trivial invocation of this script. > Do we need to keep `MainSourceFile` at all? Good point. As it turns out clang-apply-replacement never uses the value afaik. The field needs to be around, however, since the definition of the replacements ``yaml`` format ( see ``clang/include/clang/Tooling/ReplacementsYaml.h``) makes it mandatory. https://reviews.llvm.org/D31326 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst updated this revision to Diff 105818. mfherbst added a comment. Correct nits and typos. 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 @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # 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': '', 'Replacements': [] } + + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): +with open(replacefile, 'r') as f: + content = yaml.safe_load(f) + if not content: +continue # Skip empty files. + +try: + merged['Replacements'].extend(content['Replacements']) +except KeyError: + pass # Ignore files with missing keys. + + if merged['Replacements']: +with open(mergefile,'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 +153,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 +205,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 +232,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() Index: clang-tidy/tool/run-clang-tidy.py === --- clang-tidy/tool/run-clang-tidy.py +++ clang-tidy/tool/run-clang-tidy.py @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # 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': '', 'Replacements': [] } + + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): +with open(replacefile, 'r') as f: + content = yaml.safe_load(f) + if not content: +continue # Skip empty files. + +try: + merged['Replacements'].extend(content['Replacements']) +except KeyError: + pass # Ignore files with missing keys. + + if merged['Replacements']: +with open(mergefile,'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,
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst added inline comments. Comment at: run-clang-tidy.py:93 +def merge_replacement_files(tmpdir, fixfile): + """Merge all replacement files in a directory into a single fixfile""" + # MainSourceFile: The key is required by the definition inside alexfh wrote: > I'm not sure "fixfile" is a word. Just "file" maybe? I thought I would refer to the name of the input argument, but I guess you are right, file makes it less clunky to read. https://reviews.llvm.org/D31326 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst updated this revision to Diff 105835. mfherbst added a comment. Correct the nits suggested by alexfh 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 @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # 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': '', 'Replacements': [] } + + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): +with open(replacefile, 'r') as f: + content = yaml.safe_load(f) + if not content: +continue # Skip empty files. + +try: + merged['Replacements'].extend(content['Replacements']) +except KeyError: + pass # Ignore files with missing keys. + + if merged['Replacements']: +with open(mergefile,'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 +153,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 +205,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 +232,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() Index: clang-tidy/tool/run-clang-tidy.py === --- clang-tidy/tool/run-clang-tidy.py +++ clang-tidy/tool/run-clang-tidy.py @@ -35,6 +35,7 @@ """ import argparse +import glob import json import multiprocessing import os @@ -45,6 +46,7 @@ import sys import tempfile import threading +import yaml def find_compilation_database(path): @@ -87,14 +89,36 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # 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': '', 'Replacements': [] } + + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): +with open(replacefile, 'r') as f: + content = yaml.safe_load(f) + if not content: +continue # Skip empty files. + +try: + merged['Replacements'].extend(content['Replacements']) +except KeyError: + pass # Ignore files with missing keys. + + if merged['Replacements']: +with open(mergefile,'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)
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst added a comment. I do not have commit rights to the svn if that's what you're asking, but I could send the patch to llvm-commits if that makes it easier for you. https://reviews.llvm.org/D31326 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
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
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst updated this revision to Diff 107633. mfherbst added a comment. Remove compatiblity with clang-tidy < 4.0.0 https://reviews.llvm.org/D31326 Files: run-clang-tidy.py Index: run-clang-tidy.py === --- run-clang-tidy.py +++ 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,31 @@ return start +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # The fixes suggested by clang-tidy >= 4.0.0 are given under + # the top level key 'Diagnostics' in the output yaml files + mergekey="Diagnostics" + merged=[] + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): +content = yaml.safe_load(open(replacefile, 'r')) +if not content: + continue # Skip empty files. +merged.extend(content.get(mergekey, [])) + + 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. +output = { 'MainSourceFile': '', mergekey: merged } +with open(mergefile, 'w') as out: + yaml.safe_dump(output, 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 +128,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 +170,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 +224,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 +252,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
[PATCH] D31326: Add option to export fixes to run-clang-tidy.py
mfherbst added a comment. Many thanks! https://reviews.llvm.org/D31326 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits