Skip to content

Commit f8afc58

Browse files
Prefer clang-format for sorting #import/#include
This should have no direct user impact. We currently have two ways of sorting `#import` and `#include` statements: 1. With our precommit script 2. With `clang-format` (via `git-clang-format`) It *looks* like we aren't using `clang-format` (because of the `SortIncludes: false` option in `.clang-format`) but we are, which you can see by running `clang-format --dump-config`. As a separate issue, it seems like we're not picking up the `clang-format` configuration file (`clang-format --style=file:.clang-format --dump-config` gives different results). I've run into situations where the two of them "fight", so I think the best thing to do is pick one. After some discussion, we decided to pick `clang-format`.
1 parent 0f232ce commit f8afc58

File tree

2 files changed

+1
-172
lines changed

2 files changed

+1
-172
lines changed

.clang-format

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ PointerBindsToType: false
1313
SpacesBeforeTrailingComments: 1
1414
TabWidth: 8
1515
UseTab: Never
16-
SortIncludes: false
16+
SortIncludes: CaseSensitive
1717
...

Scripts/precommit.py

-171
Original file line numberDiff line numberDiff line change
@@ -17,153 +17,6 @@
1717
)
1818

1919

20-
class include:
21-
def __init__(self, isInclude, isQuote, body, comment):
22-
self.isInclude = isInclude
23-
self.isQuote = isQuote
24-
self.body = body
25-
self.comment = comment
26-
27-
def format(self):
28-
result = "%s %s%s%s" % (
29-
("#include" if self.isInclude else "#import"),
30-
('"' if self.isQuote else "<"),
31-
self.body.strip(),
32-
('"' if self.isQuote else ">"),
33-
)
34-
if self.comment.strip():
35-
result += " " + self.comment.strip()
36-
return result
37-
38-
39-
def is_include_or_import(line):
40-
line = line.strip()
41-
if line.startswith("#include "):
42-
return True
43-
elif line.startswith("#import "):
44-
return True
45-
else:
46-
return False
47-
48-
49-
def parse_include(line):
50-
remainder = line.strip()
51-
52-
if remainder.startswith("#include "):
53-
isInclude = True
54-
remainder = remainder[len("#include ") :]
55-
elif remainder.startswith("#import "):
56-
isInclude = False
57-
remainder = remainder[len("#import ") :]
58-
elif remainder == "//":
59-
return None
60-
elif not remainder:
61-
return None
62-
else:
63-
print("Unexpected import or include: " + line)
64-
sys.exit(1)
65-
66-
comment = None
67-
if remainder.startswith('"'):
68-
isQuote = True
69-
endIndex = remainder.find('"', 1)
70-
if endIndex < 0:
71-
print("Unexpected import or include: " + line)
72-
sys.exit(1)
73-
body = remainder[1:endIndex]
74-
comment = remainder[endIndex + 1 :]
75-
elif remainder.startswith("<"):
76-
isQuote = False
77-
endIndex = remainder.find(">", 1)
78-
if endIndex < 0:
79-
print("Unexpected import or include: " + line)
80-
sys.exit(1)
81-
body = remainder[1:endIndex]
82-
comment = remainder[endIndex + 1 :]
83-
else:
84-
print("Unexpected import or include: " + remainder)
85-
sys.exit(1)
86-
87-
return include(isInclude, isQuote, body, comment)
88-
89-
90-
def parse_includes(text):
91-
lines = text.split("\n")
92-
93-
includes = []
94-
for line in lines:
95-
include = parse_include(line)
96-
if include:
97-
includes.append(include)
98-
99-
return includes
100-
101-
102-
def sort_include_block(text, filepath, filename, file_extension):
103-
includes = parse_includes(text)
104-
105-
blocks = []
106-
107-
file_extension = file_extension.lower()
108-
109-
for include in includes:
110-
include.isInclude = False
111-
112-
if file_extension in ("c", "cpp", "hpp"):
113-
for include in includes:
114-
include.isInclude = True
115-
elif file_extension in ("m"):
116-
for include in includes:
117-
include.isInclude = False
118-
119-
# Make sure matching header is first.
120-
matching_header_includes = []
121-
other_includes = []
122-
123-
def is_matching_header(include):
124-
filename_wo_ext = os.path.splitext(filename)[0]
125-
include_filename_wo_ext = os.path.splitext(os.path.basename(include.body))[0]
126-
return filename_wo_ext == include_filename_wo_ext
127-
128-
for include in includes:
129-
if is_matching_header(include):
130-
matching_header_includes.append(include)
131-
else:
132-
other_includes.append(include)
133-
includes = other_includes
134-
135-
def formatBlock(includes):
136-
lines = set([include.format() for include in includes])
137-
return "\n".join(sorted(lines))
138-
139-
includeAngles = [
140-
include for include in includes if include.isInclude and not include.isQuote
141-
]
142-
includeQuotes = [
143-
include for include in includes if include.isInclude and include.isQuote
144-
]
145-
importAngles = [
146-
include
147-
for include in includes
148-
if (not include.isInclude) and not include.isQuote
149-
]
150-
importQuotes = [
151-
include for include in includes if (not include.isInclude) and include.isQuote
152-
]
153-
if matching_header_includes:
154-
blocks.append(formatBlock(matching_header_includes))
155-
if includeQuotes:
156-
blocks.append(formatBlock(includeQuotes))
157-
if includeAngles:
158-
blocks.append(formatBlock(includeAngles))
159-
if importQuotes:
160-
blocks.append(formatBlock(importQuotes))
161-
if importAngles:
162-
blocks.append(formatBlock(importAngles))
163-
164-
return "\n".join(blocks) + "\n"
165-
166-
16720
def sort_forward_decl_statement_block(text, filepath, filename, file_extension):
16821
lines = text.split("\n")
16922
lines = [line.strip() for line in lines if line.strip()]
@@ -289,29 +142,6 @@ def is_forward_protocol_statement(line):
289142
return find_matching_section(text, is_forward_protocol_statement)
290143

291144

292-
def find_include_section(text):
293-
def is_include_line(line):
294-
return is_include_or_import(line)
295-
# return is_include_or_import_or_empty(line)
296-
297-
return find_matching_section(text, is_include_line)
298-
299-
300-
def sort_includes(filepath, filename, file_extension, text):
301-
# print 'sort_includes', filepath
302-
if file_extension not in (".h", ".m", ".mm"):
303-
return text
304-
return sort_matching_blocks(
305-
"sort_includes",
306-
filepath,
307-
filename,
308-
file_extension,
309-
text,
310-
find_include_section,
311-
sort_include_block,
312-
)
313-
314-
315145
def sort_forward_class_statements(filepath, filename, file_extension, text):
316146
# print 'sort_class_statements', filepath
317147
if file_extension not in (".h", ".m", ".mm"):
@@ -361,7 +191,6 @@ def process(filepath):
361191

362192
original_text = text
363193

364-
text = sort_includes(filepath, filename, file_ext, text)
365194
text = sort_forward_class_statements(filepath, filename, file_ext, text)
366195
text = sort_forward_protocol_statements(filepath, filename, file_ext, text)
367196

0 commit comments

Comments
 (0)