Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/PrismLauncher/PrismLauncher/llms.txt

Use this file to discover all available pages before exploring further.

Prism Launcher follows specific code style conventions to maintain consistency across the codebase. All contributors must adhere to these guidelines.

Automatic Formatting

All C++ files are formatted with clang-format using the configuration in .clang-format.
Always run clang-format on changed files before committing!

Running clang-format

# 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

clang-format Configuration

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

Use camelCase with m_ prefix:
class ImportantClass {
   private:
    int m_counter;
    QString m_userName;
    std::vector<int> m_dataPoints;
};

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:
nix flake 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

Header Files

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:
1

Format your code

clang-format -i $(git diff --name-only | grep -E '\.(cpp|h)$')
2

Run clang-tidy

clang-tidy path/to/modified/file.cpp
3

Build successfully

cd build && cmake --build .
4

Run tests

cd build && ctest

Further Reading