📄

Инструменты разработчика С++/ Qt. Clang-Tidy, Clang-Format в VSCode

04.10.2025 CXX

В продолжение темы настройки IDE из статьи про Qt6, мы углубимся в инструменты, которые превращают хорошего разработчика в отличного. Речь идет о внедрении практик, которые делают код не просто рабочим, но и качественнымединообразным и безопасным на этапе его написания, а не после появления ошибок.

Два ключевых инструмента в арсенале C++-разработчика — это clang-format и clang-tidy.

  • clang-format — это «автоисправление» для стиля кода. Он автоматически приводит ваш код к единому стандарту оформления: отступы, пробелы, переносы строк, выравнивание. Это решает все споры о том, где ставить фигурную скобку, раз и навсегда.
  • clang-tidy — это статический анализатор, линтер. Он не просто смотрит на внешний вид, а анализирует логику кода. Он находит потенциальные баги, уязвимости, «запахи кода» (code smells) и предлагает современные идиомы (вплоть до C++20), предлагая автоматический рефакторинг (fix-it hints).

Интеграция этих инструментов в VSCode позволяет проводить «чистку» кода в реальном времени, превращая разработку в непрерывный процесс рефакторинга и улучшения.

Настройка clang-format для единого стиля кода

1. Установка и создание конфигурационного файла

Убедитесь, что у вас установлен LLVM/Clang (вместе с Qt6 часто поставляется через Mingw или как отдельный пакет). Создайте в корне вашего проекта файл .clang-format.

Этот файл определяет все правила форматирования. Вот пример конфигурации, хорошо подходящий для современных C++ и Qt6 проектов.

# .clang-format
---
Language: Cpp
# Базовый стиль. LLVM - хороший, строгий стандарт.
BasedOnStyle: LLVM

# Настройки, специфичные для C++
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: true
ColumnLimit: 120
CompactNamespaces: false
Cpp11BracedListStyle: true
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeBlocks: Regroup
IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never

Ключевые моменты для Qt и C++17:

  • BasedOnStyle: LLVM: Четкий и распространенный стандарт.
  • PointerAlignment: Left: Стиль, привычный для C и C++ (int *ptr).
  • AllowShortLambdasOnASingleLine: All: Короткие лямбды в одну строку — обычное дело в современном C++.
  • SortIncludes: true и SortUsingDeclarations: true: Автоматическая сортировка инклюдов и using-объявлений для порядка.
  • ColumnLimit: 120: Более широкая строка, чем стандартные 80, что удобно при работе с современными мониторами.
  • UseTab: Never и IndentWidth: 4: Использование пробелов для отступов — гарантия одинакового отображения кода everywhere.

2. Интеграция в VSCode

Установите официальное расширение ms-vscode.cpptools.

Затем откройте настройки VSCode (Ctrl + ,) и найдите следующие параметры:

  • C_Cpp > Formatting: Убедитесь, что оно включено.
  • C_Cpp > Code Style: Выберите clangFormat.
  • Editor: Format On Save: Отметьте галочку. Это ключевая настройка! Теперь при каждом сохранении файла (Ctrl + S) он будет автоматически форматироваться согласно вашему .clang-format.

Чтобы проверить, что все работает, откройте любой .cpp файл, намеренно нарушите форматирование (уберите отступы, нагородите пробелов) и сохраните. Код должен мгновенно прийти в должный вид.

Настройка clang-tidy для статического анализа и рефакторинга

1. Создание конфигурационного файла .clang-tidy

Создайте в корне проекта файл .clang-tidy. Этот файл определяет, какие именно проверки будет выполнять линтер.

Вот пример конфигурации, ориентированный на C++17 и лучшие практики, с акцентом на поиск потенциальных проблем.

# .clang-tidy
---
Checks: >
    -*,
    clang-analyzer-*,
    bugprone-*,
    performance-*,
    modernize-*,
    readability-*,
    portability-*,
    -bugprone-macro-parentheses, # Часто ложные срабатывания в коде с макросами
    -modernize-use-trailing-return-type, # Не всем нравится trailing return type
    -modernize-avoid-c-arrays,           # Может конфликтовать с некоторыми C-API
    -readability-identifier-length,      # Слишком строго для legacy-кода
    -readability-magic-numbers           # Полезно, но может быть шумно

WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: file
CheckOptions:
  - key: modernize-use-nodiscard.CheckThrowTypes
    value: '0'
  - key: modernize-use-using.CheckTrivialTypeAlias
    value: '0'
  - key: modernize-loop-convert.MaxCopySize
    value: '16'
  - key: modernize-use-emplace.IgnoreImplicitConstructors
    value: '0'
  - key: modernize-use-default-member-init.IgnoreMacros
    value: '1'

# Явно включаем стандарт C++17 и ключевые макросы Qt
CheckOptions:
  - key: modernize-use-trailing-return-type.Value
    value: 'false'
  - key: readability-identifier-naming.ClassCase
    value: CamelCase
  - key: readability-identifier-naming.VariableCase
    value: lower_case
  - key: modernize-use-using.IgnoreMacros
    value: '1'

Пояснение к ключевым группам проверок:

  • clang-analyzer-*: Проверки на сложные ошибки времени выполнения (разыменование nullptr, утечки памяти).
  • bugprone-*: Поиск распространенных ошибок программирования.
  • performance-*: Проверки, замедляющие выполнение кода (неоптимальные аллокации, копирования).
  • modernize-*: *Самая важная группа для перехода на C++17!* Предлагает заменить старые конструкции на современные (autonullptr, range-based for loops, overrideusing вместо typedef и т.д.).
  • readability-*: Улучшает читаемость кода.

2. Интеграция в VSCode

Расширение ms-vscode.cpptools также поддерживает clang-tidy. В настройках VSCode найдите:

  • C_Cpp > Code Analysis > Clang Tidy > Enabled: Включите.
  • C_Cpp > Code Analysis > Clang Tidy > Checks: Оставьте пустым. VSCode будет автоматически использовать файл .clang-tidy из корня проекта. Если файла нет, можно указать checks здесь, например ["modernize-*", "readability-*"].
  • C_Cpp > Code Analysis > Clang Tidy > Header Filter: Можно оставить пустым или указать пути к заголовочным файлам вашего проекта (например, ["include/**/*.h", "src/**/*.h"]).

После сохранения настроек, откройте файл с кодом. Вы сразу увидите подчеркивания — предупреждения и ошибки от clang-tidy.

3. Примеры полезных проверок clang-tidy для C++17 и Qt6

  1. modernize-use-auto
    • Было: std::vector<QString>::iterator it = vec.begin();
    • Стало: auto it = vec.begin();
    • Эффект: Более короткий и типобезопасный код.
  2. modernize-use-nullptr
    • Было: QWidget *parent = 0;
    • Стало: QWidget *parent = nullptr;
    • Эффект: Явное указание на нулевой указатель, а не на целое число.
  3. modernize-use-override
    • Было:
class MyButton : public QPushButton {
public:
    void paintEvent(QPaintEvent *e); // Хочу переопределить
};
  • Стало
class MyButton : public QPushButton {
public:
    void paintEvent(QPaintEvent *e) override;
};
  1. readability-qualified-auto
    • Было: auto *item = new QListWidgetItem; (у item будет тип QListWidgetItem*, но без квалификаторов).
    • Рекомендация: Заставляет задуматься о константности. const auto *item = ....
    • Эффект: Помогает избежать случайного изменения объектов, которые не должны изменяться.
  2. performance-for-range-copy
    • Было: for (auto item : bigVector) { ... } // Создается дорогая копия!
    • Стало: for (const auto &item : bigVector) { ... }
    • Эффект: Значительное ускорение при работе с контейнерами тяжелых объектов (например, QStringQList<MyBigData>).

Работа с предупреждениями:
Наведите курсор на подчеркнутую проблему, чтобы увидеть подробное описание. Часто clang-tidy предлагает «Quick Fix» (лампочка слева от кода). Нажав на нее, вы можете применить рефакторинг автоматически.

Заключение

Комбинация clang-format и clang-tidy, глубоко интегрированная в VSCode, — это мощнейший буст для продуктивности и качества кода.

  • clang-format избавляет вас от рутины и споров о стиле, делая код аккуратным и единообразным.
  • clang-tidy выступает в роли вашего личного опытного наставника, который в реальном времени указывает на слабые места, учит использовать современные возможности C++17 и предотвращает ошибки до этапа компиляции и тестирования.

Потратив менее часа на первоначальную настройку, вы создаете для себя и своей команды среду, которая непрерывно и ненавязчиво подталкивает к написанию не просто рабочего, но и хорошего кода. Это долгосрочная инвестиция в стабильность, поддерживаемость и эволюцию вашего C++/Qt6 проекта.