mirror of
https://github.com/signalapp/Signal-iOS.git
synced 2025-12-05 01:10:41 +00:00
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`.
This commit is contained in:
@@ -13,5 +13,5 @@ PointerBindsToType: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
SortIncludes: false
|
||||
SortIncludes: CaseSensitive
|
||||
...
|
||||
|
||||
@@ -17,153 +17,6 @@ git_repo_path = os.path.abspath(
|
||||
)
|
||||
|
||||
|
||||
class include:
|
||||
def __init__(self, isInclude, isQuote, body, comment):
|
||||
self.isInclude = isInclude
|
||||
self.isQuote = isQuote
|
||||
self.body = body
|
||||
self.comment = comment
|
||||
|
||||
def format(self):
|
||||
result = "%s %s%s%s" % (
|
||||
("#include" if self.isInclude else "#import"),
|
||||
('"' if self.isQuote else "<"),
|
||||
self.body.strip(),
|
||||
('"' if self.isQuote else ">"),
|
||||
)
|
||||
if self.comment.strip():
|
||||
result += " " + self.comment.strip()
|
||||
return result
|
||||
|
||||
|
||||
def is_include_or_import(line):
|
||||
line = line.strip()
|
||||
if line.startswith("#include "):
|
||||
return True
|
||||
elif line.startswith("#import "):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def parse_include(line):
|
||||
remainder = line.strip()
|
||||
|
||||
if remainder.startswith("#include "):
|
||||
isInclude = True
|
||||
remainder = remainder[len("#include ") :]
|
||||
elif remainder.startswith("#import "):
|
||||
isInclude = False
|
||||
remainder = remainder[len("#import ") :]
|
||||
elif remainder == "//":
|
||||
return None
|
||||
elif not remainder:
|
||||
return None
|
||||
else:
|
||||
print("Unexpected import or include: " + line)
|
||||
sys.exit(1)
|
||||
|
||||
comment = None
|
||||
if remainder.startswith('"'):
|
||||
isQuote = True
|
||||
endIndex = remainder.find('"', 1)
|
||||
if endIndex < 0:
|
||||
print("Unexpected import or include: " + line)
|
||||
sys.exit(1)
|
||||
body = remainder[1:endIndex]
|
||||
comment = remainder[endIndex + 1 :]
|
||||
elif remainder.startswith("<"):
|
||||
isQuote = False
|
||||
endIndex = remainder.find(">", 1)
|
||||
if endIndex < 0:
|
||||
print("Unexpected import or include: " + line)
|
||||
sys.exit(1)
|
||||
body = remainder[1:endIndex]
|
||||
comment = remainder[endIndex + 1 :]
|
||||
else:
|
||||
print("Unexpected import or include: " + remainder)
|
||||
sys.exit(1)
|
||||
|
||||
return include(isInclude, isQuote, body, comment)
|
||||
|
||||
|
||||
def parse_includes(text):
|
||||
lines = text.split("\n")
|
||||
|
||||
includes = []
|
||||
for line in lines:
|
||||
include = parse_include(line)
|
||||
if include:
|
||||
includes.append(include)
|
||||
|
||||
return includes
|
||||
|
||||
|
||||
def sort_include_block(text, filepath, filename, file_extension):
|
||||
includes = parse_includes(text)
|
||||
|
||||
blocks = []
|
||||
|
||||
file_extension = file_extension.lower()
|
||||
|
||||
for include in includes:
|
||||
include.isInclude = False
|
||||
|
||||
if file_extension in ("c", "cpp", "hpp"):
|
||||
for include in includes:
|
||||
include.isInclude = True
|
||||
elif file_extension in ("m"):
|
||||
for include in includes:
|
||||
include.isInclude = False
|
||||
|
||||
# Make sure matching header is first.
|
||||
matching_header_includes = []
|
||||
other_includes = []
|
||||
|
||||
def is_matching_header(include):
|
||||
filename_wo_ext = os.path.splitext(filename)[0]
|
||||
include_filename_wo_ext = os.path.splitext(os.path.basename(include.body))[0]
|
||||
return filename_wo_ext == include_filename_wo_ext
|
||||
|
||||
for include in includes:
|
||||
if is_matching_header(include):
|
||||
matching_header_includes.append(include)
|
||||
else:
|
||||
other_includes.append(include)
|
||||
includes = other_includes
|
||||
|
||||
def formatBlock(includes):
|
||||
lines = set([include.format() for include in includes])
|
||||
return "\n".join(sorted(lines))
|
||||
|
||||
includeAngles = [
|
||||
include for include in includes if include.isInclude and not include.isQuote
|
||||
]
|
||||
includeQuotes = [
|
||||
include for include in includes if include.isInclude and include.isQuote
|
||||
]
|
||||
importAngles = [
|
||||
include
|
||||
for include in includes
|
||||
if (not include.isInclude) and not include.isQuote
|
||||
]
|
||||
importQuotes = [
|
||||
include for include in includes if (not include.isInclude) and include.isQuote
|
||||
]
|
||||
if matching_header_includes:
|
||||
blocks.append(formatBlock(matching_header_includes))
|
||||
if includeQuotes:
|
||||
blocks.append(formatBlock(includeQuotes))
|
||||
if includeAngles:
|
||||
blocks.append(formatBlock(includeAngles))
|
||||
if importQuotes:
|
||||
blocks.append(formatBlock(importQuotes))
|
||||
if importAngles:
|
||||
blocks.append(formatBlock(importAngles))
|
||||
|
||||
return "\n".join(blocks) + "\n"
|
||||
|
||||
|
||||
def sort_forward_decl_statement_block(text, filepath, filename, file_extension):
|
||||
lines = text.split("\n")
|
||||
lines = [line.strip() for line in lines if line.strip()]
|
||||
@@ -289,29 +142,6 @@ def find_forward_protocol_statement_section(text):
|
||||
return find_matching_section(text, is_forward_protocol_statement)
|
||||
|
||||
|
||||
def find_include_section(text):
|
||||
def is_include_line(line):
|
||||
return is_include_or_import(line)
|
||||
# return is_include_or_import_or_empty(line)
|
||||
|
||||
return find_matching_section(text, is_include_line)
|
||||
|
||||
|
||||
def sort_includes(filepath, filename, file_extension, text):
|
||||
# print 'sort_includes', filepath
|
||||
if file_extension not in (".h", ".m", ".mm"):
|
||||
return text
|
||||
return sort_matching_blocks(
|
||||
"sort_includes",
|
||||
filepath,
|
||||
filename,
|
||||
file_extension,
|
||||
text,
|
||||
find_include_section,
|
||||
sort_include_block,
|
||||
)
|
||||
|
||||
|
||||
def sort_forward_class_statements(filepath, filename, file_extension, text):
|
||||
# print 'sort_class_statements', filepath
|
||||
if file_extension not in (".h", ".m", ".mm"):
|
||||
@@ -361,7 +191,6 @@ def process(filepath):
|
||||
|
||||
original_text = text
|
||||
|
||||
text = sort_includes(filepath, filename, file_ext, text)
|
||||
text = sort_forward_class_statements(filepath, filename, file_ext, text)
|
||||
text = sort_forward_protocol_statements(filepath, filename, file_ext, text)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user