Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / clang_format / script / clang-format-diff.py
1 #!/usr/bin/python
2 #
3 #===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- python -*--===#
4 #
5 #                     The LLVM Compiler Infrastructure
6 #
7 # This file is distributed under the University of Illinois Open Source
8 # License. See LICENSE.TXT for details.
9 #
10 #===------------------------------------------------------------------------===#
11
12 r"""
13 ClangFormat Diff Reformatter
14 ============================
15
16 This script reads input from a unified diff and reformats all the changed
17 lines. This is useful to reformat all the lines touched by a specific patch.
18 Example usage for git users:
19
20   git diff -U0 HEAD^ | clang-format-diff.py -p1 -i
21
22 """
23
24 import argparse
25 import difflib
26 import re
27 import string
28 import subprocess
29 import StringIO
30 import sys
31
32
33 # Change this to the full path if clang-format is not on the path.
34 binary = 'clang-format'
35
36
37 def main():
38   parser = argparse.ArgumentParser(description=
39                                    'Reformat changed lines in diff. Without -i '
40                                    'option just output the diff that would be '
41                                    'introduced.')
42   parser.add_argument('-i', action='store_true', default=False,
43                       help='apply edits to files instead of displaying a diff')
44   parser.add_argument('-p', metavar='NUM', default=0,
45                       help='strip the smallest prefix containing P slashes')
46   parser.add_argument('-regex', metavar='PATTERN', default=None,
47                       help='custom pattern selecting file paths to reformat '
48                       '(case sensitive, overrides -iregex)')
49   parser.add_argument('-iregex', metavar='PATTERN', default=
50                       r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc|js)',
51                       help='custom pattern selecting file paths to reformat '
52                       '(case insensitive, overridden by -regex)')
53   parser.add_argument(
54       '-style',
55       help=
56       'formatting style to apply (LLVM, Google, Chromium, Mozilla, WebKit)')
57   args = parser.parse_args()
58
59   # Extract changed lines for each file.
60   filename = None
61   lines_by_file = {}
62   for line in sys.stdin:
63     match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
64     if match:
65       filename = match.group(2)
66     if filename == None:
67       continue
68
69     if args.regex is not None:
70       if not re.match('^%s$' % args.regex, filename):
71         continue
72     else:
73       if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
74         continue
75
76     match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
77     if match:
78       start_line = int(match.group(1))
79       line_count = 1
80       if match.group(3):
81         line_count = int(match.group(3))
82       if line_count == 0:
83         continue
84       end_line = start_line + line_count - 1;
85       lines_by_file.setdefault(filename, []).extend(
86           ['-lines', str(start_line) + ':' + str(end_line)])
87
88   # Reformat files containing changes in place.
89   for filename, lines in lines_by_file.iteritems():
90     command = [binary, filename]
91     if args.i:
92       command.append('-i')
93     command.extend(lines)
94     if args.style:
95       command.extend(['-style', args.style])
96     p = subprocess.Popen(command, stdout=subprocess.PIPE,
97                          stderr=None, stdin=subprocess.PIPE)
98     stdout, stderr = p.communicate()
99     if p.returncode != 0:
100       sys.exit(p.returncode);
101
102     if not args.i:
103       with open(filename) as f:
104         code = f.readlines()
105       formatted_code = StringIO.StringIO(stdout).readlines()
106       diff = difflib.unified_diff(code, formatted_code,
107                                   filename, filename,
108                                   '(before formatting)', '(after formatting)')
109       diff_string = string.join(diff, '')
110       if len(diff_string) > 0:
111         sys.stdout.write(diff_string)
112
113 if __name__ == '__main__':
114   main()