C++ code style
The root .clang-format is the formatting authority for C and C++ code. It began with the CLion code-style export and adds a small number of explicit repository conventions where the inherited LLVM defaults disagreed with the codebase. Keeping the file at the repository root allows CLion and command-line clang-format to discover it automatically.
Formatting
Use four spaces and never tabs for new or edited code.
Use attached pointer and reference declarators:
CE::Rendering::OpenGL::Texture* textureandconst CE::Assets::Grids::Definition& grid.Keep opening braces on the declaration or control-statement line.
Let the root formatter decide enum wrapping; short enums may fit on one line. Do not add comments to namespace-closing braces.
Short inline accessors may remain on one line; keep out-of-line function definitions expanded.
Treat 140 columns as the limit, matching the root configuration for clang-format 23+. Let
clang-formatdecide whether a declaration or expression fits on one line; do not manually align continuation lines.Preserve meaningful include groups. In a source file, put its matching header first, then other project or third-party headers, then standard-library headers, with blank lines between groups.
Format individual files with:
(
set -e
cd "$(git rev-parse --show-toplevel)"
clang-format -i path/to/file.cpp
)
To restrict formatting to uncommitted lines changed from HEAD, use the following
command. Substitute another base revision when needed:
(
set -e
cd "$(git rev-parse --show-toplevel)"
git clang-format HEAD
)
Code conventions
The project targets C++23. Prefer the standard library and current language features already used by the surrounding subsystem.
New headers use
#pragma once; do not add a second include guard.Prefer nested namespaces such as
namespace CE::Assetsand indent their contents.Types and enum values use
PascalCase. Functions, methods, and local variables usesnake_case.Private data members introduced in modernized code use a trailing underscore, such as
root_path_. Preserve established public APIs and legacy subsystem names rather than renaming them only for style.Mark converting constructors
explicit, and useoverrideorfinalwhere the relationship is known.Put data declarations above methods. Keep declaration and definition signatures on one line when they fit within 140 columns; wrap longer parameter lists as a block. Put constructor initializers on the following line, as specified by the root formatter configuration.
Add
[[nodiscard]]to query or factory functions when silently discarding the result is probably a mistake.Include what a file uses instead of relying on transitive includes.
Keep comments focused on invariants, ownership, coordinate systems, or other non-obvious intent. Avoid narrating code that is already clear.
Scope and tests
The repository contains older code written under several conventions. Apply the current style to new code and to lines materially changed by a task; avoid drive-by formatting of unrelated files. Do not reformat vendored code under extern/, the embedded POSH header (projects/engine/include/internals/posh.h), or generated build output.
Tests should follow the production subsystem they cover and use short, intuitive snake_case suite and test names. Let the suite identify the subsystem and name each case for its main scenario, usually in two to four words: input_routing.stale_focus_lease, opengl_upload.atlas_upload_failure. Keep detailed behavior in the test body instead of writing sentence-length names.
Consume relevant [[nodiscard]] results in assertions; explicitly discard an
irrelevant result with static_cast<void>(...), including exception assertions.
Normal behavior checks must not intentionally emit compiler warnings. Test expected
compiler diagnostics with isolated captured probes and narrow compiler/construct
suppression, retaining API attributes and target warning policy.