aboutsummaryrefslogtreecommitdiff
path: root/clang-format
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2013-01-09 20:20:11 +0000
committerDaniel Jasper <djasper@google.com>2013-01-09 20:20:11 +0000
commitd9d7bf9f30c9c1a1b3baf47de9ddd08c252377c9 (patch)
tree78337bccb8db289c5b3aeb1d6f54a5e916fa9f54 /clang-format
parentc0d1dc5c66a9734af2130f80556555f7821ca16c (diff)
Initial version of diff/patch-reformat tool.
Use at your own risk :-). git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@171994 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-format')
-rwxr-xr-xclang-format/clang-format-diff.py117
1 files changed, 117 insertions, 0 deletions
diff --git a/clang-format/clang-format-diff.py b/clang-format/clang-format-diff.py
new file mode 100755
index 00000000..cd01f93d
--- /dev/null
+++ b/clang-format/clang-format-diff.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+#
+#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+ClangFormat Diff Reformatter
+============================
+
+This script reads input from a unified diff and reformats all the changed
+lines. This is useful to reformat all the lines touched by a specific patch.
+Example usage for git users:
+
+ git diff -U0 HEAD^ | clang-format-diff.py -p1
+
+"""
+
+import argparse
+import re
+import subprocess
+import sys
+
+
+# Change this to the full path if clang-format is not on the path.
+binary = 'clang-format'
+
+
+def getOffsetLength(filename, line_number, line_count):
+ """
+ Calculates the field offset and length based on line number and count.
+ """
+ offset = 0
+ length = 0
+ with open(filename, 'r') as f:
+ for line in f:
+ if line_number > 1:
+ offset += len(line)
+ line_number -= 1
+ elif line_count > 0:
+ length += len(line)
+ line_count -= 1
+ else:
+ break
+ return offset, length
+
+
+def formatRange(r, style):
+ """
+ Formats range 'r' according to style 'style'.
+ """
+ filename, line_number, line_count = r
+ # FIXME: Add other types containing C++/ObjC code.
+ if not (filename.endswith(".cpp") or filename.endswith(".cc") or
+ filename.endswith(".h")):
+ return
+
+ offset, length = getOffsetLength(filename, line_number, line_count)
+ with open(filename, 'r') as f:
+ text = f.read()
+ p = subprocess.Popen([binary, '-offset', str(offset), '-length', str(length),
+ '-style', style],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE)
+ stdout, stderr = p.communicate(input=text)
+ if stderr:
+ print stderr
+ return
+ if not stdout:
+ print 'Segfault occurred while formatting', filename
+ print 'Please report a bug on llvm.org/bugs.'
+ return
+ with open(filename, 'w') as f:
+ f.write(stdout)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=
+ 'Reformat changed lines in diff')
+ parser.add_argument('-p', default=1,
+ help='strip the smallest prefix containing P slashes')
+ parser.add_argument('-style', default='LLVM',
+ help='formatting style to apply (LLVM, Google)')
+ args = parser.parse_args()
+
+ filename = None
+ ranges = []
+
+ for line in sys.stdin:
+ match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
+ if match:
+ filename = match.group(2)
+ if filename == None:
+ continue
+
+ match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
+ if match:
+ line_count = 1
+ if match.group(3):
+ line_count = int(match.group(3))
+ ranges.append((filename, int(match.group(1)), line_count))
+
+ # Reverse the ranges so that the reformatting does not influence file offsets.
+ ranges.reverse()
+
+ # Do the actual formatting.
+ for r in ranges:
+ formatRange(r, args.style)
+
+
+if __name__ == '__main__':
+ main()