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