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
|
SpacesBeforeTrailingComments: 1
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
UseTab: Never
|
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):
|
def sort_forward_decl_statement_block(text, filepath, filename, file_extension):
|
||||||
lines = text.split("\n")
|
lines = text.split("\n")
|
||||||
lines = [line.strip() for line in lines if line.strip()]
|
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)
|
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):
|
def sort_forward_class_statements(filepath, filename, file_extension, text):
|
||||||
# print 'sort_class_statements', filepath
|
# print 'sort_class_statements', filepath
|
||||||
if file_extension not in (".h", ".m", ".mm"):
|
if file_extension not in (".h", ".m", ".mm"):
|
||||||
@@ -361,7 +191,6 @@ def process(filepath):
|
|||||||
|
|
||||||
original_text = text
|
original_text = text
|
||||||
|
|
||||||
text = sort_includes(filepath, filename, file_ext, text)
|
|
||||||
text = sort_forward_class_statements(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)
|
text = sort_forward_protocol_statements(filepath, filename, file_ext, text)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user