blob: 6f20cb76e4831c52e6b3e69858a779050a7dddb3 [file] [log] [blame]
Chandler Carruthcba0f3d2012-12-03 14:23:44 +00001#!/usr/bin/env python
2
3"""Script to sort the top-most block of #include lines.
4
5Assumes the LLVM coding conventions.
6
7Currently, this script only bothers sorting the llvm/... headers. Patches
8welcome for more functionality, and sorting other header groups.
9"""
10
11import argparse
12import os
13import re
14import sys
15import tempfile
16
17def sort_includes(f):
18 lines = f.readlines()
19 look_for_api_header = f.name[-4:] == '.cpp'
20 headers_begin = 0
21 headers_end = 0
22 api_headers = []
23 local_headers = []
24 project_headers = []
25 system_headers = []
26 for (i, l) in enumerate(lines):
27 if l.strip() == '':
28 continue
29 if l.startswith('#include'):
30 if headers_begin == 0:
31 headers_begin = i
32 headers_end = i
33 header = l[len('#include'):].lstrip()
34 if look_for_api_header and header.startswith('"'):
35 api_headers.append(header)
36 look_for_api_header = False
37 continue
38 if header.startswith('<'):
39 system_headers.append(header)
40 continue
41 if header.startswith('"llvm/') or header.startswith('"clang/'):
42 project_headers.append(header)
43 continue
44 local_headers.append(header)
45 continue
46
47 # Only allow comments and #defines prior to any includes. If either are
48 # mixed with includes, the order might be sensitive.
49 if headers_begin != 0:
50 break
51 if l.startswith('//') or l.startswith('#define'):
52 continue
53 break
54 if headers_begin == 0:
55 return
56
57 local_headers.sort()
58 project_headers.sort()
59 system_headers.sort()
60 headers = api_headers + local_headers + project_headers + system_headers
61 header_lines = ['#include ' + h for h in headers]
62 lines = lines[:headers_begin] + header_lines + lines[headers_end + 1:]
63
64 #for l in lines[headers_begin:headers_end]:
65 # print l.rstrip()
66 f.seek(0)
67 f.truncate()
68 f.writelines(lines)
69
70def main():
71 parser = argparse.ArgumentParser(description=__doc__)
72 parser.add_argument('files', nargs='+', type=argparse.FileType('r+'),
73 help='the source files to sort includes within')
74 args = parser.parse_args()
75 for f in args.files:
76 sort_includes(f)
77
78if __name__ == '__main__':
79 main()