Skip to content

style: apply automated formatting baseline with clang-format#2638

Open
DevGeniusCode wants to merge 7 commits intoTheSuperHackers:mainfrom
DevGeniusCode:clang/step1-whitespace
Open

style: apply automated formatting baseline with clang-format#2638
DevGeniusCode wants to merge 7 commits intoTheSuperHackers:mainfrom
DevGeniusCode:clang/step1-whitespace

Conversation

@DevGeniusCode
Copy link
Copy Markdown

@DevGeniusCode DevGeniusCode commented Apr 20, 2026

Prerequisites: Please Merge First

This PR is the final step of the formatting baseline. It depends on two preliminary structural PRs that must be merged first to ensure a clean, 100% automated formatting pass without breaking VC6 compilation:

  1. refactor: Extract nested templates into typedefs for legacy compatibility #2642 - Extracts nested templates to prevent >> merging in C++98.
  2. refactor: Eliminate macro-split assignments #2641 - Eliminates macro-split assignments for clean AST parsing.

Objective

This PR introduces a minimalist, non-destructive .clang-format baseline. To make this easy to review and discuss, I have scoped the formatting only to the .\Core\GameEngine directory.

The "Do No Harm" Approach

The primary goal of this configuration is to avoid the "destructive" behavior of standard formatters.

  • ColumnLimit: 0: Automatic line wrapping is completely disabled. Clang-format will respect our manual line breaks and will not pack or split arguments unexpectedly.

What is being formatted?

To establish a consistent baseline, the formatter enforces a few core rules:

  1. Tabs & Indentation: Enforces Tabs for indentation with a width of 2.
  2. Braces (Allman Style): Standardizes to the Allman style (braces on new lines).
    Why this change was made -now-: clang-format fundamentally requires a brace style to function; it cannot simply "ignore" braces even on a pure whitespace pass. Since running the tool was inevitably going to touch braces and affect line counts anyway, I decided to "go all in" and establish a fully consistent style across the board, rather than trying to fight the tool to maintain an inconsistent legacy mix.
  3. Pointers: Enforces Left-aligned pointers (e.g., void* ptr).
  4. Trailing Comments: Vertical alignment is disabled (AlignTrailingComments: false) with a fixed 5-space offset. This prevents "diff pollution" (the ripple effect where adding one long function name forces all surrounding comments to shift).
  5. Escaped Newlines: Macro line continuations (\) are left-aligned (AlignEscapedNewlines: DontAlign) with a single space. This eliminates the "mixed whitespace" anti-pattern and ensures macros render perfectly straight in GitHub and all IDEs, regardless of the user's tab width setting.

Legacy / VC6 Compatibility

A lot of effort went into making sure this doesn't break our legacy support:

  • Zero Manual Overrides: Because the structural blockers (nested templates and macro splits) are handled in the prerequisite PRs, this configuration successfully parses and formats the legacy codebase automatically. We use Standard: c++20 to correctly parse modern syntax while maintaining VC6 compatibility structurally.
  • Macro Handling: I added custom rules (AttributeMacros and Macros) to safely parse our CPP_11 enum macros without breaking the formatting tree.
  • Short Blocks: Kept AllowShortBlocksOnASingleLine: Always so macros and empty stubs aren't vertically bloated.

Future Phases (Minimizing the Initial Diff)

Please note that several settings in this baseline (such as SortIncludes: false, AllowShortFunctionsOnASingleLine: All, and AllowShortBlocksOnASingleLine: Always) are intentionally included purely to minimize the initial diff and avoid overwhelming changes.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR introduces a .clang-format baseline scoped to Core/GameEngine (283 files), applying Allman-style braces, tab indentation (width 2), and left-aligned pointers while disabling line wrapping and include sorting to minimize the initial diff.

  • Standard: c++20 not updated: The in-thread reply acknowledged changing this to c++03, but the committed file still reads c++20. This also invalidates the prior dismissal of the SpacesInAngles concern, since that reasoning was conditioned on c++03 being set.
  • AllowShortBlocksOnASingleLine: Always conflicts with the team's debugger-breakpoint rule: The codebase standard requires statement bodies on separate lines; this setting actively prevents the formatter from enforcing that for existing single-line braced blocks.

