mirror of
https://github.com/rizinorg/cutter
synced 2026-08-11 16:23:06 -04:00
Enforce coding style using clang-tidy (#3603)
Added scripts/clang-tidy.py Updated doc to tell about clang-tidy Added checks for clang-tidy are defined below * cppcoreguidelines-pro-type-cstyle-cast * misc-const-correctness * misc-unused-parameters * modernize-loop-convert * modernize-use-auto * modernize-use-nullptr * 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
This commit is contained in:
parent
1e6782de48
commit
dc76ccf59e
11 changed files with 652 additions and 113 deletions
46
.clang-tidy
Normal file
46
.clang-tidy
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
Checks: >
|
||||
-*,
|
||||
cppcoreguidelines-pro-type-cstyle-cast,
|
||||
misc-const-correctness,
|
||||
misc-unused-parameters,
|
||||
modernize-loop-convert,
|
||||
modernize-use-auto,
|
||||
modernize-use-nullptr,
|
||||
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/(?!.*autogen).*'
|
||||
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'
|
||||
...
|
||||
58
.github/workflows/linter.yml
vendored
58
.github/workflows/linter.yml
vendored
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
|
||||
clang-format:
|
||||
needs: changes
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ needs.changes.outputs.clang-format == 'true' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
|
@ -43,17 +43,63 @@ 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
|
||||
|
||||
clang-tidy:
|
||||
needs: changes
|
||||
# if: ${{ needs.changes.outputs.code == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
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 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-20
|
||||
run: |
|
||||
sudo apt --assume-yes install clang-tidy-20
|
||||
|
||||
- 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-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
|
||||
|
|
|
|||
138
_clang-format
138
_clang-format
|
|
@ -1,30 +1,59 @@
|
|||
# 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 15.0.4 (https://github.com/ssciwr/clang-format-wheel 0bdee69eb2db136302efab015caaf616d33f5430)
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
|
|
@ -34,11 +63,14 @@ BraceWrapping:
|
|||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
|
|
@ -49,16 +81,23 @@ BreakAfterJavaFieldAnnotations: false
|
|||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^!|^:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: NextLine
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
|
|
@ -67,61 +106,118 @@ ForEachMacros:
|
|||
- QBENCHMARK
|
||||
- QBENCHMARK_ONCE
|
||||
- CutterRzListForeach
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^"([^"]*)"'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<[Qq]'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: true
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
RemoveBracesLLVM: false
|
||||
RequiresClausePosition: OwnLine
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
StatementMacros:
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- emit
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <https://wiki.qt.io/Qt_Coding_Style>`__
|
||||
to format the code. Before sending a pull request, you will need to use `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__ (version 8 or newer)
|
||||
to format the code. The command line for formatting the code according
|
||||
|
|
@ -60,12 +63,226 @@ 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 {} \;
|
||||
|
||||
clang-tidy
|
||||
~~~~~~~~~~
|
||||
|
||||
Beyond formatting, we use `clang-tidy <https://clang.llvm.org/extra/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|Cutter_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/
|
||||
|
||||
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
|
||||
|
||||
usage: clang-tidy.py [-h] [-T RUN_CLANG_TIDY] [-p BUILD_PATH] [-j JOBS] [-r REGEX] [-i] [-q]
|
||||
|
||||
clang-tidy regex 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
|
||||
-j, --jobs JOBS Number of parallel execution jobs
|
||||
-r, --regex REGEX Regex pattern for filtering files
|
||||
-i, --fix Apply fixes automatically
|
||||
-q, --quiet Suppress configuration logs
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// Bad
|
||||
void doSomething(int one, int two) {
|
||||
Q_UNUSED(one)
|
||||
...
|
||||
}
|
||||
|
||||
// Good
|
||||
void doSomething(int /*one*/, int two) {
|
||||
...
|
||||
}
|
||||
|
||||
// Good
|
||||
void doSomething(int, int two) {
|
||||
...
|
||||
}
|
||||
|
||||
Avoid the use of automatic name based connections. See `Connecting Qt Signals`_.
|
||||
|
||||
Classes
|
||||
~~~~~~~~
|
||||
|
||||
First letter of each word is uppercased. (**CamelCase**)
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
class memory_dock_widget; // Wrong
|
||||
class memoryDockWidget; // Wrong
|
||||
|
||||
class MemoryDockWidget; // Correct
|
||||
|
||||
Only first letter of an acronym is uppercase
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
class CutterJSONWidget // Wrong
|
||||
|
||||
class CutterJsonWidget // Correct
|
||||
|
||||
|
||||
Member variables follow the same naming conventions defined in `variables`_ that means no leading/trailing underscores or m\_ prefixes
|
||||
|
||||
Casting
|
||||
~~~~~~~
|
||||
|
||||
Avoid the use of C style casts, prefer C++ casts (``static_cast``, ``const_cast`` ...)
|
||||
|
||||
Use ``qobject_cast`` for ``QObjects``
|
||||
|
||||
Smart Pointers
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Prefer the use of C++ smart pointers (``unique_ptr``, ``shared_ptr``...)
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
RegisterProfileDialog *ui; // Bad
|
||||
|
||||
std::unique_ptr<Ui::RegisterProfileDialog> 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
|
||||
|
|
@ -88,51 +305,6 @@ In contrast to the official guidelines of Qt, in Cutter we always use curly brac
|
|||
qDebug("%i", i);
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
MyClassThatExists *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 <QShortcut>`.
|
||||
Finally, include the standard C++ headers you need.
|
||||
|
||||
Includes must be sorted by alphabetical order.
|
||||
|
||||
Docstrings
|
||||
~~~~~~~~~~
|
||||
|
||||
Our API reference is generated using Doxygen, so when it comes to
|
||||
function documentation, please use the following format:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
/**
|
||||
* @brief Add a new param to the accumulator
|
||||
*/
|
||||
virtual void accumulate(RefreshDeferrerParams params) =0;
|
||||
|
||||
Loops
|
||||
~~~~~
|
||||
|
||||
|
|
@ -140,10 +312,41 @@ We use the C++11 foreach loop style, which means any “foreach” loop should
|
|||
look like:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
for (QJsonValue value : importsArray) {
|
||||
doSomething(value);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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<float>(myInt);
|
||||
|
||||
// Initializing using new
|
||||
auto *item = new QListWidgetItem(text);
|
||||
|
||||
nullptr
|
||||
~~~~~~~
|
||||
|
|
@ -154,7 +357,10 @@ Example:
|
|||
|
||||
.. code:: cpp
|
||||
|
||||
QObject *object = nullptr;
|
||||
std::unique_ptr<QObject> 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 +397,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<MyClassThatExists> 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 <QShortcut>`.
|
||||
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 <https://cutter.re/docs/api.html>`__ menu item.
|
||||
|
||||
Updating the Git Submodules
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -239,6 +514,6 @@ In order to update one submodule individually, use the following code:
|
|||
Useful Resources (Qt Development)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* `Signals & Slots <https://doc.qt.io/qt-5/signalsandslots.html>`__
|
||||
* `Model/View Programming <https://doc.qt.io/qt-5/model-view-programming.html>`__ - read this if you are going to work with a list or table-like widgets
|
||||
* `QAction <https://doc.qt.io/qt-5/qaction.html#details>`__
|
||||
* `Signals & Slots <https://doc.qt.io/qt-6/signalsandslots.html>`__
|
||||
* `Model/View Programming <https://doc.qt.io/qt-6/model-view-programming.html>`__ - read this if you are going to work with a list or table-like widgets
|
||||
* `QAction <https://doc.qt.io/qt-6/qaction.html#details>`__
|
||||
|
|
|
|||
|
|
@ -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,28 @@ 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 <Q...> or <q...>
|
||||
# 4- Standard C++ headers or any others
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^"([^"]*)"'
|
||||
Priority: 1
|
||||
- Regex: '^<[Qq]'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
|
||||
# Insert braces after conditional statements/loops even if they
|
||||
# contain a single statement
|
||||
InsertBraces: true
|
||||
|
||||
# Insert space in empty braces
|
||||
SpaceInEmptyBlock: false
|
||||
|
||||
# Removes the spaces around ->
|
||||
StatementAttributeLikeMacros: [emit]
|
||||
|
|
|
|||
51
scripts/clang-tidy.py
Normal file
51
scripts/clang-tidy.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
DEFAULT_REGEX = r".*src/(?!(themes|bindings|fonts|img|translations|Cutter_autogen)).*\.(cpp|h)$"
|
||||
|
||||
def run_tidy(args):
|
||||
cmd = [args.run_clang_tidy, "-p", args.build_path]
|
||||
|
||||
if args.jobs:
|
||||
cmd.append(f"-j {args.jobs}")
|
||||
|
||||
if args.fix:
|
||||
cmd.append("-fix")
|
||||
|
||||
if args.quiet:
|
||||
cmd.append("-quiet")
|
||||
|
||||
cmd.append(f"'{args.regex}'")
|
||||
|
||||
print(f"Executing: {' '.join(cmd)}")
|
||||
|
||||
result = subprocess.run(" ".join(cmd), shell=True)
|
||||
|
||||
sys.exit(result.returncode)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="clang-tidy regex 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("-j", "--jobs", type=int, default=0,
|
||||
help="Number of parallel execution jobs")
|
||||
|
||||
parser.add_argument("-r", "--regex", default=DEFAULT_REGEX,
|
||||
help="Regex pattern for filtering files")
|
||||
|
||||
parser.add_argument("-i", "--fix", action="store_true", help="Apply fixes automatically")
|
||||
parser.add_argument("-q", "--quiet", action="store_true", default=False, help="Suppress configuration logs")
|
||||
|
||||
args = parser.parse_args()
|
||||
run_tidy(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -5,9 +5,9 @@ set -euo pipefail
|
|||
cd $(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
# Do not replace with newer without dicussing! Intentionally using older clang-format-version.
|
||||
tool=clang-format-8
|
||||
tool=clang-format-15
|
||||
# Using full config dumped with older clang format should produce more consistent result when some
|
||||
# people have slightly newer clang-format. 8 chosen because it is newest version available in Ubuntu 16.04 official repository.
|
||||
# people have slightly newer clang-format. 15 chosen because it is newest version available in Ubuntu 22.04 official repository.
|
||||
output_file=../_clang-format
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4974,29 +4974,27 @@ QString CutterCore::getVersionInformation()
|
|||
{
|
||||
const char *name;
|
||||
const char *(*callback)();
|
||||
} vcs[] = {
|
||||
{ "rz_arch", &rz_arch_version },
|
||||
{ "rz_lib", &rz_lib_version },
|
||||
{ "rz_egg", &rz_egg_version },
|
||||
{ "rz_bin", &rz_bin_version },
|
||||
{ "rz_cons", &rz_cons_version },
|
||||
{ "rz_flag", &rz_flag_version },
|
||||
{ "rz_core", &rz_core_version },
|
||||
{ "rz_crypto", &rz_crypto_version },
|
||||
{ "rz_debug", &rz_debug_version },
|
||||
{ "rz_hash", &rz_hash_version },
|
||||
{ "rz_io", &rz_io_version },
|
||||
} vcs[] = { { "rz_arch", &rz_arch_version },
|
||||
{ "rz_lib", &rz_lib_version },
|
||||
{ "rz_egg", &rz_egg_version },
|
||||
{ "rz_bin", &rz_bin_version },
|
||||
{ "rz_cons", &rz_cons_version },
|
||||
{ "rz_flag", &rz_flag_version },
|
||||
{ "rz_core", &rz_core_version },
|
||||
{ "rz_crypto", &rz_crypto_version },
|
||||
{ "rz_debug", &rz_debug_version },
|
||||
{ "rz_hash", &rz_hash_version },
|
||||
{ "rz_io", &rz_io_version },
|
||||
#if !USE_LIB_MAGIC
|
||||
{ "rz_magic", &rz_magic_version },
|
||||
{ "rz_magic", &rz_magic_version },
|
||||
#endif
|
||||
{ "rz_reg", &rz_reg_version },
|
||||
{ "rz_sign", &rz_sign_version },
|
||||
{ "rz_search", &rz_search_version },
|
||||
{ "rz_syscall", &rz_syscall_version },
|
||||
{ "rz_util", &rz_util_version },
|
||||
/* ... */
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
{ "rz_reg", &rz_reg_version },
|
||||
{ "rz_sign", &rz_sign_version },
|
||||
{ "rz_search", &rz_search_version },
|
||||
{ "rz_syscall", &rz_syscall_version },
|
||||
{ "rz_util", &rz_util_version },
|
||||
/* ... */
|
||||
{ nullptr, nullptr } };
|
||||
versionInfo.append(getRizinVersionReadable());
|
||||
versionInfo.append("\n");
|
||||
for (i = 0; vcs[i].name; i++) {
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ void ColorThemeComboBox::updateFromConfig(bool interfaceThemeChanged)
|
|||
}
|
||||
}
|
||||
|
||||
QString curTheme = interfaceThemeChanged ? Config()->getLastThemeOf(
|
||||
Configuration::cutterInterfaceThemesList()[curInterfaceThemeIndex])
|
||||
: Config()->getColorTheme();
|
||||
QString curTheme = interfaceThemeChanged
|
||||
? Config()->getLastThemeOf(
|
||||
Configuration::cutterInterfaceThemesList()[curInterfaceThemeIndex])
|
||||
: Config()->getColorTheme();
|
||||
const int index = findText(curTheme);
|
||||
|
||||
setCurrentIndex(index == -1 ? 0 : index);
|
||||
|
|
|
|||
|
|
@ -253,9 +253,10 @@ void HexdumpWidget::updateParseWindow(RVA start_address, int size)
|
|||
tempConfig.set("asm.arch", arch).set("asm.bits", bits).set("cfg.bigendian", bigEndian);
|
||||
|
||||
ui->hexDisasTextEdit->setPlainText(
|
||||
selectedCommand != "" ? Core()->cmdRawAt(
|
||||
QString("%1 @! %2").arg(selectedCommand).arg(size), start_address)
|
||||
: "");
|
||||
selectedCommand != ""
|
||||
? Core()->cmdRawAt(QString("%1 @! %2").arg(selectedCommand).arg(size),
|
||||
start_address)
|
||||
: "");
|
||||
} else {
|
||||
// Fill the information tab hashes and entropy
|
||||
RzHashSize digestSize = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue