7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

あなたの.clang-format、どのスタイルに近い?

Last updated at Posted at 2022-08-02

はじめに

.clang-formatを長く使って育てていると、古くなってしまっている部分もあるかもしれません。最新版のテンプレートとの差分を確認して、自分が変更した点を取捨選択したい、ということはありませんか?

どのスタイルに近くて、どこを変更したかをあぶり出す、という作業を今回してみましたので記事に残しておきます。

clang-formatに付属のテンプレート

現在clang-format(version 14.0.6)には、以下の7つのスタイルテンプレートが標準で付属しています。

近いテンプレートをdiff行数で比較

自分のスタイルがどのテンプレートに近いか、次のようにコンフィグのdiff行数を距離とすることで簡易的に得ることができます。

clang-format --version

cd ".clang-formatのある場所"
mkdir tmp
clang-format --dump-config --style=file > tmp/clang-format.conf
for i in LLVM GNU Google Chromium Microsoft Mozilla WebKit; do
  clang-format --dump-config --style=$i > tmp/clang-format-$i.conf
  diff -uBb tmp/clang-format-$i.conf tmp/clang-format.conf > tmp/$i.diff
done
wc -l tmp/*.diff | sort -n

スクリプトでは、利用中のclang-format--dump-config --style=fileして得られた現バージョンでのコンフィグと、--dump-config --style=***して得られた現バージョンでのコンフィグテンプレートを比較しています。数字が小さいスタイルがあなたのスタイルに近いスタイルです。

私の場合、Mozillaに近いことがわかりました。

clang-format version 14.0.6
 125 tmp/Mozilla.diff
 138 tmp/LLVM.diff
 143 tmp/Microsoft.diff
 161 tmp/WebKit.diff
 185 tmp/GNU.diff
 214 tmp/Chromium.diff
 223 tmp/Google.diff
1189 total

以降、今回やってわかった私の.clang-formatについて紹介します。

私の.clang-formatこだわりポイント

  1. 私は、ほとんどの設定はMozillaに従っています。
  2. Mozillaよりもコード行数を減らしたいため、次の3点を変更しています。
    • 括弧の位置
    • メソッド呼び出し
    • メソッド宣言・定義
  3. またエディタ(Xcode)の自動補正とコンフリクトしないように、インデント調整しています。

具体的な設定

私が利用している.clang-format (この行をクリック)
---
Language:        Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands:   Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
  - __capability
BinPackArguments: true
BinPackParameters: false
BraceWrapping:
  AfterCaseLabel:  false
  AfterClass:      true
  AfterControlStatement: Never
  AfterEnum:       false
  AfterFunction:   true
  AfterNamespace:  true
  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
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Linux
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     85
CommentPragmas:  '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat:   false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: NextLine
BasedOnStyle:    ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IfMacros:
  - KJ_IF_MAYBE
IncludeBlocks:   Preserve
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '.*'
    Priority:        1
    SortPriority:    0
    CaseSensitive:   false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: true
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires:  false
IndentWidth:     4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 0
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth:   -1
ReferenceAlignment: Pointer
ReflowComments:  true
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes:    CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
  AfterControlStatements: true
  AfterForeachMacros: true
  AfterFunctionDefinitionName: false
  AfterFunctionDeclarationName: false
  AfterIfMacros:   true
  AfterOverloadedOperator: false
  BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
  Minimum:         1
  Maximum:         -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard:        Latest
StatementAttributeLikeMacros:
  - Q_EMIT
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
TabWidth:        4
UseCRLF:         false
UseTab:          Always
WhitespaceSensitiveMacros:
  - STRINGIZE
  - PP_STRINGIZE
  - BOOST_PP_STRINGIZE
  - NS_SWIFT_NAME
  - CF_SWIFT_NAME
...

こだわり点ピックアップ

  • 基本はMozillaを利用★

  • インデント

    • エディタとの調整

      IndentWidth:     4		# mozilla: 2
      TabWidth:        4		# mozilla: 8
      UseTab:          Always		# mozilla: Never
      ColumnLimit:     85		# mozilla: 80
      ConstructorInitializerIndentWidth: 4		# mozilla: 2
      ContinuationIndentWidth: 8		# mozilla: 2
      AccessModifierOffset: -4		# mozilla: -2
      
  • 括弧の位置

    • 括弧前後の改行はLinuxスタイルを利用しています。

      BreakBeforeBraces: Linux		# mozilla: Mozilla
      

      すなわち、下記がMozillaと比べて変更になっています。

      BraceWrapping:
        AfterEnum:       false		# mozilla: true
        AfterNamespace:  true		# mozilla: false
        AfterStruct:     false		# mozilla: true
        AfterUnion:      false		# mozilla: true
        AfterExternBlock: false		# mozilla: true
        SplitEmptyRecord: true		# mozilla: false
      
  • メソッド呼び出し

    • 引数が長く、改行する場合でも、各行にそれぞれ入るだけ複数の引数を書くようにしています。

      BinPackArguments: true		# mozilla: false
      
  • メソッド宣言・定義

    • 返り値型と関数名は1行に書く。

      AlwaysBreakAfterDefinitionReturnType: None		# mozilla: TopLevel
      AlwaysBreakAfterReturnType: None		# mozilla: TopLevel
      
    • ただし関数名(+引数など)が長いなら、躊躇せず返り値型を切り離す。

      PenaltyReturnTypeOnItsOwnLine: 0		# mozilla: 200
      
    • 複数の親から継承しても、短いなら1行で継承を記述するようにする。

      BreakInheritanceList: BeforeColon		# mozilla: BeforeComma
      
    • 同様にコンストラクタ初期化子も短いなら1行で。ただし初期化子が長い場合は、変数ごとに個別に改行する。

      BreakConstructorInitializers: BeforeColon		# mozilla: BeforeComma
      PackConstructorInitializers: NextLine		# mozilla: BinPack
      
    • 超短い関数の内容定義は、関数名と同じ行で1行で済ませる。

      AllowShortFunctionsOnASingleLine: All		# mozilla: Inline
      
  • その他

    • Namespaceを閉じるときのコメントは、常に正しくなるようにする。

      FixNamespaceComments: true		# mozilla: false
      

以上です。

補足

clang-formatのコンフィグの記述は、clang-formatがバージョンアップするとよく変化しているようです。下位互換を保っているようで気づくことは普通はありませんが、いつ切り捨てられるかわかりません。ときどきは新しい記述にアップデートした方が良さそうです。
この方法で新しい記述に変換できますのでときどき実行してみることをおすすめします。

cd ".clang-formatのある場所"
clang-format --dump-config --style=file > .clang-format

これで長く安心して使い続けられますね。

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?