ddnet/scripts/check_config_variables.py
Robert Müller 42b952bc6c Move config variables to config_variables.h, remove variables.h
The contents of `variables.h` are moved to `config_variables.h` instead of being included with the preprocessor. The file `variables.h` is removed, so all config variables can be found in a single file instead of being spread over two files without any clear structure. The original declaration order of config variables is preserved. The unnecessary header guard `GAME_VARIABLES_H` from `variables.h` is removed, as the comment `// This file can be included several times.` already serves the same purpose of silencing the header guard check.

A comment is added at the end of `config_variables.h` to mark the location where modders should ideally declare all of their own config variables to avoid merge conflicts with us in the future.

Closes #7472.
2023-11-25 16:40:55 +01:00

62 lines
2.2 KiB
Python
Executable file

#!/usr/bin/env python3
import os
import re
import sys
def read_all_lines(filename):
with open(filename, 'r', encoding='utf-8') as file:
return file.readlines()
def parse_config_variables(lines):
pattern = r'^MACRO_CONFIG_[A-Z]+\((.*?), (.*?),.*'
matches = {}
for line in lines:
match = re.match(pattern, line)
if match:
matches[match.group(1)] = match.group(2)
return matches
def generate_regex(variable_code):
return fr'(g_Config\.m_{variable_code}|Config\(\)->m_{variable_code}|m_pConfig->m_{variable_code})'
def find_config_variables(config_variables):
"""Returns the config variables which were not found."""
# Set of variables that have yet to be found.
variables_not_found = set(config_variables)
# Precompile regex for every config variable (~1.6x speedup).
regex_cache = {}
for variable_code in variables_not_found.copy():
regex_cache[variable_code] = re.compile(generate_regex(variable_code))
for root, _, files in os.walk('src'):
if not variables_not_found:
break
for file in files:
if not variables_not_found:
break
if file.endswith(('.cpp', '.h')) and not 'external' in root:
filepath = os.path.join(root, file)
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Only variables not yet found are searched in the remaining files (~3.6x speedup).
# Copy set to remove elements while iterating, which is slightly faster than collecting
# the elements to remove in another set and removing them after the loop.
for variable_code in variables_not_found.copy():
if regex_cache[variable_code].search(content):
variables_not_found.remove(variable_code)
return variables_not_found
def main():
lines = read_all_lines('src/engine/shared/config_variables.h')
config_variables = parse_config_variables(lines)
config_variables_not_found = find_config_variables(config_variables)
for variable_code in config_variables_not_found:
print(f'The config variable \'{config_variables[variable_code]}\' is unused.')
if config_variables_not_found:
print('Error: Unused config variables found.')
return 1
print('Success: No unused config variables found.')
return 0
if __name__ == '__main__':
sys.exit(main())