Consistent code style makes a large, multi-contributor codebase much easier to read, review, and maintain. Ladybird enforces low-level formatting automatically viaDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ladybirdBrowser/ladybird/llms.txt
Use this file to discover all available pages before exploring further.
clang-format, while this document defines the higher-level naming
conventions, structural rules, and patterns that the formatter cannot check. All new C++ code must conform to both.
Automated Formatting with clang-format
All Ladybird C++ code is formatted according to the.clang-format file in the project root. The CI pipeline
rejects any commit that does not match the expected output of the enforced clang-format version.
Use the exact
clang-format version enforced by CI. The version is specified in
Meta/Linters/lint_clang_format.py.
If your OS distribution does not ship the correct version, see
AdvancedBuildInstructions.md
for instructions on obtaining it.Naming Conventions
Ladybird uses a combination of CamelCase, snake_case, and SCREAMING_CASE depending on context.Classes, Structs, and Namespaces — CamelCase
Classes, Structs, and Namespaces — CamelCase
Use CamelCase (capitalize the first letter, including all letters in an acronym) for class, struct, and namespace
names.
Variables and Functions — snake_case
Variables and Functions — snake_case
Use snake_case (all lowercase, words separated by underscores) for variable and function names.Use full words; only abbreviate when the shortened form is more canonical than the full word.
Constants — SCREAMING_CASE
Constants — SCREAMING_CASE
Use SCREAMING_CASE for both global and static member constants.Prefer
const to #define. #defined constants that must exist should also use all-uppercase names with
underscores.Member Prefixes — m_, s_, g_
Member Prefixes — m_, s_, g_
Data members in C++ classes must be private. Apply the following prefixes:
For structs (data-only types without methods), everything may be public and the
| Prefix | Applies to |
|---|---|
m_ | Regular instance members |
s_ | Static data members |
g_ | Global variables |
m_ prefix is omitted:Getters, Setters, and ensure_ Functions
Getters, Setters, and ensure_ Functions
- Precede setters with
set_. Use bare words for getters. Names must match the underlying member. - Precede out-argument getters with
get_. - When two getters exist and one lazily initialises the object, prefix it with
ensure_; it must return a reference.
Spec Alignment — Match the Spec Name
Spec Alignment — Match the Spec Name
When implementing a spec algorithm or construct that has an explicit name in the spec text, prefer matching that name
as closely as possible.Given the construct at
https://html.spec.whatwg.org/…#suffering-from-being-missing:
Classes and Structs
For types that have methods, preferclass over struct. Classes should expose public getters and setters while
keeping data members private with the m_ prefix. Structs should have all-public data with no m_ prefix.
Use a constructor for implicit type conversion only when the argument is reasonably thought of as a type conversion and
the conversion is fast. Otherwise, use the explicit keyword or a named factory function.
Singleton Pattern
Use a static member function namedthe() to access a singleton instance:
Pointers and References
Write pointer and reference types with no space between the type name and* or &. Pass out arguments by reference;
use a pointer only when the argument is optional.
Const Placement
Ladybird uses east const style:const appears to the right of the type it qualifies.
Casts
Do not use C-style casts. Use the appropriate C++ cast operator (static_cast, reinterpret_cast, bit_cast,
dynamic_cast, const_cast). The only exception is marking an unused parameter with (void)parameter;.
Comments
- Use
//for all comments; reserve/* */for copyright notices. - Write comments as proper sentences (capital first letter, ending punctuation).
- Use
FIXME:(without attribution) for items that need future work;TODO:is also permitted. - Explain why the code does something, not what it does — the code itself should make what clear.
- Wrap long comments at approximately 120 characters.
NOTE: prefix; developer notes use NB:.
Spec questions are wrapped in double square brackets: [[ ... ]].
Virtual Methods
Every overriding method must include both thevirtual keyword and either override or final:
Header Guards
Use#pragma once instead of #define/#ifdef include guards.
String Formatting
Ladybird provides its own string-formatting facilities that work similarly toprintf() but are checked at compile
time. The primary entry points are ByteString::formatted(), StringBuilder::appendff(), and dbgln().
Basic Usage
Any{} placeholder in the format string is replaced by the corresponding argument, converted to its string form:
{{ to emit a literal {:
Format Specifiers
Add a colon after the optional index to specify formatting options. In order, a format specifier may contain: fill character + alignment, sign,# (alternate form), 0 (zero-pad), width, precision, and type.
| Type specifier | Effect | Example output |
|---|---|---|
| (nothing) | Default format | Anything! |
b | Binary | 110, 0b000110 |
d | Decimal | 42, +0000042 |
o | Octal | 043 |
x | Hexadecimal | ff0, 0x00000ff0 |
X | Hexadecimal uppercase | FF0, 0X00000FF0 |
c | Character | a |
s | String | well, hello friends! |
p | Pointer | 0xdeadc0de |
f | Float | 1.234, -inf |
hex-dump | Hexadecimal dump | fdfdfdfd |
Formatting Custom Types
Provide a specialisation ofAK::Formatter<YourType> to make a type formattable:
AK::HasFormatter<T> to detect at compile time whether a type can be formatted, and FormatIfSupported<T> to
safely format a value that may or may not have a Formatter specialisation.