diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..a27c42c1 --- /dev/null +++ b/.clang-format @@ -0,0 +1,148 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: WebKit +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: true +FixNamespaceComments: true +ForEachMacros: + - wl_list_for_each + - wl_list_for_each_safe +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Double +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: false +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE +TypenameMacros: + - g_auto + - g_autoptr +... diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml new file mode 100644 index 00000000..1a6e6e0c --- /dev/null +++ b/.github/workflows/codestyle.yml @@ -0,0 +1,31 @@ +--- +name: Code Style +on: [pull_request] + +jobs: + check: + runs-on: ubuntu-20.04 + steps: + - name: Checkout Head + uses: actions/checkout@v2 + - name: Fetch Git History + run: | + git fetch --no-tags --prune --depth=1 \ + origin +refs/heads/master:refs/remotes/origin/master + - name: Install Tools + run: | + curl -sL https://apt.llvm.org/llvm-snapshot.gpg.key | \ + sudo apt-key add - + sudo add-apt-repository \ + 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main' + sudo apt update + sudo apt install -y clang-format-13 diffutils + - name: Check + run: | + scripts/check-style -ocode-style.diff origin/master + - name: Archive Diff + uses: actions/upload-artifact@v2 + if: failure() + with: + name: diff + path: code-style.diff diff --git a/scripts/check-style b/scripts/check-style new file mode 100755 index 00000000..bdfb101c --- /dev/null +++ b/scripts/check-style @@ -0,0 +1,131 @@ +#! /usr/bin/env bash +set -eu -o pipefail + +FILE= +BASE= +HEAD=HEAD + +declare -a args=() +diff_input=false +show_help=false + +for opt in "$@" ; do + case "${opt}" in + -h | --help) + show_help=true + ;; + -d | --diff) + diff_input=true + ;; + -o*) + FILE=${opt#-o} + ;; + *) + args+=("${opt}") + ;; + esac +done +declare -r diff_input show_help + +show_help () +{ + echo "Usage: $0 [-o] [-d|--diff] [ []]" +} + +if ${show_help} ; then + show_help + exit +fi + +if [[ ${#args[@]} -eq 1 ]] ; then + BASE=${args[0]} +elif [[ ${#args[@]} -eq 2 ]] ; then + BASE=${args[0]} + HEAD=${args[1]} +elif [[ ${#args[@]} -eq 0 ]] && ${diff_input} ; then + : no-op +else + show_help 1>&2 + exit 1 +fi +declare -r BASE HEAD + +declare -ra clang_format_diff_candidates=( + # Search in $PATH (Ubuntu, Debian, maybe others) + clang-format-diff-13 + clang-format-diff-13.py + clang-format-diff + clang-format-diff.py + # Arch Linux, Fedora. + /usr/share/clang/clang-format-diff.py +) + +find_program () +{ + local candidate path + for candidate in "$@" ; do + path=$(type -P "${candidate}") + if [[ -x ${path} ]] ; then + echo "${path}" + return + fi + done + + # Not found. + return 1 +} + +clang_format_diff=$(find_program "${clang_format_diff_candidates[@]}") +clang_format=$(find_program clang-format-11 clang-format) +declare -r clang_format_diff clang_format + +if [[ ! -x ${clang_format_diff} ]] ; then + echo "$0: clang-format-diff does not seem to be installed" 1>&2 + exit 1 +fi + +if [[ ! -x ${clang_format} ]] ; then + echo "$0: clang-format does not seem to be installed" 1>&2 + exit 1 +fi + +# +# Check the version of clang-format, to make sure that it will support the +# configuration file. The output of "clang-format --version" is formatted +# as follows: +# +# clang-format version X.Y.Z +# +declare -r clang_format_min_version=11 + +clang_format_version=$("${clang_format}" --version) +if [[ ${clang_format_version} =~ clang-format[[:space:]]+version[[:space:]]+([[:digit:]]+)\. ]] ; then + clang_format_version=${BASH_REMATCH[1]} + if [[ ${clang_format_version} -lt ${clang_format_min_version} ]] ; then + echo "$0: clang-format ${clang_format_min_version}+ is needed, ${clang_format_version} detected" 1>&2 + exit 1 + fi +else + echo "$0: clang-format did not report its version number" + exit 1 +fi + +if [[ -z ${FILE} ]] ; then + FILE=$(mktemp) + trap 'rm -f "${FILE}"' EXIT +else + trap '[[ -s ${FILE} ]] || rm -f "${FILE}"' EXIT +fi + +declare -a input_cmd +if ${diff_input} ; then + input_cmd=(cat) +else + input_cmd=(git diff --no-color -U0 "${BASE}" "${HEAD}") +fi + +"${input_cmd[@]}" \ + | "${clang_format_diff}" -p1 -style=file -regex='.+\.(c|h)' \ + | tee "${FILE}" + +[[ ! -s ${FILE} ]]