Confidence Score: 4/5

Not ready to merge until Standard: c++20 is corrected to c++03 and AllowShortBlocksOnASingleLine is revisited.

Two P1 issues in the config file: the Standard key contradicts the in-thread promise and leaves the SpacesInAngles VC6 guard unapplied, while AllowShortBlocksOnASingleLine: Always conflicts with the team's codified debugger-breakpoint rule. All 283 source-file changes are formatting-only with no logic impact, so fixing the config is the only remaining blocker.

.clang-format requires both fixes before the formatting applied to the 283 source files can be considered safe for re-runs.

Important Files Changed

Filename Overview
.clang-format Introduces the clang-format baseline config; two P1 issues: Standard is still c++20 (not c++03 as promised in-thread), and AllowShortBlocksOnASingleLine: Always conflicts with the team's debugger-breakpoint style rule.
Core/GameEngine/Source/Common/System/AsciiString.cpp Formatting-only changes (Allman braces, tab indentation); no logic changes detected.
Core/GameEngine/Source/Common/System/GameMemory.cpp Formatting-only changes; tab/brace style applied uniformly with no logic alterations.
Core/GameEngine/Source/GameClient/GUI/GameWindow.cpp Formatting-only changes (Allman braces, indentation); no behavioral differences introduced.
Core/GameEngine/Source/GameNetwork/Connection.cpp Formatting-only changes; network logic untouched.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Developer runs clang-format] --> B{.clang-format config}
    B --> C["Standard: c++20 ⚠️ Should be c++03"]
    B --> D["ColumnLimit: 0 — no line wrapping"]
    B --> E["BreakBeforeBraces: Custom — Allman style"]
    B --> F["AllowShortBlocksOnASingleLine: Always ⚠️ Conflicts with rule 16b9b669"]
    C --> G["C++20 parser may collapse nested template brackets"]
    G --> H["VC6 template compilation may break"]
    F --> I["Single-line braced blocks preserved by formatter"]
    I --> J["Violates debugger-breakpoint placement rule"]
    E --> K["AfterControlStatement: Always — braces on new lines"]
    D --> L["Manual line breaks preserved across 283 files"]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .clang-format
Line: 23

Comment:
**`Standard: c++20` not updated despite in-thread acknowledgement**

The reply to the previous reviewer confirmed this was "changed to c++03", but the file still reads `Standard: c++20`. This matters beyond style: the thread also dismissed the missing `SpacesInAngles: Leave` concern by saying "is fine by Standard: c++03" — that reasoning only holds if the standard is actually set to c++03. With c++20 still in effect, the formatter may collapse `> >` to `>>` in template declarations, breaking compilation on VC6/early MSVC.

