Qt WidgetsプロジェクトでVisual Studio Codeのclangdの補完機能を有効にする方法

# 概要

Qt Creatorで作成したQt WidgetsプロジェクトをVisual Studio Codeで開いたときに[clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd)の補完機能を有効にするための設定方法を備忘録として書き残しておきます。

以下で説明する設定を行うことで、下の画像のようにVisual Studio Codeからclangdの補完機能を呼び出せるようになります。

![2023-01-29_15-31-36_00_modified.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/54c12e3b-2806-42f7-1b50-ade32b8388c0.png)

リポジトリ例はGitHubにも上げてあるので、併せて参照してください。
https://github.com/ishioka0222/qt-vscode-clangd

# 動作を確認した環境

- Windows 11 Home 22H2
- Visual Studio Code v1.74.3
- [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) v0.1.23
- Qt 6.4.2

# clangdの補完機能を有効にする方法

QtやVisual Studio Code、clangdの拡張機能のインストールは済んでいるものとします。

1. Qt Creatorからウィザードに従ってQt Widgetsプロジェクトを作成します（Qt Quickでも動くかもしれませんが、確認していません）。
1. プロジェクトが作成されたら、プロジェクトディレクトリをVisual Studio Codeで開きます。
    この段階では、clangdはQt関連のヘッダファイルを認識していません。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/6975d362-b4de-c263-2249-a0920ffc310b.png)

1. clangdのインクルードディレクトリの設定を行います。
    プロジェクトのルートディレクトリに`.clangd`というファイル名でclangdの設定ファイルを作成します。
    ファイルの中身は以下のようにします（`--include-directory`の行は、各自でQtをインストールしたディレクトリに読み替えてください）。
    ```:.clangd
    CompileFlags:
      Add: 
        - "-std=c++17"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtGui"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtCore"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtWidgets"
    ```
    現在のQtはデフォルトでC++17を使用しているらしく、`-std=c++17`の指定がないとエラーが出ます。
    QtSqlなど、Qtから提供されている追加のモジュールを使用している場合は、`- "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtSql"`のように行を追加する必要があります。

    この設定ファイルの詳細については以下のclangdの公式ドキュメントを参照してください。
    https://clangd.llvm.org/config
    `--include-directory`などのオプションの詳細については以下のclangの公式ドキュメントを参照してください。
    https://clang.llvm.org/docs/ClangCommandLineReference.html

    `.clangd`ファイルを作成した状態のフォルダ構成は下の画像のようになります。
    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/55c37fff-3020-cf15-8c7d-84eab4842f30.png)

1. Visual Studio Codeのclangdの拡張機能ではデフォルトでは`.clangd`の設定ファイルは読み込まれない設定になっているようなので、`.clangd`を読み込むための設定を行います。
    まず、Visual Studio Codeの設定画面を開きます。
    設定はUser設定でもWorkspace設定でもどちらでも問題ないと思いますが、ここではWorkspace設定を選択した場合の説明を行います。
    `Workspace`のタブをクリックし、`clangd.arguments`で検索すると`Clangd: Arguments`という設定項目が出てきます。
    `Add Item`をクリックして、`--enable-config`と入力して、OKを押します。
    設定が完了したら以下の画像のような状態になります。
    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/b16d9249-29c3-d904-be1b-fa64ad83877f.png)

1. clangdの設定はlanguage serverを再起動させないと反映されないため、Visual Studio Codeのコマンドパレットから`clangd: Restart language server`を実行します。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/30cb0e3d-3d59-a8de-f5e8-020cb5b8f452.png)

1. すると、Visual Studio Codeの右下に設定を読み込むか確認するダイアログが出てくるので、`Yes, use this setting`をクリックします。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/9a98a038-3efb-bd0e-a506-27d48c1ac16f.png)

1. これでclangdがQtのインクルードディレクトリを認識し、最初に出ていたようなエラーは出なくなります。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/14ed9e7f-6b37-46a4-d6c8-737c9f88aa7b.png)

    補完機能も動作していることが分かります。

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/2a6d1f53-e646-483a-20d7-43b538ab5760.png)

    （ちなみに、この記事を執筆中、clangdのlanguage serverを再起動させるところで、たまにエラーになることがありました。その場合は何度かVisual Studio Codeを再起動させたら治りましたが、原因は不明です……。）
    
# 補足

Qtのフォームのデザインを`.ui`ファイルで編集している場合、clangdが`.ui`ファイルから生成されたヘッダーファイルを認識せず、その部分だけ以下のようなエラーが出ます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/39cd0c43-f1d6-eb1d-7863-8a1961ecd495.png)

これを回避するには、以下のようにします。

1. `.ui`ファイルをQt Creatorで編集したらビルドを行い、`.ui`ファイルに対応するヘッダーファイルを生成する。
1. プロジェクトのルートディレクトリと同じ階層に`build-qt-vscode-clangd-Desktop_Qt_6_4_2_MSVC2019_64bit-Debug`のような名前のビルドディレクトリが生成されていることを確認する。
1. `.clangd`に、上で確認したビルドディレクトリをインクルードする設定を追加する。
    具体的には以下のようにすればOKです（ディレクトリは各自で読み替えてください）。
    ```
    CompileFlags:
      Add: 
        - "-std=c++17"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtGui"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtCore"
        - "--include-directory=C:\\Qt\\6.4.2\\msvc2019_64\\include\\QtWidgets"
        - "--include-directory=C:\\Users\\hiroki\\source\\repos\\build-qt-vscode-clangd-Desktop_Qt_6_4_2_MSVC2019_64bit-Debug"
    ```

1. これで`ui_mainwindow.h`のような`.ui`ファイルから生成されるファイルのインクルードによるエラーも消えます。