godot/misc/scripts/header_guards.py
2025-03-07 17:32:33 -06:00

89 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
if len(sys.argv) < 2:
print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.")
sys.exit(1)
changed = []
invalid = []
for file in sys.argv[1:]:
header_start = -1
header_end = -1
with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f:
lines = f.readlines()
for idx, line in enumerate(lines):
sline = line.strip()
if header_start < 0:
if sline == "": # Skip empty lines at the top.
continue
if sline.startswith("/**********"): # Godot header starts this way.
header_start = idx
else:
header_end = 0 # There is no Godot header.
break
else:
if not sline.startswith(("*", "/*")): # Not in the Godot header anymore.
header_end = idx + 1 # The guard should be two lines below the Godot header.
break
if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines):
invalid.append(file)
continue
if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"):
continue
# Might be using legacy header guards.
HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1
HEADER_END_OFFSET = len(lines) - 1
if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET:
invalid.append(file)
continue
if (
lines[HEADER_CHECK_OFFSET].startswith("#ifndef")
and lines[HEADER_BEGIN_OFFSET].startswith("#define")
and lines[HEADER_END_OFFSET].startswith("#endif")
):
lines[HEADER_CHECK_OFFSET] = "#pragma once"
lines[HEADER_BEGIN_OFFSET] = "\n"
lines.pop()
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
# Verify `#pragma once` doesn't exist at invalid location.
misplaced = False
for line in lines:
if line.startswith("#pragma once"):
misplaced = True
break
if misplaced:
invalid.append(file)
continue
# Assume that we're simply missing a guard entirely.
lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n")
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
if changed:
for file in changed:
print(f"FIXED: {file}")
if invalid:
for file in invalid:
print(f"REQUIRES MANUAL CHANGES: {file}")
sys.exit(1)