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

Side by Side Diff: tools/sort_sources.py

Issue 932133005: sort_sources.py: Document limitations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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 | « no previous file | 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 2015 The Chromium Authors. All rights reserved. 2 # Copyright 2015 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 GYP/GN filename, sort C-ish source files in that file. 6 """Given a GYP/GN filename, sort C-ish source files 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
11 Limitations:
12
13 1) Comments used as section headers
14
15 If a comment (1+ lines starting with #) appears in a source list without a
16 preceding blank line, the tool assumes that the comment is about the next
17 line. For example, given the following source list,
18
19 sources = [
20 "b.cc",
21 # Comment.
22 "a.cc",
23 "c.cc",
24 ]
25
26 the tool will produce the following output:
27
28 sources = [
29 # Comment.
30 "a.cc",
31 "b.cc",
32 "c.cc",
33 ]
34
35 This is not correct if the comment is for starting a new section like:
36
37 sources = [
38 "b.cc",
39 # These are for Linux.
40 "a.cc",
41 "c.cc",
42 ]
43
44 The tool cannot disambiguate the two types of comments. The problem can be
45 worked around by inserting a blank line before the comment because the tool
46 interprets a blank line as the end of a source list.
Daniel Erat 2015/02/19 14:05:17 hmm, it may not be possible to always do this. i t
satorux1 2015/02/20 00:14:29 It should be OK. Here's from ash/BUILD.gn: #
47
48 2) Sources commented out
49
50 Sometimes sources are commented out with their positions kept in the
51 alphabetical order, but what if the list is not sorted correctly? For
52 example, given the following source list,
53
54 sources = [
55 "a.cc",
56 # "b.cc",
57 "d.cc",
58 "c.cc",
59 ]
60
61 the tool will produce the following output:
62
63 sources = [
64 "a.cc",
65 "c.cc",
66 # "b.cc",
67 "d.cc",
68 ]
69
70 This is because the tool assumes that the comment (# "b.cc",) is about the
71 next line ("d.cc",). This kind of errors should be fixed manually.
Daniel Erat 2015/02/19 14:05:17 maybe you should say that the fix is to not check
satorux1 2015/02/20 00:14:29 good point. added.
72
73 3) " and ' are used both used in the same source list (GYP only problem)
74
75 If both " and ' are used in the same source list, sources quoted with " will
76 appear first in the output. The problem is rare enough so the tool does not
77 attempt to normalize them. Hence this kind of errors should be fixed
78 manually.
79
80 4) Spaces and tabs used in the same source list
81
82 Similarly, if spaces and tabs are both used in the same source list, sources
83 indented with tabs will appear first in the output. This kind of errors
84 should be fixed manually.
10 """ 85 """
11 86
12 import difflib 87 import difflib
13 import optparse 88 import optparse
14 import re 89 import re
15 import sys 90 import sys
16 91
17 from yes_no import YesNo 92 from yes_no import YesNo
18 93
19 SUFFIXES = ['c', 'cc', 'cpp', 'h', 'mm', 'rc', 'rc.version', 'ico', 'def', 94 SUFFIXES = ['c', 'cc', 'cpp', 'h', 'mm', 'rc', 'rc.version', 'ico', 'def',
20 'release'] 95 'release']
21 SOURCE_PATTERN = re.compile('^\s+[\'"].*\.(%s)[\'"],$' % 96 SOURCE_PATTERN = re.compile(r'^\s+[\'"].*\.(%s)[\'"],$' %
22 '|'.join([re.escape(x) for x in SUFFIXES])) 97 '|'.join([re.escape(x) for x in SUFFIXES]))
23 COMMENT_PATTERN = re.compile('^\s+#') 98 COMMENT_PATTERN = re.compile(r'^\s+#')
99
24 100
25 def SortSources(original_lines): 101 def SortSources(original_lines):
26 """Sort source file names in |original_lines|. 102 """Sort source file names in |original_lines|.
27 103
28 Args: 104 Args:
29 original_lines: Lines of the original content as a list of strings. 105 original_lines: Lines of the original content as a list of strings.
30 106
31 Returns: 107 Returns:
32 Lines of the sorted content as a list of strings. 108 Lines of the sorted content as a list of strings.
33 109
34 The algorithm is fairly naive. The code tries to find a list of C-ish 110 The algorithm is fairly naive. The code tries to find a list of C-ish
35 source file names by a simple regex, then sort them. The code does not try 111 source file names by a simple regex, then sort them. The code does not try
36 to understand the syntax of the build files, hence there are some cases 112 to understand the syntax of the build files. See the file comment above for
37 that the code cannot handle correctly (ex. blank lines within a list of 113 details.
38 source file names).
39 """ 114 """
40 115
41 output_lines = [] 116 output_lines = []
42 comments = [] 117 comments = []
43 sources = [] 118 sources = []
44 for line in original_lines: 119 for line in original_lines:
45 if re.search(COMMENT_PATTERN, line): 120 if re.search(COMMENT_PATTERN, line):
46 comments.append(line) 121 comments.append(line)
47 elif re.search(SOURCE_PATTERN, line): 122 elif re.search(SOURCE_PATTERN, line):
48 # Associate the line with the preceeding comments. 123 # Associate the line with the preceding comments.
49 sources.append([line, comments]) 124 sources.append([line, comments])
50 comments = [] 125 comments = []
51 else: 126 else:
52 # |sources| should be flushed first, to handle comments at the end of a 127 # |sources| should be flushed first, to handle comments at the end of a
53 # source list correctly. 128 # source list correctly.
54 if sources: 129 if sources:
55 for source_line, source_comments in sorted(sources): 130 for source_line, source_comments in sorted(sources):
56 output_lines.extend(source_comments) 131 output_lines.extend(source_comments)
57 output_lines.append(source_line) 132 output_lines.append(source_line)
58 sources = [] 133 sources = []
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 if len(filenames) < 1: 176 if len(filenames) < 1:
102 parser.print_help() 177 parser.print_help()
103 return 1 178 return 1
104 179
105 for filename in filenames: 180 for filename in filenames:
106 ProcessFile(filename, opts.should_confirm) 181 ProcessFile(filename, opts.should_confirm)
107 182
108 183
109 if __name__ == '__main__': 184 if __name__ == '__main__':
110 sys.exit(main()) 185 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698