Skip to main content
Consistent code style makes a large, multi-contributor codebase much easier to read, review, and maintain. Ladybird enforces low-level formatting automatically via 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.
Use CamelCase (capitalize the first letter, including all letters in an acronym) for class, struct, and namespace names.
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.
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.
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 m_ prefix is omitted:
  • 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.
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, prefer class 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 named the() 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.
For comments in spec-implementation code, verbatim spec notes use the NOTE: prefix; developer notes use NB:. Spec questions are wrapped in double square brackets: [[ ... ]].

Virtual Methods

Every overriding method must include both the virtual 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 to printf() 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:
Use {{ to emit a literal {:
Arguments can be referenced by index to reorder or repeat them:

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.

Formatting Custom Types

Provide a specialisation of AK::Formatter<YourType> to make a type formattable:
Use 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.