1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
|
# Code Style
## Overview
MeshMC enforces consistent code style using `.clang-format` and `.clang-tidy` configurations. The project uses C++23 with Qt6 patterns. Code formatting is checked automatically via lefthook git hooks.
## Clang-Format Configuration
The `.clang-format` file defines the formatting rules:
```yaml
BasedOnStyle: LLVM
ColumnLimit: 80
IndentWidth: 4
TabWidth: 4
UseTab: Always
ContinuationIndentWidth: 4
BreakBeforeBraces: Linux
PointerAlignment: Left
SortIncludes: false
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignOperands: Align
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
IndentCaseLabels: true
IndentPPDirectives: None
NamespaceIndentation: All
SpaceBeforeParens: ControlStatements
SpacesInParentheses: false
```
### Key Formatting Rules
| Rule | Value | Example |
|---|---|---|
| Indentation | Tabs (width 4) | `\tif (x)` |
| Column limit | 80 characters | — |
| Braces | Linux style | `if (x) {` on same line; function `{` on new line |
| Pointer alignment | Left | `int* ptr` not `int *ptr` |
| Include sorting | Disabled | Preserve manual grouping |
| Short blocks | Never on one line | Always use braces + newlines |
| Namespace indent | All | Contents indented inside namespaces |
### Running clang-format
```bash
# Format a single file
clang-format -i launcher/Application.cpp
# Format all source files
find launcher libraries -name '*.cpp' -o -name '*.h' | xargs clang-format -i
# Check without modifying (CI mode)
clang-format --dry-run --Werror launcher/Application.cpp
```
## Clang-Tidy Configuration
The `.clang-tidy` file enables static analysis checks:
```yaml
Checks: >
-*,
bugprone-*,
clang-analyzer-*,
performance-*,
portability-*,
readability-*,
-readability-function-cognitive-complexity,
-readability-magic-numbers,
-readability-identifier-length,
-readability-convert-member-functions-to-static,
modernize-*,
-modernize-use-trailing-return-type
HeaderFilterRegex: '^(launcher|libraries|updater|buildconfig)/'
FormatStyle: file
CheckOptions:
- key: readability-function-size.LineThreshold
value: '200'
- key: readability-function-size.StatementThreshold
value: '120'
```
### Enabled Check Categories
| Category | Scope |
|---|---|
| `bugprone-*` | Bug-prone patterns (narrowing conversions, incorrect moves, etc.) |
| `clang-analyzer-*` | Clang Static Analyzer checks (null deref, memory leaks, etc.) |
| `performance-*` | Performance issues (unnecessary copies, move semantics) |
| `portability-*` | Portability concerns across compilers/platforms |
| `readability-*` | Code readability (naming, braces, simplification) |
| `modernize-*` | C++ modernization (auto, range-for, nullptr, etc.) |
### Disabled Checks
| Check | Reason |
|---|---|
| `readability-function-cognitive-complexity` | Qt UI code often has inherently complex functions |
| `readability-magic-numbers` | Not enforced due to frequent use in UI layout code |
| `readability-identifier-length` | Short names like `i`, `dl`, `it` are acceptable |
| `readability-convert-member-functions-to-static` | Conflicts with Qt's signal/slot pattern |
| `modernize-use-trailing-return-type` | Traditional return types preferred |
### Function Size Limits
- Maximum **200 lines** per function
- Maximum **120 statements** per function
### Running clang-tidy
```bash
# Run on a single file (requires compile_commands.json)
clang-tidy launcher/Application.cpp
# Run with fixes applied
clang-tidy --fix launcher/Application.cpp
# Generate compile_commands.json
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...
```
## C++ Standard
MeshMC uses **C++23**:
```cmake
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
```
### C++23 Features Used
- `std::expected` — error handling without exceptions
- `std::format` — string formatting (where supported)
- `std::ranges` — range operations
- Structured bindings
- `if constexpr`
- `std::optional`, `std::variant`
- Designated initializers
- Three-way comparison (`<=>`)
## Qt Patterns
### Q_OBJECT Macro
All QObject subclasses must include the `Q_OBJECT` macro:
```cpp
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject* parent = nullptr);
// ...
};
```
### Signals and Slots
Use the new-style signal/slot syntax:
```cpp
// Preferred: compile-time checked
connect(sender, &Sender::signalName, receiver, &Receiver::slotName);
// Lambda connections
connect(sender, &Sender::signalName, this, [this]() {
// Handle signal
});
```
Avoid the old `SIGNAL()`/`SLOT()` macro syntax.
### shared_qobject_ptr
MeshMC uses `shared_qobject_ptr<T>` for shared ownership of QObjects:
```cpp
// Instead of raw pointers or QSharedPointer
shared_qobject_ptr<NetJob> job(new NetJob("Download", network));
```
This is a custom smart pointer that integrates with Qt's parent-child ownership.
### Memory Management
- Use Qt's parent-child ownership for UI objects
- Use `shared_qobject_ptr<T>` for task objects shared across modules
- Use `std::shared_ptr<T>` for non-QObject types
- Use `std::unique_ptr<T>` for exclusive ownership
- Avoid raw `new`/`delete` outside Qt's parent-child system
## Naming Conventions
### Classes
```cpp
class MinecraftInstance; // PascalCase
class BaseVersionList; // PascalCase
class NetJob; // PascalCase
```
### Member Variables
```cpp
class MyClass {
int m_count; // m_ prefix for member variables
QString m_name; // m_ prefix
QList<Item> m_items; // m_ prefix
static int s_instance; // s_ prefix for static members
};
```
### Methods
```cpp
void executeTask(); // camelCase
QString profileName() const; // camelCase, const for getters
void setProfileName(const QString& name); // set prefix for setters
```
### Signals and Slots
```cpp
signals:
void taskStarted(); // camelCase, past tense for events
void progressChanged(int); // camelCase
void downloadFinished(); // camelCase
public slots:
void onButtonClicked(); // on prefix for UI slots (optional)
void handleError(QString); // handle prefix (optional)
```
### Type Aliases
```cpp
using Ptr = std::shared_ptr<MyClass>; // Ptr alias convention
using WeakPtr = std::weak_ptr<MyClass>;
```
### Enums
```cpp
enum class AccountState { // PascalCase, scoped (enum class)
Unchecked, // PascalCase values
Online,
Offline,
Errored,
};
```
### Files
```
Application.h / Application.cpp // PascalCase, matching class name
MinecraftInstance.h // PascalCase
ui-shared.h / ui-shared.c // kebab-case for C files (cgit-inherited)
```
## Header Guards
Use `#pragma once`:
```cpp
#pragma once
#include <QString>
// ...
```
## Include Order
Includes are grouped (but not auto-sorted):
```cpp
// 1. Corresponding header
#include "MyClass.h"
// 2. Project headers
#include "Application.h"
#include "settings/SettingsObject.h"
// 3. Qt headers
#include <QObject>
#include <QString>
// 4. Standard library
#include <memory>
#include <vector>
```
## Lefthook Integration
Git hooks are managed via `lefthook.yml`:
```yaml
pre-commit:
commands:
clang-format:
glob: "*.{cpp,h}"
run: clang-format --dry-run --Werror {staged_files}
```
Install hooks after bootstrapping:
```bash
lefthook install
```
|