mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
refactor(Core/Misc): enforce east-const style and add codestyle check (#26492)
Co-authored-by: Ludwig <sudlud@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,30 @@ import re
|
||||
# Get the src directory of the project
|
||||
src_directory = os.path.join(os.getcwd(), 'src')
|
||||
|
||||
# Matches west-const declarations: "const <type> &" / "const <type> *".
|
||||
# <type> may be a (qualified) identifier, an optional unsigned/signed/long/short
|
||||
# prefix and an optional (single level of nested) template argument list.
|
||||
qualifier_align_regex = re.compile(
|
||||
r'\bconst\s+('
|
||||
r'(?:(?:unsigned|signed|long|short)\s+)*'
|
||||
r'(?:::)?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*'
|
||||
r'(?:\s*<[^<>;{}]*(?:<[^<>;{}]*>[^<>;{}]*)*>)?'
|
||||
r')\s*([&*])')
|
||||
|
||||
# Matches a raw string, line comment, block comment, string literal or char literal
|
||||
# (whichever starts first at any position, so // inside a string or " inside a comment
|
||||
# is handled). The raw string alternative comes first so R"delim(...)delim" - which may
|
||||
# contain unescaped quotes - is consumed whole rather than as a plain "..." string.
|
||||
literal_or_comment_regex = re.compile(
|
||||
r'R"([^()\\ \t\r\n]{0,16})\(.*?\)\1"'
|
||||
r'|//[^\n]*|/\*.*?\*/|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'', re.DOTALL)
|
||||
|
||||
# Replaces the contents of string/char literals and comments with spaces so the
|
||||
# qualifier-alignment check never matches text inside them. Whitespace (including
|
||||
# newlines) is preserved so line numbers stay accurate.
|
||||
def blank_non_code(text: str) -> str:
|
||||
return literal_or_comment_regex.sub(lambda m: re.sub(r'\S', ' ', m.group()), text)
|
||||
|
||||
# Global variables
|
||||
error_handler = False
|
||||
results = {
|
||||
@@ -16,7 +40,8 @@ results = {
|
||||
"GetTypeId() check": "Passed",
|
||||
"NpcFlagHelpers check": "Passed",
|
||||
"ItemFlagHelpers check": "Passed",
|
||||
"ItemTemplateFlagHelpers check": "Passed"
|
||||
"ItemTemplateFlagHelpers check": "Passed",
|
||||
"Qualifier alignment check": "Passed"
|
||||
}
|
||||
|
||||
# Main function to parse all the files of the project
|
||||
@@ -46,6 +71,7 @@ def parsing_file(directory: str) -> None:
|
||||
itemflag_helpers_check(file, file_path)
|
||||
if file_name != 'ItemTemplate.h':
|
||||
itemtemplateflag_helpers_check(file, file_path)
|
||||
qualifier_alignment_check(file, file_path)
|
||||
except UnicodeDecodeError:
|
||||
print(f"\nCould not decode file {file_path}")
|
||||
sys.exit(1)
|
||||
@@ -214,6 +240,24 @@ def itemtemplateflag_helpers_check(file: io, file_path: str) -> None:
|
||||
error_handler = True
|
||||
results["ItemTemplateFlagHelpers check"] = "Failed"
|
||||
|
||||
# Codestyle patterns enforcing east-const: "const T&" -> "T const&", "const T*" -> "T const*"
|
||||
def qualifier_alignment_check(file: io, file_path: str) -> None:
|
||||
global error_handler, results
|
||||
file.seek(0) # Reset file pointer to the beginning
|
||||
check_failed = False
|
||||
# Blank out strings/comments so we never match inside them, then check line by line
|
||||
masked_lines = blank_non_code(file.read()).split('\n')
|
||||
for line_number, line in enumerate(masked_lines, start = 1):
|
||||
for match in qualifier_align_regex.finditer(line):
|
||||
type_name, symbol = match.group(1).strip(), match.group(2)
|
||||
print(
|
||||
f"Please use the '{type_name} const{symbol}' syntax instead of 'const {type_name}{symbol}': {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
# Handle the script error and update the result output
|
||||
if check_failed:
|
||||
error_handler = True
|
||||
results["Qualifier alignment check"] = "Failed"
|
||||
|
||||
# Codestyle patterns checking for various codestyle issues
|
||||
def misc_codestyle_check(file: io, file_path: str) -> None:
|
||||
global error_handler, results
|
||||
@@ -229,14 +273,6 @@ def misc_codestyle_check(file: io, file_path: str) -> None:
|
||||
|
||||
# Parse all the file
|
||||
for line_number, line in enumerate(file, start = 1):
|
||||
if 'const auto&' in line:
|
||||
print(
|
||||
f"Please use the 'auto const&' syntax instead of 'const auto&': {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
if re.search(r'\bconst\s+\w+\s*\*\b', line):
|
||||
print(
|
||||
f"Please use the 'Class/ObjectType const*' syntax instead of 'const Class/ObjectType*': {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
if [match for match in [' if(', ' if ( '] if match in line]:
|
||||
print(
|
||||
f"Please use the 'if (XXXX)' syntax instead of 'if(XXXX)': {file_path} at line {line_number}")
|
||||
|
||||
Reference in New Issue
Block a user