style: Convert continuation lines to tabs in Generals#2571
style: Convert continuation lines to tabs in Generals#2571bobtista wants to merge 10 commits intoTheSuperHackers:mainfrom
Conversation
|
These should be rebased after 2561-2564 get merged, as they contain those changes. I couldn't set the base branch in github here because those branches only exist on my fork. |
|
| Filename | Overview |
|---|---|
| scripts/cpp/convert_leading_spaces_to_tabs.py | New tool driving the reformatting; two previously-flagged bugs (is_closing_delimiter_line misses compound delimiters like });, and mid-line /* inside // comments triggers false block-comment state) remain unaddressed. No GPL header. |
| Generals/Code/GameEngine/Source/Common/GlobalData.cpp | Whitespace-only: converts 2-space continuation lines to single tabs inside initializer lists and constructors. |
| Generals/Code/GameEngine/Include/Common/GlobalData.h | Whitespace-only: aligns member declarations inside preprocessor-guarded blocks to tabs. |
| Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | Whitespace-only: cleans mixed space/tab indentation in several method bodies to pure tabs. |
| Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp | Whitespace-only reformatting of continuation lines. |
| Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | Whitespace-only reformatting of continuation lines in W3D rendering code. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Read file as cp1252] --> B[Parse with tree-sitter C++ parser]
B --> C{Too many parse errors?}
C -- Yes --> D[Skip file]
C -- No --> E[Iterate lines]
E --> F{In block comment?}
F -- Yes --> G[Pass through unchanged]
F -- No --> H{In macro continuation?}
H -- Yes --> G
H -- No --> I{In asm block?}
I -- Yes --> G
I -- No --> J{Preprocessor directive?}
J -- Yes --> K[Pass through, update pp_depth]
J -- No --> L{Leading spaces only?}
L -- No --> G
L -- Yes --> M[Query AST node at col]
M --> N{Continuation line?}
N -- Yes --> O[depth = parent_depth + 1 or parent_depth if closing delimiter]
N -- No --> P[depth = get_indent_depth node]
O --> Q{Sanity check depth == 0?}
P --> Q
Q -- Fail --> G
Q -- Pass --> R[Write tabs x depth + content]
R --> S[Check for mid-line /* opening]
S --> E
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: 1
Comment:
**Missing GPL license header**
This is a newly created community file and has no license header in its prologue. Per the project's convention, newly created files should carry a copyright notice and, if applicable, the project's GPL header.
```suggestion
# Copyright 2026 TheSuperHackers
#
# This file is part of the Command & Conquer Generals open-source project.
# ... (GPL header) ...
"""
```
**Rule Used:** Only flag missing GPL license headers in file prol... ([source](https://app.greptile.com/review/custom-context?memory=1cd6ffcb-aeb0-457d-899f-184a39b97b1e))
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "style: Preserve indentation inside prepr..." | Re-trigger Greptile
| lines = content.split('\n') | ||
| # Preserve original line endings | ||
| if content.endswith('\n'): | ||
| lines = lines[:-1] # split adds an empty string after trailing \n | ||
|
|
||
| code_bytes = content.encode('utf-8') | ||
| parse_bytes = preprocess_for_parsing(code_bytes) |
There was a problem hiding this comment.
/* inside // comments falsely opens block-comment state
stripped.rfind('/*') runs on the already-lstripped line content without first checking whether the /* appears after a //. A line like code(); // relies on /* old trick */ would set in_block_comment = True (since the */ is in the after_open slice but not correctly attributed), or if the */ were absent it would definitely set the flag — causing the immediately following line to be left un-converted. Consider skipping the mid-line /* check when a // precedes it:
# Track mid-line block comment opens (e.g. /**< trailing doc comments)
line_comment_pos = stripped.find('//')
last_open = stripped.rfind('/*')
if last_open >= 0 and (line_comment_pos < 0 or last_open < line_comment_pos):
after_open = stripped[last_open + 2:]
if '*/' not in after_open:
in_block_comment = TruePrompt To Fix With AI
This is a comment left during a code review.
Path: scripts/cpp/convert_leading_spaces_to_tabs.py
Line: 176-182
Comment:
**`/*` inside `//` comments falsely opens block-comment state**
`stripped.rfind('/*')` runs on the already-lstripped line content without first checking whether the `/*` appears after a `//`. A line like `code(); // relies on /* old trick */` would set `in_block_comment = True` (since the `*/` is in the `after_open` slice but not correctly attributed), or if the `*/` were absent it would definitely set the flag — causing the immediately following line to be left un-converted. Consider skipping the mid-line `/*` check when a `//` precedes it:
```python
# Track mid-line block comment opens (e.g. /**< trailing doc comments)
line_comment_pos = stripped.find('//')
last_open = stripped.rfind('/*')
if last_open >= 0 and (line_comment_pos < 0 or last_open < line_comment_pos):
after_open = stripped[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.|
|
||
|
|
||
| def is_closing_delimiter_line(stripped): | ||
| """Check if a line is just a closing delimiter, possibly with trailing punctuation. | ||
|
|
||
| Matches lines like ')', ');', ') {', ']);', etc. | ||
| These should be at the parent statement's depth, not +1. |
There was a problem hiding this comment.
is_closing_delimiter_line misses compound closing delimiters
stripped.rstrip(';,{ ') strips trailing punctuation but stops before ). So }); produces remainder }), which is not in the recognized set (')', ']', '}'). Any line that closes both a brace and a parenthesis (e.g. closing a lambda-style init block or a chained call) would be treated as a continuation body line (depth+1) instead of a closing delimiter (depth+0), leaving it one tab too deeply indented.
def is_closing_delimiter_line(stripped):
s = stripped.rstrip(';,{ ')
# strip any number of interleaved closing delimiters, e.g. '})' or '])'
s = s.rstrip(')]}')
return s == '' or s in (')', ']', '}')Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/cpp/convert_leading_spaces_to_tabs.py
Line: 147-153
Comment:
**`is_closing_delimiter_line` misses compound closing delimiters**
`stripped.rstrip(';,{ ')` strips trailing punctuation but stops before `)`. So `});` produces remainder `})`, which is not in the recognized set `(')', ']', '}')`. Any line that closes both a brace and a parenthesis (e.g. closing a lambda-style init block or a chained call) would be treated as a continuation body line (depth+1) instead of a closing delimiter (depth+0), leaving it one tab too deeply indented.
```python
def is_closing_delimiter_line(stripped):
s = stripped.rstrip(';,{ ')
# strip any number of interleaved closing delimiters, e.g. '})' or '])'
s = s.rstrip(')]}')
return s == '' or s in (')', ']', '}')
```
How can I resolve this? If you propose a fix, please make it concise.
Summary
git diff -wis empty)Note on diff size
This PR currently shows a large diff because it includes Phase 1-3 changes
(#2561-#2564) in its branch history. After those PRs merge and this is
rebased onto main, the diff will shrink to just the continuation line delta.
Both parts
Script
The formatting script is included for reference. See
scripts/cpp/convert_leading_spaces_to_tabs.py.