diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /tools/clang-format/clang-format-diff.py | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'tools/clang-format/clang-format-diff.py')
-rwxr-xr-x | tools/clang-format/clang-format-diff.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py new file mode 100755 index 0000000..ab5f1b1 --- /dev/null +++ b/tools/clang-format/clang-format-diff.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# +#===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- 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. + for r in reversed(ranges): + # Do the actual formatting. + formatRange(r, args.style) + + +if __name__ == '__main__': + main() |