125 lines
3.8 KiB
Python
125 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Inlines method bodies from a .cpp file into the corresponding .h file.
|
|
|
|
Scans the .cpp for method definitions matching "ClassName::MethodName(...)"
|
|
and extracts the body (from opening '{' to closing '}'). Then reads the .h
|
|
file and replaces matching declaration-only lines (ending with ';') with the
|
|
declaration (minus ';') followed by the body.
|
|
|
|
Usage: python3 tools/inline-methods.py <header.h> <source.cpp>
|
|
|
|
Outputs the new header to stdout.
|
|
"""
|
|
|
|
import sys
|
|
import re
|
|
|
|
|
|
def extract_bodies(cpp_lines):
|
|
"""Extract method bodies from cpp file.
|
|
Returns dict of (ClassName, MethodName) -> list of body lines (from '{' to '}')."""
|
|
bodies = {}
|
|
i = 0
|
|
while i < len(cpp_lines):
|
|
# Match lines like: void UMCPHandler_Foo::Handle(...)
|
|
m = re.match(r'^\S.*?\s+(\w+)::(\w+)\s*\(', cpp_lines[i])
|
|
if not m:
|
|
i += 1
|
|
continue
|
|
|
|
class_name = m.group(1)
|
|
method_name = m.group(2)
|
|
|
|
# Skip forward to the line containing '{'
|
|
while i < len(cpp_lines) and '{' not in cpp_lines[i]:
|
|
i += 1
|
|
if i >= len(cpp_lines):
|
|
break
|
|
|
|
# Collect from '{' to matching '}'
|
|
brace_depth = 0
|
|
body_lines = []
|
|
while i < len(cpp_lines):
|
|
line = cpp_lines[i]
|
|
brace_depth += line.count('{') - line.count('}')
|
|
body_lines.append(line)
|
|
i += 1
|
|
if brace_depth == 0:
|
|
break
|
|
|
|
bodies[(class_name, method_name)] = body_lines
|
|
|
|
return bodies
|
|
|
|
|
|
def inline_into_header(h_lines, bodies):
|
|
"""Replace declaration-only methods in header with inlined bodies."""
|
|
output = []
|
|
for line in h_lines:
|
|
# Match declaration lines like:
|
|
# \tvirtual void Handle(const FJsonObject* Json, ...) override;
|
|
# Capture: indent, everything before method name, method name, rest up to ';'
|
|
m = re.match(r'^(\t+)(.*?\s+)(\w+)\s*(\(.*\)\s*(?:const\s*)?(?:override\s*)?);', line)
|
|
if m:
|
|
indent = m.group(1)
|
|
prefix = m.group(2) # e.g. "virtual void "
|
|
method_name = m.group(3)
|
|
params = m.group(4) # e.g. "(const FJsonObject* Json, FJsonObject* Result) override"
|
|
|
|
# Find which class we're inside
|
|
class_name = None
|
|
for prev in reversed(output):
|
|
cm = re.match(r'^class\s+(\w+)\s*', prev)
|
|
if cm:
|
|
class_name = cm.group(1)
|
|
break
|
|
|
|
if class_name and (class_name, method_name) in bodies:
|
|
body_lines = bodies[(class_name, method_name)]
|
|
# Emit the declaration as a definition (replace ';' with body)
|
|
output.append(f'{indent}{prefix}{method_name}{params}')
|
|
for bline in body_lines:
|
|
if bline.strip():
|
|
output.append(indent + bline)
|
|
else:
|
|
output.append('')
|
|
continue
|
|
|
|
output.append(line)
|
|
return output
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 3:
|
|
print(f"Usage: {sys.argv[0]} <header.h> <source.cpp>", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
h_path = sys.argv[1]
|
|
cpp_path = sys.argv[2]
|
|
|
|
with open(cpp_path) as f:
|
|
cpp_lines = [line.rstrip('\n') for line in f]
|
|
|
|
with open(h_path) as f:
|
|
h_lines = [line.rstrip('\n') for line in f]
|
|
|
|
bodies = extract_bodies(cpp_lines)
|
|
|
|
if not bodies:
|
|
print("No method bodies found in cpp file.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print(f"Found {len(bodies)} method(s) to inline:", file=sys.stderr)
|
|
for (cls, method) in bodies:
|
|
print(f" {cls}::{method}", file=sys.stderr)
|
|
|
|
result = inline_into_header(h_lines, bodies)
|
|
|
|
for line in result:
|
|
print(line)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|