```suggestion
Standard: c++03
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: .clang-format
Line: 70

Comment:
**`AllowShortBlocksOnASingleLine: Always` conflicts with the codebase's debugger-breakpoint rule**

The team's coding standard requires that if/else/for/while statement bodies always appear on a separate line from the condition, specifically to allow precise debugger breakpoint placement. With `AllowShortBlocksOnASingleLine: Always`, clang-format will not split existing single-line braced blocks (e.g. `if (a) { b; }`), leaving them on one line indefinitely — directly conflicting with this rule. The safer value is `Empty`, which only collapses genuinely empty blocks (`{}`) while leaving single-statement blocks to be expanded by `AfterControlStatement: Always`.

**Rule Used:** Always place if/else/for/while statement bodies on... ([source](https://app.greptile.com/review/custom-context?memory=16b9b669-b823-49be-ba5b-2bd30ff3ba6d))

**Learned From**
[TheSuperHackers/GeneralsGameCode#2067](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2067#discussion_r2706274626)

How can I resolve this? If you propose a fix, please make it concise.

Reviews (4): Last reviewed commit: "style: standardize assignment operator i..." | Re-trigger Greptile

Comment thread .clang-format
Comment thread .clang-format
Copy link
Copy Markdown

@Skyaero42 Skyaero42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First initial impression.

Generic comment:

Tabs & Indentation: Enforces Tabs for indentation with a width of 2.

This is an incorrect description. Indentation width of tabs is determined by the IDE. VS defaults to 2.

Comment thread Core/GameEngine/Include/Common/AudioEventRTS.h Outdated
Comment thread Core/GameEngine/Include/Common/ArchiveFileSystem.h Outdated
Comment thread Core/GameEngine/Include/Common/AudioSettings.h Outdated
Comment thread Core/GameEngine/Include/Common/CRCDebug.h
Comment thread Core/GameEngine/Source/Common/CRCDebug.cpp
@DevGeniusCode DevGeniusCode force-pushed the clang/step1-whitespace branch from a9d279e to 9ddb58a Compare April 20, 2026 16:36
Comment thread .clang-format
@DevGeniusCode
Copy link
Copy Markdown
Author

DevGeniusCode commented Apr 21, 2026

There are still a few formatting improvements I haven’t addressed in this pass, such as consecutive assignment alignment.

Current (Before):

AudioAffect_Music = 0x01,
AudioAffect_Sound = 0x02,
AudioAffect_Sound3D = 0x04,
AudioAffect_All = (Music | Sound | Sound3D),

Target (After):

AudioAffect_Music   = 0x01,
AudioAffect_Sound   = 0x02,
AudioAffect_Sound3D = 0x04,
AudioAffect_All     = (Music | Sound | Sound3D),

If there is interest, I can implement it

{ \
DebugLogRaw m; \
} \
} while (0)
Copy link
Copy Markdown
Author

@DevGeniusCode DevGeniusCode Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GitHub interface uses 4-space tabs, so the backslashes are visually misaligned

Image

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like an argument for indenting with spaces to me, but I realise that will bloat the diff significantly so isn't really in scopde for the first pass.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that the backslashes shouldn't be aligned with spaces in the first place.

This is not a github only problem, but every IDE that has a tab size setting other then 2.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can be aligned to the right with spaces when leading tabs become spaces.

Copy link
Copy Markdown
Author

@DevGeniusCode DevGeniusCode Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also possible to disable the alignment

before

#define DEBUG_LOG_LEVEL(l, m) \
  do..........................\
  {...........................\
    if (l & DebugLevelMask)...\

after

#define DEBUG_LOG_LEVEL(l, m) \
  do \
  { \
    if (l & DebugLevelMask) \
    { \
      DebugLog m; \
    } \
  } while (0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless tabs turn into spaces, I think disabling alignment is the best approach.

I think in general, complex logic shouldn't be in a macro, but in an actual function.

@DevGeniusCode DevGeniusCode changed the title Proposal: Minimalist Code Formatting Baseline (Scoped to Core\GameEngine) Proposal: Minimalist Code Formatting Baseline using clang-format (Scoped to Core\GameEngine) Apr 21, 2026
@xezon
Copy link
Copy Markdown

xezon commented Apr 21, 2026

AudioAffect_Music = 0x01,
AudioAffect_Sound = 0x02,
AudioAffect_Sound3D = 0x04,
AudioAffect_All = (Music | Sound | Sound3D),

This is good.

Copy link
Copy Markdown

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does look promising.

Comment thread Core/GameEngine/Include/Common/ArchiveFile.h Outdated
Comment thread Core/GameEngine/Include/Common/FileSystem.h
Comment thread Core/GameEngine/Include/Common/FileSystem.h Outdated
Comment thread Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp Outdated
Comment thread Core/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp Outdated
@DevGeniusCode DevGeniusCode changed the title Proposal: Minimalist Code Formatting Baseline using clang-format (Scoped to Core\GameEngine) Proposal: Minimalist Code Formatting Baseline using clang-format (Scoped to Core\GameEngine) Apr 22, 2026
@DevGeniusCode
Copy link
Copy Markdown
Author

Updated

Comment thread .clang-format
@DevGeniusCode DevGeniusCode changed the title Proposal: Minimalist Code Formatting Baseline using clang-format (Scoped to Core\GameEngine) style: apply automated formatting baseline with clang-format Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants