From 9226fb6e44d33664bd9dd4508921a59e8351915d Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Fri, 12 Apr 2024 09:59:10 +0200 Subject: [PATCH] Clang Format file and script Adds paths to ignore to clang-format, .clang-format file. Also a wrapper script to clang-format to read .clang-format-ignore. To format the whole tree at the root of the repository run: `find . -iname '*.h' -o -iname '*.cpp' -exec python3 Scripts/clang-format.py -i \{\} \;` --- .clang-format | 109 ++++++++++++++++++++++++++++++++++++++++ .clang-format-ignore | 17 +++++++ Scripts/clang-format.py | 70 ++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-format-ignore create mode 100644 Scripts/clang-format.py diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..9fdc1ddc9a --- /dev/null +++ b/.clang-format @@ -0,0 +1,109 @@ +Language: Cpp +BasedOnStyle: WebKit +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: Consecutive +AlignConsecutiveDeclarations: None +AlignConsecutiveMacros: None +AlignEscapedNewlines: DontAlign +AlignOperands: Align +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: Inline +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +AttributeMacros: + - JEMALLOC_NOTHROW + - FEX_ALIGNED + - FEX_ANNOTATE + - FEX_DEFAULT_VISIBILITY + - FEX_NAKED + - FEX_PACKED + - FEXCORE_PRESERVE_ALL_ATTR + - GLIBC_ALIAS_FUNCTION +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BreakAfterAttributes: Always # clang 16 required +BreakBeforeBraces: Attach +BreakBeforeBinaryOperators: None +BreakBeforeInlineASMColon: OnlyMultiline # clang 16 required +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeColon +ColumnLimit: 140 +CompactNamespaces: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +EmptyLineAfterAccessModifier: Leave +EmptyLineBeforeAccessModifier: Leave +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IncludeBlocks: Preserve +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: false +IndentPPDirectives: None +IndentRequires: false +IndentWidth: 2 +InsertBraces: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: OuterScope +LineEnding: LF # clang 16 required +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: Inner +QualifierAlignment: Left +PackConstructorInitializers: Never +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 2 +PenaltyBreakOpenParenthesis: 2 +PenaltyBreakString: 10 +PenaltyBreakTemplateDeclaration: 8 +PenaltyExcessCharacter: 2 +PenaltyReturnTypeOnItsOwnLine: 16 +PointerAlignment: Left +RemoveBracesLLVM: false +ReferenceAlignment: Left +ReflowComments: true +RequiresClausePosition: WithPreceding +SeparateDefinitionBlocks: Leave +SortIncludes: Never +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterFunctionDeclarationName: false + AfterFunctionDefinitionName: false + AfterOverloadedOperator: false + AfterRequiresInClause: true + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Leave +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInParentheses: false +Standard: c++20 +UseTab: Never diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 0000000000..5f2518306a --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1,17 @@ +# This file is used to ignore files and directories from clang-format + +# Ignore build folder +build/* + +# Ignore all files in the External directory +External/* + +# SoftFloat-3e code doesn't belong to us +FEXCore/Source/Common/SoftFloat-3e/* +Source/Common/cpp-optparse/* + +# Files with human-indented tables for readability - don't mess with these +FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp +FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp +FEXCore/Source/Interface/Core/X86Tables/* + diff --git a/Scripts/clang-format.py b/Scripts/clang-format.py new file mode 100644 index 0000000000..c23654eb2d --- /dev/null +++ b/Scripts/clang-format.py @@ -0,0 +1,70 @@ +import subprocess +import sys +import os +import re +import fnmatch + +# Wrapper globals +project_root = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..") +ignore_file_path = os.path.join(project_root, ".clang-format-ignore") +clang_format_command = "clang-format" + + +def glob_to_regex(pattern): + # Normalize directory separators + pattern = pattern.replace("\\", "/") + return fnmatch.translate(pattern) + + +def load_ignore_patterns(ignore_file_path): + with open(ignore_file_path, "r") as file: + lines = file.readlines() + + patterns = [] + for line in lines: + line = line.strip() + if line and not line.startswith("#"): # Ignore empty lines and comments + pattern = glob_to_regex(line) + patterns.append(re.compile(pattern)) + return patterns + + +def normalize_path(file_path): + absolute_path = os.path.abspath(file_path) + normalized_path = absolute_path.replace("\\", "/") + return normalized_path + + +def should_ignore(file_path, ignore_patterns): + normalized_path = normalize_path(file_path) + relative_path = os.path.relpath(normalized_path, start=project_root).replace( + "\\", "/" + ) + for pattern in ignore_patterns: + if pattern.match(relative_path): + return True + return False + + +def find_valid_file_paths(args): + return [arg for arg in args if os.path.isfile(arg)] + + +def main(): + ignore_patterns = load_ignore_patterns(ignore_file_path) + valid_paths = find_valid_file_paths(sys.argv[1:]) + + if len(valid_paths) != 1: + print("Error: Expected exactly one valid file path as argument.") + sys.exit(1) + + file_path = valid_paths[0] + if should_ignore(file_path, ignore_patterns): + print(f"Ignoring {file_path} based on ignore patterns.") + return + + subprocess.run([clang_format_command] + sys.argv[1:], check=True) + + +if __name__ == "__main__": + main()