diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2024-05-08 18:22:59 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-05-08 18:22:59 +0200 |
commit | 4778b24366fbcc216d9d59fafbbb7505c371dd1d (patch) | |
tree | 50aacf8bab9ce654952356dff875084bd9af7d03 /misc/scripts/header_guards.py | |
parent | 15d20000fafeb511e34f1687e5a1b68ace60b226 (diff) | |
parent | df969ff7426d61c8d32f3a89ec461b47b34e83b2 (diff) | |
download | redot-engine-4778b24366fbcc216d9d59fafbbb7505c371dd1d.tar.gz |
Merge pull request #91597 from Repiteo/ci/pre-commit-handle-everything
CI: Overhaul static checks to use `pre-commit`
Diffstat (limited to 'misc/scripts/header_guards.py')
-rw-r--r-- | misc/scripts/header_guards.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/misc/scripts/header_guards.py b/misc/scripts/header_guards.py new file mode 100644 index 0000000000..b554be5159 --- /dev/null +++ b/misc/scripts/header_guards.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +from pathlib import Path + +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) + +HEADER_CHECK_OFFSET = 30 +HEADER_BEGIN_OFFSET = 31 +HEADER_END_OFFSET = -1 + +changed = [] +invalid = [] + +for file in sys.argv[1:]: + with open(file, "rt", encoding="utf-8", newline="\n") as f: + lines = f.readlines() + + if len(lines) <= HEADER_BEGIN_OFFSET: + continue # Most likely a dummy file. + + if lines[HEADER_CHECK_OFFSET].startswith("#import"): + continue # Early catch obj-c file. + + split = file.split("/") # Already in posix-format. + + prefix = "" + if split[0] == "modules" and split[-1] == "register_types.h": + prefix = f"{split[1]}_" # Name of module. + elif split[0] == "platform" and (file.endswith("api/api.h") or "/export/" in file): + prefix = f"{split[1]}_" # Name of platform. + elif file.startswith("modules/mono/utils") and "mono" not in split[-1]: + prefix = "MONO_" + elif file == "servers/rendering/storage/utilities.h": + prefix = "RENDERER_" + + suffix = "" + if "dummy" in file and "dummy" not in split[-1]: + suffix = "_DUMMY" + elif "gles3" in file and "gles3" not in split[-1]: + suffix = "_GLES3" + elif "renderer_rd" in file and "rd" not in split[-1]: + suffix = "_RD" + elif split[-1] == "ustring.h": + suffix = "_GODOT" + + name = (f"{prefix}{Path(file).stem}{suffix}{Path(file).suffix}".upper() + .replace(".", "_").replace("-", "_").replace(" ", "_")) # fmt: skip + + HEADER_CHECK = f"#ifndef {name}\n" + HEADER_BEGIN = f"#define {name}\n" + HEADER_END = f"#endif // {name}\n" + + if ( + lines[HEADER_CHECK_OFFSET] == HEADER_CHECK + and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN + and lines[HEADER_END_OFFSET] == HEADER_END + ): + continue + + # Guards might exist but with the wrong names. + 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] = HEADER_CHECK + lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN + lines[HEADER_END_OFFSET] = HEADER_END + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + continue + + header_check = -1 + header_begin = -1 + header_end = -1 + pragma_once = -1 + objc = False + + for idx, line in enumerate(lines): + if not line.startswith("#"): + continue + elif line.startswith("#ifndef") and header_check == -1: + header_check = idx + elif line.startswith("#define") and header_begin == -1: + header_begin = idx + elif line.startswith("#endif") and header_end == -1: + header_end = idx + elif line.startswith("#pragma once"): + pragma_once = idx + break + elif line.startswith("#import"): + objc = True + break + + if objc: + continue + + if pragma_once != -1: + lines.pop(pragma_once) + lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) + lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) + lines.append("\n") + lines.append(HEADER_END) + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + continue + + if header_check == -1 and header_begin == -1 and header_end == -1: + # Guards simply didn't exist + lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) + lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) + lines.append("\n") + lines.append(HEADER_END) + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + continue + + if header_check != -1 and header_begin != -1 and header_end != -1: + # All prepends "found", see if we can salvage this. + if header_check == header_begin - 1 and header_begin < header_end: + lines.pop(header_check) + lines.pop(header_begin - 1) + lines.pop(header_end - 2) + if lines[header_end - 3] == "\n": + lines.pop(header_end - 3) + lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) + lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) + lines.append("\n") + lines.append(HEADER_END) + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + continue + + invalid.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) |