From f41310397070e748d46cb49357669946667fe23f Mon Sep 17 00:00:00 2001 From: James Price Date: Wed, 15 Apr 2020 10:46:39 -0400 Subject: [PATCH] Add clang-format config and check-format.sh script (#724) * Add clang-format config and check-format.sh script Travis CI is now configured to run check-format.sh and the job will fail if any format violations are detected. This will only check the format of new/modified code; existing code that violates the format will not cause a CI failure. * Make format checking the first Travis CI job * Tweak format based on Jeremy's preferences * Tweak format based on Kevin's preferences --- .clang-format | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 2 + check-format.sh | 13 +++++ clean_tests.py | 104 ---------------------------------------- travis.sh | 5 ++ 5 files changed, 144 insertions(+), 104 deletions(-) create mode 100644 .clang-format create mode 100755 check-format.sh delete mode 100755 clean_tests.py diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..ef5e5aee --- /dev/null +++ b/.clang-format @@ -0,0 +1,124 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: false +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 0 +Cpp11BracedListStyle: false +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: Inner +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: false +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +... diff --git a/.travis.yml b/.travis.yml index e663bb8a..39f86eed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ os: jobs: include: + - os: linux + env: JOB_CHECK_FORMAT=1 - os: linux env: JOB_ARCHITECTURE=arm - os: linux diff --git a/check-format.sh b/check-format.sh new file mode 100755 index 00000000..9bfb41a9 --- /dev/null +++ b/check-format.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Run git-clang-format to check for violations +CLANG_FORMAT_OUTPUT=$(git-clang-format --diff origin/master --extensions c,cpp,h,hpp) + +# Check for no-ops +grep '^no modified files to format$' <<<"$CLANG_FORMAT_OUTPUT" && exit 0 +grep '^clang-format did not modify any files$' <<<"$CLANG_FORMAT_OUTPUT" && exit 0 + +# Dump formatting diff and signal failure +echo -e "\n==== FORMATTING VIOLATIONS DETECTED ====\n" +echo "$CLANG_FORMAT_OUTPUT" +exit 1 diff --git a/clean_tests.py b/clean_tests.py deleted file mode 100755 index 4ee0294f..00000000 --- a/clean_tests.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/python - -import sys, os, re -from subprocess import Popen, PIPE -from optparse import OptionParser - -# trail_spaces: This method removes the trailing whitespaces and trailing tabs -def trail_spaces(line): - newline=line - carreturn = 0 - if re.search("\r\n",line): - carreturn = 1 - status = re.search("\s+$",line) - if status: - if carreturn: - newline = re.sub("\s+$","\r\n",line) - else: - newline = re.sub("\s+$","\n",line) - - status = re.search("\t+$",newline) - if status: - newline = re.sub("\t+$","",newline) - return newline - -#convert_tabs: This methos converts tabs to 4 spaces -def convert_tabs(line): - newline=line - status = re.search("\t",line) - if status: - newline = re.sub("\t"," ",line) - return newline - -#convert_lineends: This method converts lineendings from DOS to Unix -def convert_lineends(line): - newline=line - status = re.search("\r\n",line) - if status: - newline = re.sub("\r\n","\n",line) - return newline - -#processfile: This method processes each file passed to it depending -# on the flags passed - -def processfile(file,tabs, lineends,trails,verbose): - processed_data = [] - if verbose: - print "processing file: "+file - - with open(file,'r') as fr: - data = fr.readlines() - for line in data: - if tabs: - line = convert_tabs(line) - if lineends: - line = convert_lineends(line) - if trails: - line = trail_spaces(line) - processed_data.append(line) - - with open(file,'w') as fw: - fw.writelines(processed_data) - -#findfiles: This method finds all the code files present in current -# directory and subdirectories. - -def findfiles(tabs,lineends,trails,verbose): - testfiles = [] - for root, dirs, files in os.walk("./"): - for file in files: - for extn in ('.c','.cpp','.h','.hpp'): - if file.endswith(extn): - testfiles.append(os.path.join(root, file)) - for file in testfiles: - processfile(file,tabs,lineends,trails,verbose) - -# Main function - -def main(): - - parser = OptionParser() - parser.add_option("--notabs", dest="tabs", action="store_false", default=True, help="Disable converting tabs to 4 spaces.") - parser.add_option("--notrails", dest="trails", action="store_false", default=True, help="Disable removing trailing whitespaces and trailing tabs.") - parser.add_option("--nolineends", dest="lineends", action="store_false", default=True, help=" Disable converting line endings to Unix from DOS.") - parser.add_option("--verbose", dest="verbose", action="store_true", default=False, help="Prints out the files being processed.") - parser.add_option("--git", dest="SHA1", default="", help="Processes only the files present in the particular commit.") - parser.add_option('-o', action="store", default=True, help="Default: All the code files (.c,.cpp,.h,.hpp) in the current directory and subdirectories will be processed") - - (options, args) = parser.parse_args() - - if options.SHA1: - pl = Popen(["git","show", "--pretty=format:", "--name-only",options.SHA1], stdout=PIPE) - cmdout = pl.communicate()[0] - gitout=cmdout.split("\n") - for file in gitout: - print file - if file: - processfile(file,options.tabs,options.lineends,options.trails,options.verbose) - - - if not options.SHA1: - findfiles(options.tabs,options.lineends,options.trails,options.verbose) - -# start the process by calling main -main() diff --git a/travis.sh b/travis.sh index 3c691d8a..c7ad707a 100755 --- a/travis.sh +++ b/travis.sh @@ -4,6 +4,11 @@ set -e export TOP=$(pwd) +if [ "${JOB_CHECK_FORMAT}" -eq 1 ]; then + ./check-format.sh + exit $? +fi + TOOLCHAIN_URL_arm="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz" TOOLCHAIN_URL_aarch64="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz"