[PATCH] D31326: Add option to export fixes to run-clang-tidy.py

2017-03-24 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-07 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-07 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-10 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-10 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-10 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-10 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-18 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-20 Thread Michael F. Herbst via Phabricator via cfe-commits
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

2017-07-21 Thread Michael F. Herbst via Phabricator via cfe-commits
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