Prism Launcher follows specific code style conventions to maintain consistency across the codebase. All contributors must adhere to these guidelines.
All C++ files are formatted with clang-format using the configuration in .clang-format.
Always run clang-format on changed files before committing!
# Format a single file
clang-format -i path/to/file.cpp
# Format all modified files in git
git diff --name-only | grep -E '\.(cpp|h|cc|hpp)$' | xargs clang-format -i
# Check formatting without modifying files
clang-format --dry-run --Werror path/to/file.cpp
The project uses a custom clang-format configuration based on Chromium style:
BasedOnStyle: Chromium
IndentWidth: 4
AllowShortIfStatementsOnASingleLine: false
ColumnLimit: 140
AccessModifierOffset: -1
BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma
Cpp11BracedListStyle: false
QualifierAlignment: Left
Key formatting rules:
- Indent width: 4 spaces
- Column limit: 140 characters
- Braces: Functions have braces on a new line
- Short statements: No single-line if statements
Naming Conventions
Classes and Types
Use PascalCase for class and type names:
class MyClass { };
struct Person { };
enum class PizzaToppings { };
Member Variables
Private/Protected
Private/Protected Static
Public
Static Const
Use camelCase with m_ prefix:class ImportantClass {
private:
int m_counter;
QString m_userName;
std::vector<int> m_dataPoints;
};
Use camelCase with s_ prefix:class Singleton {
private:
static Singleton* s_instance;
static std::mutex s_mutex;
};
Use camelCase without prefix:struct Person {
QString name;
QDateTime dateOfBirth;
int age;
};
Use SCREAMING_SNAKE_CASE for constants:class Configuration {
public:
static constexpr int MAX_CONNECTIONS = 100;
static const QString DEFAULT_SERVER;
private:
static constexpr int DEFAULT_TIMEOUT = 5000;
};
Functions
Use camelCase for all function names:
class DataProcessor {
public:
void processData();
int calculateSum(int a, int b);
bool isValid() const;
private:
void initializeBuffers();
};
// Global functions also use camelCase
void globalFunction();
int computeHash(const QString& data);
Global Variables and Constants
// Non-const global variables: camelCase
int globalCounter = 0;
QString applicationPath;
// Const global variables and macros: SCREAMING_SNAKE_CASE
const int MAX_BUFFER_SIZE = 4096;
constexpr double PI = 3.14159;
#define AWESOMENESS 10
#define VERSION_STRING "1.0.0"
Enum Constants
Use PascalCase for enum values:
enum class PizzaToppings {
HamAndPineapple,
OreoAndKetchup,
ClassicPepperoni
};
enum class HttpStatus {
Ok,
NotFound,
InternalServerError
};
Complete Example
Here’s a comprehensive example showing all naming conventions:
#define AWESOMENESS 10
constexpr double PI = 3.14159;
enum class PizzaToppings { HamAndPineapple, OreoAndKetchup };
struct Person {
QString name;
QDateTime dateOfBirth;
long daysOld() const { return dateOfBirth.daysTo(QDateTime::currentDateTime()); }
};
class ImportantClass {
public:
void incrementCounter()
{
if (m_counter + 1 > MAX_COUNTER_VALUE)
throw std::runtime_error("Counter has reached limit!");
++m_counter;
}
int counter() const { return m_counter; }
private:
static constexpr int MAX_COUNTER_VALUE = 100;
int m_counter;
};
ImportantClass importantClassInstance;
Best Practices
Avoid Abbreviations
Avoid inventing acronyms or abbreviations, especially for multi-word names.
// Bad: unclear abbreviation
TexturePack tp;
int cnt;
// Good: clear, full names
TexturePack texturePack;
int counter;
Use of [[nodiscard]]
Only use [[nodiscard]] when ignoring the return value is likely to cause a bug:
// Good: Memory allocation must be handled
[[nodiscard]] void* allocateMemory(size_t size);
// Good: Error status should be checked
[[nodiscard]] bool connectToServer(const QString& host);
// Good: Function might be mistaken for having side effects
[[nodiscard]] int calculate(int a, int b);
// Bad: Plain getter doesn't need [[nodiscard]]
int getCount() const; // Not [[nodiscard]]
A plain getter is unlikely to cause confusion. Adding [[nodiscard]] to every getter creates clutter and inconsistency.
When to Rename
If you encounter names that don’t follow these conventions:
- Preferred: Leave them as-is to minimize review complexity and merge conflicts
- Acceptable: Rename them if you’re already refactoring the entire class
Unnecessary renames increase the number of changes, making reviews harder and increasing the likelihood of conflicts.
Static Analysis
clang-tidy
Most naming conventions are enforced by clang-tidy. Run it to check for violations:
clang-tidy path/to/file.cpp -- -I./include -I./src
The project includes a .clang-tidy configuration that checks:
- Naming conventions
- Code quality issues
- Potential bugs
- Performance problems
Running Checks in Nix
If using Nix, the project provides a formatting check:
This runs:
clang-format - C++ formatting
deadnix - Dead Nix code detection
nixfmt - Nix file formatting
statix - Nix static analysis
markdownlint - Markdown linting
Code Organization
Use #pragma once for header guards:
#pragma once
#include <QString>
class MyClass {
// ...
};
Brace Style
Functions have opening braces on a new line:
void myFunction()
{
if (condition) {
// if/else/for/while have braces on the same line
doSomething();
}
}
Constructor Initialization
Initializers break before the comma:
MyClass::MyClass(int value, QString name)
: m_value(value)
, m_name(std::move(name))
, m_initialized(true)
{
// Constructor body
}
Empty Functions and Records
Don’t split empty functions or records:
// Good
class Empty { };
void emptyFunction() { }
// Bad
class Empty {
};
Qt-Specific Guidelines
Q_DISABLE_COPY
For non-copyable classes:
class NonCopyable {
Q_DISABLE_COPY(NonCopyable)
public:
NonCopyable() = default;
};
Signals and Slots
class MyWidget : public QWidget {
Q_OBJECT
public:
explicit MyWidget(QWidget* parent = nullptr);
signals:
void dataChanged();
void errorOccurred(const QString& error);
private slots:
void onButtonClicked();
void handleTimeout();
private:
QPushButton* m_button;
};
Qt Deprecation Warnings
The project disables Qt deprecation warnings for APIs up to Qt 6.4:
// Set in CMakeLists.txt
-DQT_WARN_DEPRECATED_UP_TO=0x060400
-DQT_DISABLE_DEPRECATED_UP_TO=0x060400
Compiler Flags
Security
The build enables security features:
# All compilers
-fstack-protector-strong
--param=ssp-buffer-size=4
# Release builds
-D_FORTIFY_SOURCE=2
# Windows
-mguard=cf # Control Flow Guard
Optimization
# Release builds
-O2
-ffunction-sections
-fdata-sections
Pre-commit Checklist
Before committing, ensure:
Format your code
clang-format -i $(git diff --name-only | grep -E '\.(cpp|h)$')
Run clang-tidy
clang-tidy path/to/modified/file.cpp
Build successfully
cd build && cmake --build .
Further Reading