Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

## Next Release

### Features

#### CPP Rules

- Add `noPublicLeadingUnderscore` AST check flagging public member variables and member functions (including static and template ones) whose name starts with `_`, e.g. `int _count;` or `void _compute();` under `public:` (or under a `struct`'s default access) should drop the leading underscore. Private/protected members are never checked here, since that's the concern of `memberLeadingUnderscore`/`memberFunctionLeadingUnderscore`. Constructors/destructors, operator overloads/conversions, and methods overriding a base-class virtual method are always exempt, and members synthesized entirely by a macro invoked on the same source line are excluded too. Takes no configuration
- Add `classMemberOrder` AST check enforcing a fixed section order within each class/struct/union body: public, protected, then private member variables, followed by public, protected, then private member functions. Only in-class declarations count — out-of-line member-function definitions don't affect ordering — and declarations outside that list (nested types, `using` declarations, enums, friend declarations, ...) are ignored rather than resetting the sequence. Takes an optional `excluded_macros` list (e.g. `["Q_OBJECT"]`) so members/access-specifier changes synthesized by a named macro invocation are excluded from ordering entirely

<!-- insertion marker -->
## [0.7.0](https://github.com/repo/owner/releases/tag/0.7.0) - 2026-09-28

Expand Down
88 changes: 88 additions & 0 deletions docs/source/sections/ast_checks/enforce_class_member_order.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
classMemberOrder
=================

Flags a member variable or member function declared before a section that
must precede it. Within a single class/struct/union body (including
templates), the direct members must appear grouped, in exactly this order:

1. public member variables
2. protected member variables
3. private member variables
4. public member functions
5. protected member functions
6. private member functions

.. code-block:: cpp

class Widget {
public:
int size;

protected:
int flag;

private:
int count;

public:
void resize();

protected:
void hook();

private:
void compute();
};

class Bad {
private:
int count; // Bad — flagged, a private member variable

public:
int size; // before a public one.

void resize();

private:
void compute();

public:
void hook(); // Bad — flagged, a public member function after
// a private one.
};

A section may be skipped entirely (e.g. a class with no protected members
at all), but once a later section has started, an earlier one may not
reappear.

Only members declared lexically inside the class body count — an
out-of-line member-function definition (``void C::f() { ... }``) never
affects its class's ordering, only the in-class declaration does. Nested
types, ``using`` declarations, enums, friend declarations, and other
declarations not covered by the list above are ignored for ordering
purposes: they neither need to fit anywhere in particular nor reset the
sequence.

Configuration
--------------

Optional — exclude specific macros invoked inside a class body from
ordering entirely. Any member (or access-specifier change) synthesized by
a listed macro, matched by the macro's own name at its invocation line, is
skipped: it's neither flagged itself nor counted when checking what came
before or after it. Useful for macros such as Qt's ``Q_OBJECT`` that expand
to boilerplate members and their own access-specifier bookkeeping, whose
position isn't the author's choice.

.. code-block:: toml

[cpp.ast_check_config.classMemberOrder]
excluded_macros = ["Q_OBJECT", "MY_DECLARE_PROPERTY"]

Disabling
----------

.. code-block:: toml

[cpp]
ast_check_disabled_ids = ["classMemberOrder"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
noPublicLeadingUnderscore
===========================

Flags any data member or member function declared under a ``public:``
access specifier (or under no access specifier at all in a
``struct``/``union``) whose name starts with ``_``. Private/protected
members are never flagged here — that's the concern of
:doc:`memberLeadingUnderscore <enforce_member_leading_underscore>` and
:doc:`memberFunctionLeadingUnderscore
<enforce_member_function_leading_underscore>`.

.. code-block:: cpp

class Widget {
public:
int size; // Good.
int _size; // Bad — flagged, leading underscore on a public member.

void compute(); // Good.
void _compute(); // Bad — flagged, leading underscore on a public method.

private:
int _count; // Good — not checked here.
};

Constructors/destructors, operator overloads/conversions, and methods
overriding a base-class virtual method are always exempt, since their names
aren't the author's to change. A member synthesized entirely by a macro
invoked on that same source line is not flagged either — there is no
user-typed name to rename.

Configuration
--------------

This check takes no configuration.

Disabling
----------

.. code-block:: toml

[cpp]
ast_check_disabled_ids = ["noPublicLeadingUnderscore"]
10 changes: 10 additions & 0 deletions docs/source/sections/ast_checks/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ Available checks
* - :doc:`memberFunctionLeadingUnderscore <enforce_member_function_leading_underscore>`
- A private or protected member function not starting with ``_``.
- None
* - :doc:`noPublicLeadingUnderscore <enforce_no_public_leading_underscore>`
- A public member variable/function starting with ``_``.
- None
* - :doc:`classMemberOrder <enforce_class_member_order>`
- A member variable/function declared before a section that must
precede it (public/protected/private members, then
public/protected/private member functions).
- Optional (``excluded_macros``)
* - :doc:`paramNameForType <param_name_for_type>`
- A parameter of a configured type not using its canonical name.
- Required (``type_to_name``)
Expand All @@ -92,6 +100,8 @@ Available checks

enforce_member_leading_underscore
enforce_member_function_leading_underscore
enforce_no_public_leading_underscore
enforce_class_member_order
param_name_for_type
macro_replacement
no_global_using
Expand Down
Loading
Loading