BloGroonga

2023-02-28

グルカイ!第27回「コードフォーマッター clang-formatについて」を開催しました!

グルカイ!第27回「コードフォーマッター clang-formatについて」の内容をまとめました! 今回はコードフォーマッターの一つであるclang-formatについて解説していただきました。

解説の図はこちらです。

背景

現在Groongaでは基本的に手動でコードをフォーマットしています。 EditorConfigを使って最低限の自動化はされていますが、多くの部分を手作業でフォーマットしています。

そのため、コードのフォーマットに時間がかかったり、レビューの際にレビュワーが細かくフォーマットの確認をせねばならず、非効率な状態となっています。

この問題を解消するため、新たなコードフォーマッターの導入を検討しています。

clang-format

clang-formatはコードフォーマッターの一つです。

LLVM C CompilerのコンパイラフロントエンドであるClangをベースにしています。 そのため、フォーマットするための構文解析もClangと同じようにしてくれるという利点があります。

構成

Language Server Protocol(LSP)にしたがっています。

LSPのモデルでは、言語支援のAPIを提供するLanguage Serverと、Language Serverに問い合わせしたり、その結果を表示するUIに分かれています。 実際の言語支援機能をLanguage Serverに集約することにより、UI側はLSPをサポートするだけで集約済みの言語支援機能を利用できます。 例えば、Visual Studio、Visual Studio Code、Emacs、VimといったエディターがLSPをサポートしており、UIとして使用可能です。

clang-formatの場合は、Language ServerはClangdです。

フォーマット確認自動化

clang-formatは入力ファイルをフォーマットした結果をファイルとして出力します。 そのため、入力ファイルと出力ファイルを比較し、差分の有無を確認することでフォーマッターの定義にしたがっているかどうかの確認を自動化できます。

lint機能がある場合には、実際にファイルを出力しなくても、定義にしたがっていないかどうかだけ判定することができます。 しかし、clang-formatにはlint機能はないので、上記のようにファイルを出力して比較する必要があります。

compile_commands.json

clang-formatが上手く解析できるようにするためには、 compile_commands.json というファイルが必要になります。 compile_commands.json はソースコードをコンパイルする際のコンパイルオプションをClangdに伝えるためのファイルです。

例えば、 #include <groonga.h> といったインクルードするファイルがどこにあるのか、といった情報が compile_commands.json に入ります。 compile_commands.json、CMakeのオプションで CMake ... -DCMAKE_EXPORT_COMPILE_COMMANDS=ON とすることで生成できます。

バージョンについて

clang-formatなどのフォーマッターは、バージョンが上がるとルールが追加され、過去のフォーマットルールと差分が生じる場合があります。

最新のバージョンのほうが一般的に好ましいルールになっているはずです。 しかし、常に最新のバージョンを使うという運用ルールにすると、各開発者が常に最新バージョンに保つ手間がかかる、 バージョンが上がるたびに差分が出る可能性があるといった問題が生じます。

これらの問題を回避するため、バージョンを指定しての運用が望ましいです。