@@ -126,8 +126,8 @@ to make the review easier.
126
126
127
127
### C++ feature set
128
128
129
- As of Quotient 0.9, the C++ standard for newly written code is C++20, save for a few exceptions
130
- that the currently supported toolchains still don't have, most notably:
129
+ As of Quotient 0.9, the C++ standard for new code is C++20, except a few features that currently
130
+ supported toolchains still don't have, most notably:
131
131
- template parameteres for type aliases and aggregates still cannot be deduced yet, you have
132
132
to explicitly specify those;
133
133
- modules support, while formally there, is missing standard library header units; sticking with
@@ -151,22 +151,20 @@ use `// clang-format off` and `// clang-format on` to protect them.
151
151
152
152
Most fundamental things from ` .clang-format ` :
153
153
* We (mostly) use Webkit style: 4-space indents, no tabs, no trailing spaces, no last empty lines.
154
- If you spot code that doesn't follow this, fix it on the spot, thank you.
154
+ If you see code that doesn't follow this, fix it on the spot, thank you.
155
155
* Prefer keeping lines within 100 characters. Slight overflows are ok if that
156
156
helps readability. Ideally, just use ` clang-format ` to format lines.
157
157
158
158
### API conventions
159
159
160
- All non-inline symbols (functions, classes/structs, even namespace-level static
161
- variables) that are intended for use in client code must be declared with
162
- ` QUOTIENT_API ` macro (the macro itself is defined in the dedicated
163
- ` quotient_export.h ` file). This is concerned with symbols visibility in
164
- dynamic/shared libraries: the macro marks these symbols for exporting in
165
- the library symbol table. If you forget to use this macro where needed you will
166
- get linkage errors if you're lucky, obscure runtime errors otherwise (such as
167
- split-brained singleton instances). You only need to use the macro on the
168
- namespace level; inner symbols (member functions, e.g.) are exported if
169
- their class is exported.
160
+ All non-inline symbols (functions, classes/structs, even namespace-level static variables) that are
161
+ intended for use in client code must be declared with ` QUOTIENT_API ` macro (the macro itself is
162
+ defined in the dedicated ` quotient_export.h ` file) in order to export them in the library symbol
163
+ table when it is compiled as dynamic/shared. If you forget to use this macro and a client
164
+ application uses the symbol there will be linkage errors in a lucky case and obscure runtime errors
165
+ (such as split-brained singleton instances) otherwise. You only need to use the macro
166
+ on the namespace level; nested symbols (member functions, e.g.) are exported if their class is
167
+ exported.
170
168
171
169
Some header files of the library are not intended to be (directly) included by
172
170
clients - these header files have names ending with ` _p.h ` (e.g.
@@ -183,17 +181,14 @@ so tread carefully).
183
181
184
182
### Generated C++ code for CS API
185
183
186
- The code in ` Quotient/csapi ` , ` Quotient/identity ` and
187
- ` Quotient/application-service ` , although stored in Git, is actually generated
188
- from the official Matrix Client-Server API definition files. Make sure to read
189
- [ CODE_GENERATION.md] ( ./CODE_GENERATION.md ) before trying to change anything
190
- there.
184
+ The code in ` Quotient/csapi ` , ` Quotient/identity ` and ` Quotient/application-service ` , although
185
+ stored in Git, is actually generated from the official Matrix Client-Server API definition files.
186
+ Make sure to read [ CODE_GENERATION.md] ( ./CODE_GENERATION.md ) before trying to change anything there.
191
187
192
188
193
189
## Documentation changes
194
190
195
- Most of the documentation is in Markdown format. All Markdown files use the
196
- ` .md ` filename extension.
191
+ Most of the documentation is in Markdown format; the file names use the ` .md ` extension.
197
192
198
193
Where reasonable, limit yourself to Markdown that will be accepted by different
199
194
markdown processors (e.g., what is specified by CommonMark or the original
@@ -210,12 +205,10 @@ by GitHub when it renders issue or pull comments; in those cases
210
205
unfortunately this other algorithm is * also* called GitHub-flavoured markdown.
211
206
(Yes, it would be better if there were different names for different things.)
212
207
213
- In your markdown, please don't use tab characters and avoid "bare" URLs.
214
- In a hyperlink, the link text and URL should be on the same line.
215
- Both in C/C++ code comments and Markdown documents, try to keep your lines
216
- within the 100-character limit _ except hyperlinks_ (wrapping breaks them). Some
217
- historical text may not follow that rule - feel free to reformat those parts
218
- when you edit them.
208
+ Don't use tab characters and avoid "bare" URLs. In a hyperlink, the link text and URL should be
209
+ on the same line. Both in C/C++ code comments and Markdown documents, try to keep your lines
210
+ within the 100-character limit _ except hyperlinks_ (wrapping breaks them). Some historical text
211
+ may not follow that rule - feel free to reformat those parts when you edit them.
219
212
220
213
Do not use trailing two spaces for line breaks, since these cannot be seen
221
214
and may be silently removed by some tools. If, for whatever reason, a blank line
@@ -232,11 +225,11 @@ Further sections are for those who's going to actively hack on the library code.
232
225
233
226
### More on code style and formatting
234
227
235
- * Do not use ` struct ` when you have protected or private members; only use it
236
- to define plain-old-data structures, with maybe just a function or two among
237
- public members but no substantial behaviour. If you need access control or
238
- specific logic tightly coupled to the data structure, make it a ` class `
239
- instead and consider if you still want to keep its member variables public.
228
+ * Prefer ` class ` over ` struct ` when you have protected or private members in the type; ` struct ` is
229
+ meant for plain-old-data structures, with maybe just a function or two among public members
230
+ but no substantial behaviour. If you need access control or specific logic tightly coupled to
231
+ the data structure, make it a ` class ` and consider if you still want to keep its member variables
232
+ public.
240
233
241
234
* For newly created classes, keep to
242
235
[ the rule of 3/5/0] ( http://en.cppreference.com/w/cpp/language/rule_of_three ) .
@@ -250,57 +243,44 @@ Further sections are for those who's going to actively hack on the library code.
250
243
Classes without a default constructor are a problem too. Examples of that
251
244
are ` SyncRoomData ` and ` EventsArray<> ` . Again, you can use STL containers
252
245
for structures having those but consider the implications.
253
- * So, the implications. Because QML doesn't know about most of STL containers and cannot pull data
254
- out of them, you're only free to use STL containers in backend code (in the simplest case,
255
- within one .cpp file). The API exposing these containers can only be used from C++ code, with
256
- ` std::vector ` being a notable exception that QML knows about (but you still can't read
257
- uncopyable vectors such as ` EventsArray<> ` , as the previous bullet already said). For these
258
- cases you have to provide external means to iterate through the container and consume data
259
- from it; exposing a Qt item model is most natural to Qt code. If you don't provide such other
260
- means, expect questions at your pull request.
261
- * Notwithstanding the above (you're not going to use smart pointers with QML
262
- anyway), prefer ` std::unique_ptr<> ` over ` QScopedPointer<> ` as it gives
263
- stronger guarantees; also, some features of ` QScopedPointer ` are deprecated
264
- in Qt 6.
265
-
266
- * Always use ` QVector ` instead of ` QList ` unless Qt's own API uses it - see the
267
- [ great article by Marc Mutz on Qt containers] ( https://marcmutz.wordpress.com/effective-qt/containers/ )
268
- for details. With Qt 6, these two become the same type matching what used
269
- to be ` QVector ` in Qt 5.
270
-
271
- (Note: unfortunately, ` QVector ` is a type alias in Qt 6 and that breaks
272
- templated code because type deduction doesn't work with aliases. This breakage
273
- will go away as compilers adopt C++23 sufficiently but it may take a
274
- couple more years, as of this writing; in the meantime, the fix boils down
275
- to specifying the template parameter of ` QVector ` explicitly.)
246
+ * So, the implications. QML doesn't know about most of STL containers and in any case requires
247
+ data types passed to it (let alone from it) to be default-constructible and copyable. For that
248
+ reason, STL containers can only be used in backend code that is not meant for consumption by
249
+ QML. The only STL container mapped to QML as of Qt 6.6 is ` std::vector ` ; and even then you
250
+ still can't expose uncopyable vectors such as ` EventsArray<> ` to QML. For these cases you have
251
+ to provide external means to iterate through the container and consume data from it; exposing
252
+ a Qt item model is most natural to Qt code. If you don't provide such other means, expect
253
+ questions at your pull request.
254
+ * Prefer ` std::unique_ptr<> ` over ` QScopedPointer<> ` ; ` std::as_const() ` to ` qAsConst() ` ;
255
+ ` std::swap() ` to ` qSwap() ` etc.; basically, do not use compat facilities provided by Qt if the
256
+ standard library provides an _ equivalent_ facility.
276
257
277
258
* When you write logs within the library always use logging categories defined in
278
259
` logging_categories_p.h ` instead of plain ` qDebug() ` , to avoid a log line being assigned
279
260
the default category. ` qCDebug(CATEGORY) ` is the preferred form; ` qDebug(CATEGORY) ` (without ` C ` )
280
261
is accepted as well. Do not add new logging categories without necessity; if you do, make sure
281
262
to add the new category to ` logging_categories_p.h ` , so that there's a central reference for all
282
- of them (mentioned in README.md, by the way).
263
+ of them (also listed in README.md, by the way).
283
264
284
265
### Comments
285
266
286
- Whenever you add a new call to the library API that you expect to be used
287
- from client code, make sure to supply a proper doc-comment along with the call.
288
- Quotient uses the Doxygen C++-styled doc-comments (` //! ` , ` \brief ` ); some legacy
289
- code may use Javadoc (` /** ... */ ` , ` @brief ` ) or C-styled Doxygen (` /*! ... */ ` )
290
- but that is not encouraged any more. Some parts are not documented at all;
291
- adding doc-comments to them and/or converting the existing ones to the assumed
292
- style is highly encouraged; it's also a nice and easy first-time contribution.
267
+ Whenever you add or change the library API, make sure to supply a proper doc-comment along with
268
+ the call. Quotient uses the Doxygen C++-styled doc-comments (` //! ` , ` \brief ` ); some legacy code
269
+ may use Javadoc (` /** ... */ ` , ` @brief ` ) or C-styled Doxygen (` /*! ... */ ` ) but that is
270
+ not encouraged any more. Some parts are not documented at all; adding doc-comments to them
271
+ and/or converting the existing ones to the assumed style is highly encouraged; it's also a nice
272
+ and easy first-time contribution.
293
273
294
- Use ` \brief ` for the summary, and follow with details after
295
- an empty doc-comment line, using ` \param ` , ` \return ` etc. as necessary.
274
+ Use ` \brief ` for the summary, and follow with details after an empty doc-comment line, using
275
+ ` \param ` , ` \return ` etc. as necessary. Adding ` \since ` to indicate the first version when a
276
+ symbol is introduce is nice, too.
296
277
297
278
When commenting in-code:
298
- * Don't restate what's happening in the code unless it's not really obvious.
299
- We assume the readers to have some command of C++ and Qt. If your code is
300
- not obvious, consider making it clearer itself before commenting.
279
+ * Don't restate what's happening in the code. We assume the readers to have some command of C++
280
+ and Qt. If your code is not obvious, consider making it clearer itself before commenting.
301
281
* That said, both C++ and Qt have their arcane/novel features and dark corners, and education of
302
282
code readers is a great thing. Use your experience to figure what might be not that well-known,
303
- and comment such cases: leave references to web pages, Quotient wiki etc. Do not comment ` std:: `
283
+ and comment such cases: add references to web pages, Quotient wiki etc. Do not comment ` std:: `
304
284
calls just because they are less known - readers are expected to know about cppreference.com and
305
285
look it up.
306
286
* More important than everything above - make sure to document not so much "what" but more "why"
@@ -316,17 +296,19 @@ have just started adding those to the new code (you guessed it; adding more
316
296
tests to the old code is very welcome and also is a good exercise to get to
317
297
know the library).
318
298
319
- On top of that , libQuotient comes with a command-line end-to-end test suite
320
- called Quotest. Any significant addition to the library API should be
321
- accompanied by a respective test in ` autotests/ ` and/or in Quotest.
299
+ On top of autotests , libQuotient comes with a command-line end-to-end test suite called Quotest.
300
+ Any significant addition to the library API should be accompanied by a respective test
301
+ in ` autotests/ ` and/or in Quotest.
322
302
323
303
To add a test to autotests:
304
+
324
305
- In a new ` .cpp ` file in ` autotests/ ` (you don't need a header file), define a test class derived
325
306
from ` QObject ` and write tests as member functions in its ` private slots: ` section. See other
326
307
autotests to get an idea of what it should look like.
327
308
- Add a ` quotient_add_test ` macro call with your test to ` autotests/CMakeLists.txt `
328
309
329
310
To add a test to Quotest:
311
+
330
312
- In ` quotest.cpp ` , add a new test to the ` TestSuite ` class. Similar to Qt Test,
331
313
each test in Quotest is a private slot; unlike Qt Test, you should use
332
314
special macros, ` TEST_DECL() ` and ` TEST_IMPL() ` , to declare and define
@@ -348,8 +330,7 @@ from it).
348
330
349
331
### Security and privacy
350
332
351
- Pay attention to security, and work * with* , not against, the usual security
352
- hardening practices.
333
+ Pay attention to security, and work * with* , not against, the good security practices.
353
334
354
335
` char * ` and similar unchecked C-style read/write arrays are forbidden - use Qt containers
355
336
(` QString ` /` QLatin1String ` for strings, in particular) or ` std::array<> ` /` std::span<> ` instead
@@ -429,7 +410,7 @@ If you want the IDE to be _really_ picky about your code you can use
429
410
the following line for the Clang analyzer code model to enable most compiler
430
411
warnings while keeping the number of false positives at bay (that does not
431
412
include ` clang-tidy ` /` clazy ` warnings - see the next section on those):
432
- ` -Weverything -Werror=return-type - Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++20-compat -Wno-unused-macros -Wno-newline-eof -Wno-exit-time-destructors -Wno-global-constructors -Wno-gnu-zero-variadic-macro-arguments -Wno-documentation -Wno-missing-prototypes -Wno-shadow-field-in-constructor -Wno-padded -Wno-weak-vtables -Wno-unknown-attributes -Wno-comma -Wno-shadow-uncaptured-local -Wno-switch-enum -Wno-pragma-once-outside-header -Wno-range-loop-bind-reference -Wno-unsafe-buffer-usage `
413
+ ` -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++20-compat -Wno-unused-macros -Wno-newline-eof -Wno-exit-time-destructors -Wno-global-constructors -Wno-gnu-zero-variadic-macro-arguments -Wno-documentation -Wno-missing-prototypes -Wno-shadow-field-in-constructor -Wno-padded -Wno-weak-vtables -Wno-unknown-attributes -Wno-comma -Wno-shadow-uncaptured-local -Wno-switch-enum -Wno-pragma-once-outside-header -Wno-range-loop-bind-reference -Wno-unsafe-buffer-usage `
433
414
434
415
### Static analysis tools
435
416
0 commit comments