From a3db96eabae027f8cd17569b3a89e10b683e99ce Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 00:18:49 +0500 Subject: [PATCH 1/6] Enforce coding style using clang-tidy --- .clang-tidy | 49 +++ .github/workflows/linter.yml | 46 +++ _clang-format | 15 +- .../code/development-guidelines.rst | 334 +++++++++++++++--- scripts/_clang-format | 19 +- scripts/clang-tidy.py | 63 ++++ 6 files changed, 466 insertions(+), 60 deletions(-) create mode 100644 .clang-tidy create mode 100644 scripts/clang-tidy.py diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000000..c164d85f1b --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,49 @@ +--- +Checks: > + -*, + cppcoreguidelines-non-private-member-variables-in-classes, + cppcoreguidelines-prefer-member-initializer, + cppcoreguidelines-pro-type-cstyle-cast, + misc-const-correctness, + misc-unused-parameters, + modernize-loop-convert, + modernize-use-auto, + modernize-use-nullptr, + readability-magic-numbers + readability-braces-around-statements, + readability-identifier-naming, + readability-make-member-function-const, + performance-for-range-copy, + performance-enum-size, + performance-move-const-arg, + performance-no-automatic-move, + performance-noexcept-destructor, + performance-noexcept-move-constructor, + performance-noexcept-swap, + performance-unnecessary-copy-initialization, + performance-unnecessary-value-param, + performance-use-std-move, + performance-move-constructor-init, +HeaderFilterRegex: 'src/.*' +WarningsAsErrors: '*' +CheckOptions: + - key: readability-identifier-naming.VariableCase + value: camelBack + - key: readability-identifier-naming.FunctionCase + value: camelBack + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.MemberCase + value: camelBack + - key: misc-const-correctness.TransformValues + value: 'true' + # required because using "-fix" puts "const" after the typename instead of before + - key: misc-const-correctness.TransformValues + value: 'false' + - key: misc-const-correctness.TransformReferences + value: 'false' + - key: misc-const-correctness.TransformPointersAsValues + value: 'false' + - key: misc-const-correctness.TransformPointersAsPointers + value: 'false' +... diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 39171b890f..3307b70cd3 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -57,3 +57,49 @@ jobs: sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-16 160 clang-format --version python scripts/clang-format.py --check --verbose + + clang-tidy: + needs: changes + # if: ${{ needs.changes.outputs.code == 'true' }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Build Dependencies + run: | + sudo apt update + sudo apt install -y \ + build-essential cmake ninja-build meson \ + qt6-base-dev qt6-tools-dev \ + qt6-tools-dev-tools libqt6svg6-dev libqt6core5compat6-dev \ + libqt6svgwidgets6 qt6-l10n-tools \ + libgl1-mesa-dev libglu1-mesa-dev + + - name: Install automatic LLVM 16 + run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 16 + + - name: Install clang-tidy-16 + run: | + sudo apt --assume-yes install clang-tidy-16 + + - name: CMake Configuration + run: | + cmake -S . -B build \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCUTTER_QT=6 \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + + - name: Run autogen + run: | + cmake --build build --target Cutter_autogen + + - name: Run Clang-Tidy + run: | + sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-16 160 + sudo update-alternatives --install /usr/bin/run-clang-tidy run-clang-tidy /usr/bin/run-clang-tidy-16 160 + clang-tidy -version + python3 scripts/clang-tidy.py diff --git a/_clang-format b/_clang-format index 67f84f00ea..3dc95d39a4 100644 --- a/_clang-format +++ b/_clang-format @@ -1,6 +1,6 @@ # Do not edit this file! Automatically generated using scripts/udate_clang_format.sh and scripts/_clang_format # See update_clang_format.sh for more information. -# generated using clang-format version 8.0.0-3~ubuntu16.04.1 (tags/RELEASE_800/final) +# generated using clang-format version 8.0.1 --- Language: Cpp AccessModifierOffset: -4 @@ -67,14 +67,14 @@ ForEachMacros: - QBENCHMARK - QBENCHMARK_ONCE - CutterRzListForeach -IncludeBlocks: Preserve +IncludeBlocks: Regroup IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + - Regex: '^"([^"]*)"' + Priority: 1 + - Regex: '^<[Qq]' Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - Regex: '.*' - Priority: 1 + Priority: 3 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false IndentPPDirectives: AfterHash @@ -101,7 +101,7 @@ PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: true -SortIncludes: false +SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false @@ -125,3 +125,4 @@ StatementMacros: TabWidth: 8 UseTab: Never ... + diff --git a/docs/source/contributing/code/development-guidelines.rst b/docs/source/contributing/code/development-guidelines.rst index 8d17a56f9a..b938285959 100644 --- a/docs/source/contributing/code/development-guidelines.rst +++ b/docs/source/contributing/code/development-guidelines.rst @@ -60,78 +60,207 @@ to the style is: clang-format -style=file -i src/filename.cpp -If your changes were done on many files across the codebase, you can use this oneliner to tun ``clang-format`` on the entire 'src' directory: +If your changes were done on many files across the codebase, you can use this oneliner to run ``clang-format`` on the entire 'src' directory: .. code:: bash find ./src -regex '.*\.\(cpp\|h\)' -exec clang-format -style=file -i {} \; -In contrast to the official guidelines of Qt, in Cutter we always use curly braces in conditional statements, even if the body of a conditional statement contains only one line. +Beyond formatting, we use `clang-tidy `__ (version 13 or newer) to catch potential style violations. + +To run ``clang-tidy``, first configure your build to generate ``compile_commands.json`` and run the autogen tools: + +.. code:: bash + + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCUTTER_QT=6 -DCUTTER_USE_BUNDLED_RIZIN=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + + cmake --build build --target Cutter_autogen + +Run ``clang-tidy`` on modified files relative to the latest commit + +.. code:: bash + + git diff -U0 --no-color HEAD~1 | clang-tidy-diff.py -p1 -path build/ + +Similar to ``clang-format``, If your changes were done on many files across the codebase, you can use this oneliner to run ``clang-tidy`` on the entire 'src' directory. The following command excludes third-party and auto generated files: + +.. code:: bash + + run-clang-tidy -p build "src/(?!(themes|bindings|fonts|img|translations|build|.*_autogen)).*\.(cpp|h)$" + +``clang-tidy`` can also attempt to fix style violations using the ``-fix`` flag, however these may not always be perfect. Make sure to verify the fixes before opening a pull request: + +.. code:: bash + + git diff -U0 --no-color HEAD~1 | clang-tidy-diff.py -fix -p1 -path build/ + + +Below are some of the low level coding conventions that we follow + +Variables +~~~~~~~~~ + +Variable names start with a lowercase letter with each consecutive word starting with an uppercase letter. (**camelBack** case) .. code:: cpp - // Wrong - if (address.isEmpty()) - return false; - - // Correct - if (address.isEmpty()) { - return false; - } - - // Wrong - for (int i = 0; i < 10; ++i) - qDebug("%i", i); + int Height // Wrong + string name_of_widget // Wrong + + int height; // Correct + string nameOfWidget // Correct + +Avoid meaningless variable names + +.. code:: cpp + + int a, b; // Wrong + string c; // Wrong + + int height, width; // Correct + string nameOfThis; // Correct + Object obj; // Also Correct + +Only first letter of an acronym is uppercase + +.. code:: cpp + + CutterJsonWigdet cutterJSONWidget; // Wrong + + CutterJsonWigdet cutterJsonWigdet; // Correct + +Variable names don't use leading/trailing underscores, including prefixes like m\_ + +.. code:: cpp + + class Example { + private: + int index_; // Wrong + int m_index; // Wrong + + int index; // Correct + }; + +Global variables follow the same naming conventions + +Anonymous Namespace +~~~~~~~~~~~~~~~~~~~ + +Global entities (variables, functions, structs...) private to a source file (internal linkage) are defined in an anonymous namespace + +.. code:: cpp + + namespace { + int globalCounter = 0; + + bool doSomething() { + ... + return true; + } + }; + +Functions +~~~~~~~~~ + +Function names follow the same naming convention as `variables`_. (**camelBack** casing) + +.. code:: cpp + + void do_something() {} // Wrong + + void DoSomething() {} // Wrong + + void doSomething() {} // Correct + +Unused parameters inside a function are omitted in the definition either by commenting out the parameter name or not writing the name at all. + +Avoid using ``Q_UNUSED`` + +.. code:: cpp - // Correct - for (int i = 0; i < 10; ++i) { - qDebug("%i", i); - } + // Bad + void doSomething(int one, int two) { + Q_UNUSED(one) + ... + } + // Good + void doSomething(int /*one*/, int two) { + ... + } -Includes + // Good + void doSomething(int, int two) { + ... + } + +Avoid the use of automatic name based connections. See `Connecting Qt Signals`_. + +Classes ~~~~~~~~ -Strive to include only **required** definitions inside header files. -This will avoid triggering additional unnecessary compilations. +First letter of each word is uppercased. (**CamelCase**) -If you only need to know that a class exists but don't need the prototype, -you can declare the class like this: +.. code:: cpp + + class memory_dock_widget; // Wrong + class memoryDockWidget; // Wrong + + class MemoryDockWidget; // Correct + +Only first letter of an acronym is uppercase .. code:: cpp - class MyClassThatExists; + class CutterJSONWidget // Wrong - /** ... **/ + class CutterJsonWidget // Correct - private: - MyClassThatExists *classInstance; -And then include the class header inside your .cpp so you can use that class. +Member variables follow the same naming conventions defined in `variables`_ that means no leading/trailing underscores or m\_ prefixes -If you need something in the source file (.cpp) that is not a class member, -then add the include in the source file. +Casting +~~~~~~~ -The includes must be ordered from local to global. That is, first include -any local header file (with double quotes like `#include "common/Helpers.h"`. -Then, after an empty newline, include Qt definitions like -`#include `. -Finally, include the standard C++ headers you need. +Avoid the use of C style casts, prefer C++ casts (``static_cast``, ``const_cast`` ...) -Includes must be sorted by alphabetical order. +Use ``qobject_cast`` for ``QObjects`` -Docstrings -~~~~~~~~~~ +Smart Pointers +~~~~~~~~~~~~~~ -Our API reference is generated using Doxygen, so when it comes to -function documentation, please use the following format: +Prefer the use of C++ smart pointers (``unique_ptr``, ``shared_ptr``...) .. code:: cpp - /** - * @brief Add a new param to the accumulator - */ - virtual void accumulate(RefreshDeferrerParams params) =0; + RegisterProfileDialog *ui; // Bad + + std::unique_ptr ui; // Good + +Braces +~~~~~~ + +In contrast to the official guidelines of Qt, in Cutter we always use curly braces in conditional statements, even if the body of a conditional statement contains only one line. + +.. code:: cpp + + // Wrong + if (address.isEmpty()) + return false; + + // Correct + if (address.isEmpty()) { + return false; + } + + // Wrong + for (int i = 0; i < 10; ++i) + qDebug("%i", i); + + // Correct + for (int i = 0; i < 10; ++i) { + qDebug("%i", i); + } Loops ~~~~~ @@ -140,11 +269,42 @@ We use the C++11 foreach loop style, which means any “foreach” loop should look like: .. code:: cpp + + // Good - If a copy of each element is required + for (auto import : importsArray) { + doSomething(import; + } + + // Good - If copy is not required + for (auto &import : importsArray) { + doSomething(import; + } - for (QJsonValue value : importsArray) { - doSomething(value); + // Good - If no modification is required + for (const auto &import : importsArray) { + doSomething(import); } +auto +~~~~ + +Prefer the use of ``auto`` keyword when working with the following: + +.. code:: cpp + + // Iterators + auto it = myMap.find(key); + for (const auto &import : importsArray) { ... } + + // Lambdas + auto multiply = [](int a, int b) -> int { return a * b; }; + + // Casting + auto myFloat = static_cast(myInt); + + // Initializing using new + auto *item = new QListWidgetItem(text); + nullptr ~~~~~~~ @@ -154,7 +314,10 @@ Example: .. code:: cpp - QObject *object = nullptr; + std::unique_ptr obj = nullptr; + + // Note that this is just an example, unique_ptr constructor initializes the internal pointer to nullptr by default + Connecting Qt Signals ~~~~~~~~~~~~~~~~~~~~~ @@ -191,13 +354,82 @@ Don't use the older macro based syntax or automatic name based connections. connect(sender, &SomeObject::signal, [this](){ this->foo(getBar()); }); // BAD +Includes +~~~~~~~~ + +Strive to include only **required** definitions inside header files. +This will avoid triggering additional unnecessary compilations. + +If you only need to know that a class exists but don't need the prototype, +you can declare the class like this: + +.. code:: cpp + + class MyClassThatExists; + + /** ... **/ + + private: + std::unqiue_ptr classInstance; + +And then include the class header inside your .cpp so you can use that class. + +If you need something in the source file (.cpp) that is not a class member, +then add the include in the source file. + +The includes must be ordered from local to global. That is, first include +any local header file (with double quotes like `#include "common/Helpers.h"`. +Then, after an empty newline, include Qt definitions like +`#include `. +Finally, include the standard C++ headers you need. + +Includes must be sorted by alphabetical order. + +This is automatically handled by running ``clang-format`` + +Docstrings +~~~~~~~~~~ + +Our API reference is generated using Doxygen, so when it comes to +function documentation, please use the following format: + +.. code:: cpp + + /** + * @brief Add new parameters to the accumulator + * @param params The parameters to add + * @return True if the parameters were added, false otherwise + */ + bool accumulate(RefreshDeferrerParams params) { ... }; + +Documenting every function is generally not required. Only document those functions whose purpose is not immediately understandable just by looking at the function name. + +.. code:: cpp + + // No need for docs + int getCount() const; + + // Should provide docs + bool syncRemote(); + +It is preferred for classes to have documentation just above the definition, explaining their purpose. + +.. code:: cpp + + /** + * @brief A short description about SomeDialog + */ + class SomeDialog { + ... + }; + General Coding Advices ---------------------- Functions Documentation ~~~~~~~~~~~~~~~~~~~~~~~ -You can find the class documentation in the API Reference menu item. +You can find the class documentation in the `API Reference `__ menu item. Updating the Git Submodules ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -239,6 +471,6 @@ In order to update one submodule individually, use the following code: Useful Resources (Qt Development) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* `Signals & Slots `__ -* `Model/View Programming `__ - read this if you are going to work with a list or table-like widgets -* `QAction `__ +* `Signals & Slots `__ +* `Model/View Programming `__ - read this if you are going to work with a list or table-like widgets +* `QAction `__ diff --git a/scripts/_clang-format b/scripts/_clang-format index b04f2cacb1..acc7e3d5b0 100644 --- a/scripts/_clang-format +++ b/scripts/_clang-format @@ -79,10 +79,10 @@ AllowShortFunctionsOnASingleLine: Inline # separate categories with an empty line. It does not specify the order within # the categories. Since the SortInclude feature of clang-format does not # re-order includes separated by empty lines, the feature is not used. -SortIncludes: false +SortIncludes: true # macros for which the opening brace stays attached. -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ] +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE, CutterRzListForeach ] # Break constructor initializers before the colon and after the commas. BreakConstructorInitializers: BeforeColon @@ -92,3 +92,18 @@ BreakConstructorInitializers: BeforeColon # Align the assignment operators of consecutive lines AlignConsecutiveAssignments: false + +# Sort headers in the following groups in alphabetical order +# Each group is seperated by an empty line +# 1- Main header +# 2- Local headers starting with "" +# 3- Qt headers starting with or +# 4- Standard C++ headers or any others +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^"([^"]*)"' + Priority: 1 + - Regex: '^<[Qq]' + Priority: 2 + - Regex: '.*' + Priority: 3 diff --git a/scripts/clang-tidy.py b/scripts/clang-tidy.py new file mode 100644 index 0000000000..7da485680f --- /dev/null +++ b/scripts/clang-tidy.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +import argparse +import glob +import subprocess +import sys +import os + +SCAN_DIR = "src" +SKIP_LIST = ["themes", "bindings", "fonts", "img", "translations", "build", "_autogen"] +EXTENSIONS = (".cpp", ".h", ".hpp") + +def get_files(): + matched_files = [] + for root, dirs, files in os.walk(SCAN_DIR): + dirs[:] = [d for d in dirs if d not in SKIP_LIST] + + for file in files: + if file.endswith(EXTENSIONS): + matched_files.append(os.path.join(root, file)) + return matched_files + +def run_tidy(args): + files = [args.file] if args.file else get_files() + + if not files: + print("No files found to process.") + return + + cmd = [args.run_clang_tidy, "-p", args.build_path] + + # Add header filter if a specific file is targeted + # This prevents seeing errors from included headers/other files + if args.file: + cmd.append("-header-filter='^$'") + + if args.fix: + cmd.append("-fix") + + cmd.append("-quiet") + cmd.extend(files) + + result = subprocess.run(cmd) + + sys.exit(result.returncode) + +def main(): + parser = argparse.ArgumentParser(description="clang-tidy wrapper") + + parser.add_argument("-T", "--run-clang-tidy", + default="run-clang-tidy", + help="Path of run-clang-tidy binary") + + parser.add_argument("-p", "--build-path", default="build", + help="Path to the build directory") + + parser.add_argument("-f", "--file", help="Check a specific file only") + parser.add_argument("-i", "--fix", action="store_true", help="Apply fixes automatically") + + args = parser.parse_args() + run_tidy(args) + +if __name__ == "__main__": + main() From 0f856cbeca96ade8456112a7561cf5c6925bee80 Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:38:27 +0500 Subject: [PATCH 2/6] Move to LLVM version 20 --- .github/workflows/linter.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 3307b70cd3..24c12a739e 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -43,18 +43,18 @@ jobs: - name: Uninstall old conflicting packages run: sudo apt purge --assume-yes --auto-remove llvm python3-lldb-14 llvm-14 - - name: Install automatic LLVM 16 - run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 16 + - name: Install automatic LLVM 20 + run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 20 - - name: Install clang-format-16 - run: sudo apt --assume-yes install clang-format-16 + - name: Install clang-format-20 + run: sudo apt --assume-yes install clang-format-20 - name: Install gitpython run: sudo pip install gitpython - name: Run clang-format run: | - sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-16 160 + sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-20 200 clang-format --version python scripts/clang-format.py --check --verbose @@ -78,12 +78,12 @@ jobs: libqt6svgwidgets6 qt6-l10n-tools \ libgl1-mesa-dev libglu1-mesa-dev - - name: Install automatic LLVM 16 - run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 16 + - name: Install automatic LLVM 20 + run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 20 - - name: Install clang-tidy-16 + - name: Install clang-tidy-20 run: | - sudo apt --assume-yes install clang-tidy-16 + sudo apt --assume-yes install clang-tidy-20 - name: CMake Configuration run: | @@ -99,7 +99,7 @@ jobs: - name: Run Clang-Tidy run: | - sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-16 160 - sudo update-alternatives --install /usr/bin/run-clang-tidy run-clang-tidy /usr/bin/run-clang-tidy-16 160 + sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-20 200 + sudo update-alternatives --install /usr/bin/run-clang-tidy run-clang-tidy /usr/bin/run-clang-tidy-20 200 clang-tidy -version python3 scripts/clang-tidy.py From 4c354cd10fda96a0df7d52fc37745d2badd66fbc Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:39:11 +0500 Subject: [PATCH 3/6] Fix typo --- docs/source/contributing/code/development-guidelines.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/contributing/code/development-guidelines.rst b/docs/source/contributing/code/development-guidelines.rst index b938285959..327bff68f4 100644 --- a/docs/source/contributing/code/development-guidelines.rst +++ b/docs/source/contributing/code/development-guidelines.rst @@ -272,12 +272,12 @@ look like: // Good - If a copy of each element is required for (auto import : importsArray) { - doSomething(import; + doSomething(import); } // Good - If copy is not required for (auto &import : importsArray) { - doSomething(import; + doSomething(import); } // Good - If no modification is required From 1fe6d9134250b9e794b2a9959c1117967fc15a0e Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 19:48:40 +0500 Subject: [PATCH 4/6] clang-tidy.py: change header-filter regex for single file check --- scripts/clang-tidy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/clang-tidy.py b/scripts/clang-tidy.py index 7da485680f..a75c4628ea 100644 --- a/scripts/clang-tidy.py +++ b/scripts/clang-tidy.py @@ -31,7 +31,7 @@ def run_tidy(args): # Add header filter if a specific file is targeted # This prevents seeing errors from included headers/other files if args.file: - cmd.append("-header-filter='^$'") + cmd.append("-header-filter=''") if args.fix: cmd.append("-fix") From f73cd271d27f3fa08cbec7f63164c5058bb3399b Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:12:01 +0500 Subject: [PATCH 5/6] Put clang-format & clang-tidy in different headings --- docs/source/conf.py | 2 +- .../code/development-guidelines.rst | 45 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f86e443e82..2efe551bbe 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,7 +20,7 @@ # -- Project information ----------------------------------------------------- project = 'Cutter' -copyright = '2020, The Cutter Developers' +copyright = '2026, The Cutter Developers' author = 'The Cutter Developers' # The short X.Y version diff --git a/docs/source/contributing/code/development-guidelines.rst b/docs/source/contributing/code/development-guidelines.rst index 327bff68f4..2a36516b47 100644 --- a/docs/source/contributing/code/development-guidelines.rst +++ b/docs/source/contributing/code/development-guidelines.rst @@ -51,6 +51,9 @@ so your widget refreshes its output when Rizin seek is modified Coding Style ------------ +clang-format +~~~~~~~~~~~~ + In general, we follow a slightly customized version of `the official Qt guidelines `__ to format the code. Before sending a pull request, you will need to use `clang-format `__ (version 8 or newer) to format the code. The command line for formatting the code according @@ -66,6 +69,9 @@ If your changes were done on many files across the codebase, you can use this on find ./src -regex '.*\.\(cpp\|h\)' -exec clang-format -style=file -i {} \; +clang-tidy +~~~~~~~~~~ + Beyond formatting, we use `clang-tidy `__ (version 13 or newer) to catch potential style violations. To run ``clang-tidy``, first configure your build to generate ``compile_commands.json`` and run the autogen tools: @@ -88,12 +94,49 @@ Similar to ``clang-format``, If your changes were done on many files across the run-clang-tidy -p build "src/(?!(themes|bindings|fonts|img|translations|build|.*_autogen)).*\.(cpp|h)$" -``clang-tidy`` can also attempt to fix style violations using the ``-fix`` flag, however these may not always be perfect. Make sure to verify the fixes before opening a pull request: +``clang-tidy`` can also attempt to fix style violations using the ``-fix`` flag. However these may not always be perfect, as an example ``clang-tidy`` puts the const qualifier on the right side of type name whereas it is preferred to be on the left in cutter. Make sure to verify the fixes before opening a pull request: .. code:: bash git diff -U0 --no-color HEAD~1 | clang-tidy-diff.py -fix -p1 -path build/ +Python scripts +~~~~~~~~~~~~~~ + +If you don't want to run manual commands, cutter also provides scripts for running ``clang-format`` and ``clang-tidy`` in the ``scripts`` directory + +.. code:: bash + + python scripts/clang-format.py -h + usage: clang-format.py [-h] [-C CLANG_FORMAT] [-c] [-v] [-f FILE] [-d DIFF] + + Clang format the cutter project + + options: + -h, --help show this help message and exit + -C, --clang-format CLANG_FORMAT + path of clang-format + -c, --check enable the check mode + -v, --verbose use verbose output + -f, --file FILE formats (or checks) only the given file + -d, --diff DIFF format all modified file related to branch + +.. code:: bash + + python scripts/clang-tidy.py -h + usage: clang-tidy.py [-h] [-T RUN_CLANG_TIDY] [-p BUILD_PATH] [-f FILE] [-i] + + clang-tidy wrapper + + options: + -h, --help show this help message and exit + -T, --run-clang-tidy RUN_CLANG_TIDY + Path of run-clang-tidy binary + -p, --build-path BUILD_PATH + Path to the build directory + -f, --file FILE Check a specific file only + -i, --fix Apply fixes automatically + Below are some of the low level coding conventions that we follow From 534470905737d8d5369f499c4d09c52fbe8f8b79 Mon Sep 17 00:00:00 2001 From: PremadeS <128969155+PremadeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:19:07 +0500 Subject: [PATCH 6/6] Rebase dev --- docs/source/contributing/code/development-guidelines.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/contributing/code/development-guidelines.rst b/docs/source/contributing/code/development-guidelines.rst index 2a36516b47..392c000257 100644 --- a/docs/source/contributing/code/development-guidelines.rst +++ b/docs/source/contributing/code/development-guidelines.rst @@ -63,7 +63,7 @@ to the style is: clang-format -style=file -i src/filename.cpp -If your changes were done on many files across the codebase, you can use this oneliner to run ``clang-format`` on the entire 'src' directory: +If your changes were done on many files across the codebase, you can use this oneliner to run ``clang-format`` on the entire ``src`` directory: .. code:: bash @@ -94,7 +94,7 @@ Similar to ``clang-format``, If your changes were done on many files across the run-clang-tidy -p build "src/(?!(themes|bindings|fonts|img|translations|build|.*_autogen)).*\.(cpp|h)$" -``clang-tidy`` can also attempt to fix style violations using the ``-fix`` flag. However these may not always be perfect, as an example ``clang-tidy`` puts the const qualifier on the right side of type name whereas it is preferred to be on the left in cutter. Make sure to verify the fixes before opening a pull request: +``clang-tidy`` can also attempt to fix style violations using the ``-fix`` flag. However these may not always be perfect. Make sure to verify the fixes before opening a pull request: .. code:: bash