style: Convert leading spaces to tabs in GeneralsMD GameEngine#2563
style: Convert leading spaces to tabs in GeneralsMD GameEngine#2563bobtista wants to merge 2 commits intoTheSuperHackers:mainfrom
Conversation
|
| Filename | Overview |
|---|---|
| scripts/cpp/convert_leading_spaces_to_tabs.py | New tree-sitter-based Python script for converting leading spaces to tabs; well-structured with good edge-case handling, but has a minor bug in the mid-line /* detection that doesn't account for // line comments containing /*. |
| GeneralsMD/Code/GameEngine/Include/Common/BitFlags.h | Whitespace-only: leading spaces converted to tabs; confirmed by git diff -w producing no output. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp | Whitespace-only reformatting; all functional content unchanged. |
| GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h | Whitespace-only: leading spaces converted to tabs; access specifiers placed at class-brace level per codebase convention. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Read file as cp1252] --> B[Encode to UTF-8 bytes]
B --> C[Apply MACRO_EXPANSIONS for tree-sitter parsing]
C --> D[Parse with tree-sitter C++]
D --> E{Top-level parse errors > 10?}
E -- Yes --> F[Skip entire file]
E -- No --> G[Process lines]
G --> H{Inside block comment?}
H -- Yes --> I[Append unchanged / check for closing]
H -- No --> J{Starts with /*?}
J -- Yes --> K[Append unchanged / update in_block_comment]
J -- No --> L{ASM / macro continuation / blank / preprocessor?}
L -- Yes --> M[Append unchanged]
L -- No --> N{Leading whitespace already tabs only?}
N -- Yes --> O[Append unchanged]
N -- No --> P{Tabs-then-spaces alignment?}
P -- Yes --> Q[Append unchanged / skipped++]
P -- No --> R[Query tree-sitter AST for node at first non-WS char]
R --> S{Node in ERROR or continuation line?}
S -- Yes --> T[Append unchanged / skipped++]
S -- No --> U[get_indent_depth with special-case braces/case/access-specifiers]
U --> V{depth==0 but significant spaces?}
V -- Yes --> W[Append unchanged / skipped++]
V -- No --> X[Replace leading WS with depth tabs]
X --> Y[Track mid-line /* opens]
Y --> Z[Write file if changed]
Prompt To Fix All With AI
This is a comment left during a code review.
Path: scripts/cpp/convert_leading_spaces_to_tabs.py
Line: 419-424
Comment:
**`//` line comments containing `/*` trigger false block-comment mode**
`stripped.rfind('/*')` doesn't first strip the `//`-comment portion, so a line like `doFoo(); // see /* example` finds the `/*` inside the line comment, sees no closing `*/`, and sets `in_block_comment = True`. The following line is then left untouched (treated as block-comment content).
Since this script has already produced the committed output the practical impact is zero today, but if it is ever re-run the affected lines will be silently skipped. A guard against this would be to truncate `stripped` at the first `//` before doing the `rfind`:
```python
# Track mid-line block comment opens (e.g. /**< trailing doc comments)
code_part = stripped
double_slash = stripped.find('//')
if double_slash >= 0:
code_part = stripped[:double_slash]
last_open = code_part.rfind('/*')
if last_open >= 0:
after_open = code_part[last_open + 2:]
if '*/' not in after_open:
in_block_comment = True
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (6): Last reviewed commit: "style: Convert leading spaces to tabs in..." | Re-trigger Greptile
Skyaero42
left a comment
There was a problem hiding this comment.
Quick sample,
I've skipped the issue about documentation block comments - see other PR's for that.
| const AudioEventRTS *getSoundFalling() const { return getAudio(TTAUDIO_soundFalling); } | ||
|
|
||
| Bool hasSoundAmbient() const { return hasAudio(TTAUDIO_soundAmbient); } | ||
| Bool hasSoundAmbient() const { return hasAudio(TTAUDIO_soundAmbient); } |
| Bool hasSoundAmbient() const { return hasAudio(TTAUDIO_soundAmbient); } | ||
|
|
||
| const AudioEventRTS *getPerUnitSound(const AsciiString& soundName) const; | ||
| const AudioEventRTS *getPerUnitSound(const AsciiString& soundName) const; |
| UnsignedInt getThreatValue() const { return m_threatValue; } | ||
|
|
||
| //------------------------------------------------------------------------------------------------- | ||
| //------------------------------------------------------------------------------------------------- |
| //------------------------------------------------------------------------------------------------- | ||
| NameKeyType getMaxSimultaneousLinkKey() const { return m_maxSimultaneousLinkKey; } | ||
| UnsignedInt getMaxSimultaneousOfType() const; | ||
| //------------------------------------------------------------------------------------------------- |
| void validateAudio(); | ||
| const AudioEventRTS* getAudio(ThingTemplateAudioType t) const { return m_audioarray.m_audio[t] ? &m_audioarray.m_audio[t]->m_event : &s_audioEventNoSound; } | ||
| Bool hasAudio(ThingTemplateAudioType t) const { return m_audioarray.m_audio[t] != nullptr; } | ||
| Bool hasAudio(ThingTemplateAudioType t) const { return m_audioarray.m_audio[t] != nullptr; } |
| static void parseReplaceModule(INI *ini, void *instance, void *store, const void *userData); | ||
| static void parseInheritableModule(INI *ini, void *instance, void *store, const void *userData); | ||
| static void OverrideableByLikeKind(INI *ini, void *instance, void *store, const void *userData); | ||
| static void OverrideableByLikeKind(INI *ini, void *instance, void *store, const void *userData); |
f148578 to
bcfa380
Compare
Summary
git diff -wis empty)Access specifiers (
public:/private:/protected:) are placed at the classbrace level, matching the existing codebase convention.
Script
The formatting script is included in the PR for reference but is not intended
to be merged — it shows how the changes were generated.
See
scripts/cpp/convert_leading_spaces_to_tabs.pyfor details.Part 3 of 4 — GeneralsMD/Code/GameEngine/ (356 files).
See also: #2561, #2562, #2564.