Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: tools/sort-headers.py

Issue 1213613011: Allow move_source_file.py and sort-headers.py to work on blink. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Feedback Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/git/move_source_file.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Given a filename as an argument, sort the #include/#imports in that file. 6 """Given a filename as an argument, sort the #include/#imports in that file.
7 7
8 Shows a diff and prompts for confirmation before doing the deed. 8 Shows a diff and prompts for confirmation before doing the deed.
9 Works great with tools/git/for-all-touched-files.py. 9 Works great with tools/git/for-all-touched-files.py.
10 """ 10 """
11 11
12 import optparse 12 import optparse
13 import os 13 import os
14 import sys 14 import sys
15 15
16 from yes_no import YesNo 16 from yes_no import YesNo
17 17
18 18
19 def IncludeCompareKey(line): 19 def IsInclude(line):
20 """Returns True if the line is an #include/#import/import line."""
21 return any([line.startswith('#include '), line.startswith('#import '),
22 line.startswith('import ')])
23
24
25 def IncludeCompareKey(line, for_blink):
20 """Sorting comparator key used for comparing two #include lines. 26 """Sorting comparator key used for comparing two #include lines.
21 Returns the filename without the #include/#import/import prefix. 27
28 Returns an integer, optionally followed by a string. The integer is used
29 for coarse sorting of different categories of headers, and the string is
30 used for fine sorting of headers within categeries.
22 """ 31 """
23 for prefix in ('#include ', '#import ', 'import '): 32 for prefix in ('#include ', '#import ', 'import '):
24 if line.startswith(prefix): 33 if line.startswith(prefix):
25 line = line[len(prefix):] 34 line = line[len(prefix):]
26 break 35 break
27 36
37 if for_blink:
38 # Blink likes to have its "config.h" include first.
39 if line.startswith('"config.h"'):
40 return '0'
41
42 # Blink sorts system headers after others. This is handled by sorting
43 # alphabetically so no need to do anything tricky.
44 return '1' + line
45
28 # The win32 api has all sorts of implicit include order dependencies :-/ 46 # The win32 api has all sorts of implicit include order dependencies :-/
29 # Give a few headers special sort keys that make sure they appear before all 47 # Give a few headers special sort keys that make sure they appear before all
30 # other headers. 48 # other headers.
31 if line.startswith('<windows.h>'): # Must be before e.g. shellapi.h 49 if line.startswith('<windows.h>'): # Must be before e.g. shellapi.h
32 return '0' 50 return '0'
33 if line.startswith('<atlbase.h>'): # Must be before atlapp.h. 51 if line.startswith('<atlbase.h>'): # Must be before atlapp.h.
34 return '1' + line 52 return '1' + line
35 if line.startswith('<ole2.h>'): # Must be before e.g. intshcut.h 53 if line.startswith('<ole2.h>'): # Must be before e.g. intshcut.h
36 return '1' + line 54 return '1' + line
37 if line.startswith('<unknwn.h>'): # Must be before e.g. intshcut.h 55 if line.startswith('<unknwn.h>'): # Must be before e.g. intshcut.h
38 return '1' + line 56 return '1' + line
39 57
40 # C++ system headers should come after C system headers. 58 # C++ system headers should come after C system headers.
41 if line.startswith('<'): 59 if line.startswith('<'):
42 if line.find('.h>') != -1: 60 if line.find('.h>') != -1:
43 return '2' + line.lower() 61 return '2' + line.lower()
44 else: 62 else:
45 return '3' + line.lower() 63 return '3' + line.lower()
46 64
47 return '4' + line 65 return '4' + line
48 66
49 67
50 def IsInclude(line): 68 def SortHeader(infile, outfile, for_blink):
51 """Returns True if the line is an #include/#import/import line.""" 69 """Sorts the headers in infile, writing the sorted file to outfile."""
52 return any([line.startswith('#include '), line.startswith('#import '), 70 def CompareKey(line):
53 line.startswith('import ')]) 71 return IncludeCompareKey(line, for_blink)
54 72
55
56 def SortHeader(infile, outfile):
57 """Sorts the headers in infile, writing the sorted file to outfile."""
58 for line in infile: 73 for line in infile:
59 if IsInclude(line): 74 if IsInclude(line):
60 headerblock = [] 75 headerblock = []
61 while IsInclude(line): 76 while IsInclude(line):
62 infile_ended_on_include_line = False 77 infile_ended_on_include_line = False
63 headerblock.append(line) 78 headerblock.append(line)
64 # Ensure we don't die due to trying to read beyond the end of the file. 79 # Ensure we don't die due to trying to read beyond the end of the file.
65 try: 80 try:
66 line = infile.next() 81 line = infile.next()
67 except StopIteration: 82 except StopIteration:
68 infile_ended_on_include_line = True 83 infile_ended_on_include_line = True
69 break 84 break
70 for header in sorted(headerblock, key=IncludeCompareKey): 85 for header in sorted(headerblock, key=CompareKey):
71 outfile.write(header) 86 outfile.write(header)
72 if infile_ended_on_include_line: 87 if infile_ended_on_include_line:
73 # We already wrote the last line above; exit to ensure it isn't written 88 # We already wrote the last line above; exit to ensure it isn't written
74 # again. 89 # again.
75 return 90 return
76 # Intentionally fall through, to write the line that caused 91 # Intentionally fall through, to write the line that caused
77 # the above while loop to exit. 92 # the above while loop to exit.
78 outfile.write(line) 93 outfile.write(line)
79 94
80 95
81 def FixFileWithConfirmFunction(filename, confirm_function, 96 def FixFileWithConfirmFunction(filename, confirm_function,
82 perform_safety_checks): 97 perform_safety_checks, for_blink=False):
83 """Creates a fixed version of the file, invokes |confirm_function| 98 """Creates a fixed version of the file, invokes |confirm_function|
84 to decide whether to use the new file, and cleans up. 99 to decide whether to use the new file, and cleans up.
85 100
86 |confirm_function| takes two parameters, the original filename and 101 |confirm_function| takes two parameters, the original filename and
87 the fixed-up filename, and returns True to use the fixed-up file, 102 the fixed-up filename, and returns True to use the fixed-up file,
88 false to not use it. 103 false to not use it.
89 104
90 If |perform_safety_checks| is True, then the function checks whether it is 105 If |perform_safety_checks| is True, then the function checks whether it is
91 unsafe to reorder headers in this file and skips the reorder with a warning 106 unsafe to reorder headers in this file and skips the reorder with a warning
92 message in that case. 107 message in that case.
93 """ 108 """
94 if perform_safety_checks and IsUnsafeToReorderHeaders(filename): 109 if perform_safety_checks and IsUnsafeToReorderHeaders(filename):
95 print ('Not reordering headers in %s as the script thinks that the ' 110 print ('Not reordering headers in %s as the script thinks that the '
96 'order of headers in this file is semantically significant.' 111 'order of headers in this file is semantically significant.'
97 % (filename)) 112 % (filename))
98 return 113 return
99 fixfilename = filename + '.new' 114 fixfilename = filename + '.new'
100 infile = open(filename, 'rb') 115 infile = open(filename, 'rb')
101 outfile = open(fixfilename, 'wb') 116 outfile = open(fixfilename, 'wb')
102 SortHeader(infile, outfile) 117 SortHeader(infile, outfile, for_blink)
103 infile.close() 118 infile.close()
104 outfile.close() # Important so the below diff gets the updated contents. 119 outfile.close() # Important so the below diff gets the updated contents.
105 120
106 try: 121 try:
107 if confirm_function(filename, fixfilename): 122 if confirm_function(filename, fixfilename):
108 if sys.platform == 'win32': 123 if sys.platform == 'win32':
109 os.unlink(filename) 124 os.unlink(filename)
110 os.rename(fixfilename, filename) 125 os.rename(fixfilename, filename)
111 finally: 126 finally:
112 try: 127 try:
113 os.remove(fixfilename) 128 os.remove(fixfilename)
114 except OSError: 129 except OSError:
115 # If the file isn't there, we don't care. 130 # If the file isn't there, we don't care.
116 pass 131 pass
117 132
118 133
119 def DiffAndConfirm(filename, should_confirm, perform_safety_checks): 134 def DiffAndConfirm(filename, should_confirm, perform_safety_checks, for_blink):
120 """Shows a diff of what the tool would change the file named 135 """Shows a diff of what the tool would change the file named
121 filename to. Shows a confirmation prompt if should_confirm is true. 136 filename to. Shows a confirmation prompt if should_confirm is true.
122 Saves the resulting file if should_confirm is false or the user 137 Saves the resulting file if should_confirm is false or the user
123 answers Y to the confirmation prompt. 138 answers Y to the confirmation prompt.
124 """ 139 """
125 def ConfirmFunction(filename, fixfilename): 140 def ConfirmFunction(filename, fixfilename):
126 diff = os.system('diff -u %s %s' % (filename, fixfilename)) 141 diff = os.system('diff -u %s %s' % (filename, fixfilename))
127 if sys.platform != 'win32': 142 if sys.platform != 'win32':
128 diff >>= 8 143 diff >>= 8
129 if diff == 0: # Check exit code. 144 if diff == 0: # Check exit code.
130 print '%s: no change' % filename 145 print '%s: no change' % filename
131 return False 146 return False
132 147
133 return (not should_confirm or YesNo('Use new file (y/N)?')) 148 return (not should_confirm or YesNo('Use new file (y/N)?'))
134 149
135 FixFileWithConfirmFunction(filename, ConfirmFunction, perform_safety_checks) 150 FixFileWithConfirmFunction(filename, ConfirmFunction, perform_safety_checks,
151 for_blink)
136 152
137 def IsUnsafeToReorderHeaders(filename): 153 def IsUnsafeToReorderHeaders(filename):
138 # *_message_generator.cc is almost certainly a file that generates IPC 154 # *_message_generator.cc is almost certainly a file that generates IPC
139 # definitions. Changes in include order in these files can result in them not 155 # definitions. Changes in include order in these files can result in them not
140 # building correctly. 156 # building correctly.
141 if filename.find("message_generator.cc") != -1: 157 if filename.find("message_generator.cc") != -1:
142 return True 158 return True
143 return False 159 return False
144 160
145 def main(): 161 def main():
146 parser = optparse.OptionParser(usage='%prog filename1 filename2 ...') 162 parser = optparse.OptionParser(usage='%prog filename1 filename2 ...')
147 parser.add_option('-f', '--force', action='store_false', default=True, 163 parser.add_option('-f', '--force', action='store_false', default=True,
148 dest='should_confirm', 164 dest='should_confirm',
149 help='Turn off confirmation prompt.') 165 help='Turn off confirmation prompt.')
150 parser.add_option('--no_safety_checks', 166 parser.add_option('--no_safety_checks',
151 action='store_false', default=True, 167 action='store_false', default=True,
152 dest='perform_safety_checks', 168 dest='perform_safety_checks',
153 help='Do not perform the safety checks via which this ' 169 help='Do not perform the safety checks via which this '
154 'script refuses to operate on files for which it thinks ' 170 'script refuses to operate on files for which it thinks '
155 'the include ordering is semantically significant.') 171 'the include ordering is semantically significant.')
172 parser.add_option('--for_blink', action='store_true', default=False,
173 dest='for_blink', help='Whether the blink header sorting '
174 'rules should be applied.')
156 opts, filenames = parser.parse_args() 175 opts, filenames = parser.parse_args()
157 176
158 if len(filenames) < 1: 177 if len(filenames) < 1:
159 parser.print_help() 178 parser.print_help()
160 return 1 179 return 1
161 180
162 for filename in filenames: 181 for filename in filenames:
163 DiffAndConfirm(filename, opts.should_confirm, opts.perform_safety_checks) 182 DiffAndConfirm(filename, opts.should_confirm, opts.perform_safety_checks,
183 opts.for_blink)
164 184
165 185
166 if __name__ == '__main__': 186 if __name__ == '__main__':
167 sys.exit(main()) 187 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/git/move_source_file.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698