Skip to content
Thomas Hahn edited this page Dec 12, 2024 · 5 revisions

Language servers provide language-specific smarts and communicate them to clients (usually IDEs or editors).

Their main task is to perform static code analysis:

  • highlight semantic and stylistic problems in our code
  • help with refactoring, renaming symbols
  • help with formatting
  • code completion
  • enforce good coding practices
  • and more.

There are two widely used C++ language servers for VS Code:

  • Microsoft's C/C++ extension and
  • clangd.

We will focus only on clangd in the following.

Install the extension

To install/enable the extension, follow the same steps as in the previous sections.

clangd_ext

Settings

You can check the available settings for clangd by running >Preferences: Open Settings (UI) and going to the Extensions menu.

The only settings the author uses are

"clangd.path": "/opt/homebrew/opt/llvm/bin/clangd",
"clangd.arguments": [
    "--header-insertion=never"
],

The first one is important. It tells the extension where it can find the clangd executable.

The second one is not essential. It prevents clangd from inserting missing header files.

Get started

The only thing clangd needs is the compile_commands.json file. Since this is already generated automatically by CMake Tools and copied into the source directory, we are good to go without any further work.

Note: Here the CMake Tools setting "cmake.copyCompileCommands": "${sourceDirectory}/compile_commands.json" becomes important!

compilation_database

Some useful features

Hover over symbols

To check that clangd is working as expected, you can go to the source code ./src/linalg.cpp and hover over the symbol nda::matrix. You should see something like

clangd_hover

clangd provides information on symbols when you hover over them. This can especially be helpful if you are not sure of what type a certain variable is.

Go To Definition

Another useful feature is the Go To Definition command.

To test it out,

  • Right click on the matrix part of nda::matrix
  • Click Go To Definition

This will bring you to the source code line, where nda::matrix is defined:

clangd_go_to_def

As you can see, clangd is even aware of the contents of external libraries as long as they are properly linked and included in the project (for our toy repository, it is enough to use target_link_libraries in the ./src/CMakeLists.txt file).

Rename Symbol

Another powerful tool is Rename Symbol.

Suppose we want to rename the library function print_lib_info to print_info:

  • Go to ./include/linalg/linalg.hpp
  • Right click on print_lib_info and select Rename Symbol
  • Type print_info in the pop up window and press Cmd+Enter to see the preview

The Refactor Preview lists all the changes it will make. If we click on one of them, it will show us a diff:

clangd_refactor_preview

For educational purposes, let's uncheck the first box (ex1.cpp) and click Apply.

clangd immediately recognizes that something is not right with our code. The file ./examples/ex1.cpp is marked in red and opening it shows red error wiggles underneath the print_lib_info() call. To get more information, hover over it:

clangd_error_wiggles

It tells us that print_lib_info does not exist and it even suggests the correct fix for this problem. You can either manually type the correct function call or apply the suggested Quick Fix from the pop up window.

clang-format

clangd uses the clang-format engine to format a file or a selection according to some rules. The rules are specified in the ./.clang-format file in the source directory.

To format a file, simply right click anywhere in the file and select Format Document. For example

  • Before formatting:
clangd_before_format
  • After formatting:
clangd_after_format

clang-tidy

clangd can also use the linter clang-tidy to point out typical programming errors and bad coding practices. The checks that clang-tidy performs are specified in the ./.clang-tidy file in the source directory.

For example, declaring a C-style array will result in the following warning:

clangd_tidy