refactor: processing flow, and classDefine record.

This commit is contained in:
2025-01-28 20:46:38 +08:00
parent 6d32c5064d
commit 96a4ed42d1
5 changed files with 136 additions and 87 deletions

View File

@@ -0,0 +1,80 @@
import util.cpp_language as CppUtil
_need_fix_includes_queue = dict()
_need_fix_members_queue = dict()
_class_defs_record = dict()
class ClassDefineRecord:
rpath = str()
is_template = bool()
is_empty = bool()
def __init__(self, rpath: str, is_template: bool, is_empty: bool):
self.rpath = rpath
self.is_template = is_template
self.is_empty = is_empty
def record_class_definition(
path: str, namespace: str, class_name: str, is_template: bool, is_empty: bool
):
assert len(path) > 0 and len(class_name) > 0
assert '::' not in class_name # c++ does not support forward declaration for nested class.
if namespace not in _class_defs_record:
_class_defs_record[namespace] = {}
assert class_name not in _class_defs_record[namespace], (
f'path = {path}, ns = {namespace}, cl = {class_name}'
)
_class_defs_record[namespace][class_name] = ClassDefineRecord(
path[path.find('src/') + 4 :], is_template, is_empty
)
def add_pending_fix_includes_queue(path: str, decls: list, member_typeset: list):
assert path not in _need_fix_includes_queue
if len(decls) > 0 and len(member_typeset) > 0:
_need_fix_includes_queue[path] = [decls, member_typeset]
def add_pending_fix_members_queue(path: str, member_typeset: list):
assert path not in _need_fix_members_queue
if len(member_typeset) > 0:
_need_fix_members_queue[path] = member_typeset
def _find_definition(decl: str, in_types: list) -> ClassDefineRecord | None:
find_decl = CppUtil.find_class_forward_declaration(decl)
assert find_decl
namespace = find_decl.namespace_decl
clazz = find_decl.class_decl
if not CppUtil.is_full_type_required_for_typeset(namespace, clazz, in_types):
return None
assert namespace in _class_defs_record, f'namespace not recorded, {namespace}'
assert clazz in _class_defs_record[namespace], f'{clazz} not recorded, in {namespace}'
return _class_defs_record[namespace][find_decl.class_decl]
def process():
# fix includes
for path, decl_and_types in _need_fix_includes_queue.items():
with open(path, 'r', encoding='utf-8') as file:
content = file.read()
for decl in decl_and_types[0]:
record = _find_definition(decl, decl_and_types[1])
if record:
include = f'#include "{record.rpath}"'
content = content.replace(decl, include)
with open(path, 'w', encoding='utf-8') as wfile:
wfile.write(content)
# fix members
# for path, types in _need_fix_members_queue.items():
# with open(path, 'r', encoding='utf-8') as file:
# content = file.read()
# with open(path, 'w', encoding='utf-8') as wfile:
# wfile.write(content)

View File

@@ -0,0 +1,14 @@
"""
Preprocessor for _HeaderOutputPredefine.h
"""
def process(path_to_file: str):
if path_to_file.endswith('_HeaderOutputPredefine.h'):
with open(path_to_file, 'r', encoding='utf-8') as file:
content = file.read()
content += '\n#include <winsock2.h>'
with open(path_to_file, 'w', encoding='utf-8') as wfile:
wfile.write(content)

View File

@@ -1,10 +1,10 @@
import os
import re
import predefine_subprocessor as PredefineProcessor
import util.cpp_language as CppUtil
import header_preprocessor as HeaderPreProcessor
import header_postprocessor as HeaderPostProcessor
from include_fixer import IncludeFixer
import util.cpp_language as CppUtil
class Options:
@@ -21,8 +21,14 @@ class Options:
restore_member_variable = bool()
# others
# only takes effect for TypedStorage, since the TypedStorage wrapper makes the full type unnecessary.
# * only takes effect for TypedStorage, since the TypedStorage wrapper makes the full type unnecessary.
fix_includes_for_member_variables = True
# * template definitions cannot be generated for headergen and may be wrong. class sizes may be wrong if
# * empty templates are used in TypedStorage.
# * this option will erase the type of the empty template (convert to uchar[size]).
fix_size_for_type_with_empty_template_class = True
# * this option will and add sizeof & alignof static assertions to members. (only takes effect for TypedStorage)
add_sizeof_alignof_static_assertions = True
def __init__(self, args):
self.base_dir = args.path
@@ -51,11 +57,10 @@ class Options:
self.set_variable(opt)
def process(path_to_file: str, include_fixer: IncludeFixer | None, args: Options):
def process(path_to_file: str, args: Options):
assert os.path.isfile(path_to_file)
if path_to_file.endswith('_HeaderOutputPredefine.h'):
PredefineProcessor.process(path_to_file)
return
RECORDED_THUNKS = []
@@ -128,7 +133,9 @@ def process(path_to_file: str, include_fixer: IncludeFixer | None, args: Options
continue
# restore member variable:
if args.restore_member_variable and '::ll::' in line: # union { ... };
if args.restore_member_variable and stripped_line.startswith(
'::ll::'
): # union { ... };
in_member_variable = True
is_modified = True
if in_member_variable and stripped_line.endswith(';'):
@@ -192,23 +199,29 @@ def process(path_to_file: str, include_fixer: IncludeFixer | None, args: Options
in_forward_declaration_list = True
if in_forward_declaration_list:
if (
stripped_line.startswith('class')
or stripped_line.startswith('struct')
or stripped_line.startswith('namespace')
stripped_line.startswith('class ')
or stripped_line.startswith('struct ')
or stripped_line.startswith('namespace ')
):
forward_declarations.append(stripped_line)
if stripped_line.startswith('// clang-format on') and in_forward_declaration_list:
in_forward_declaration_list = False
# record namespace & classes
if not in_forward_declaration_list and args.fix_includes_for_member_variables:
if line.startswith('class') or line.startswith(
'struct'
): # ignore nested class, FIXME: ignore template class
if not in_forward_declaration_list:
if line.startswith('class ') or line.startswith('struct '): # ignore nested class
founded = CppUtil.find_class_definition(line)
if founded:
include_fixer.record_class_definition(
path_to_file, '::'.join(current_namespace), founded
is_template = (
content[content.rfind('\n', 0, -1) :].strip().startswith('template ')
)
is_empty = stripped_line.endswith('{};')
HeaderPostProcessor.record_class_definition(
path_to_file,
'::'.join(current_namespace),
founded,
is_template,
is_empty,
)
founded = CppUtil.find_namespace_declaration(line)
if founded:
@@ -233,9 +246,13 @@ def process(path_to_file: str, include_fixer: IncludeFixer | None, args: Options
content += line
if is_modified:
if args.fix_includes_for_member_variables and has_typed_storage:
include_fixer.add_pending_fix_queue(
HeaderPostProcessor.add_pending_fix_includes_queue(
path_to_file, forward_declarations, member_variable_types
)
if args.fix_size_for_type_with_empty_template_class and has_typed_storage:
HeaderPostProcessor.add_pending_fix_members_queue(
path_to_file, member_variable_types
)
with open(path_to_file, 'w', encoding='utf-8') as wfile:
wfile.write(content)
@@ -243,12 +260,15 @@ def process(path_to_file: str, include_fixer: IncludeFixer | None, args: Options
def iterate(args: Options):
assert os.path.isdir(args.base_dir)
include_fixer = args.fix_includes_for_member_variables and IncludeFixer()
for root, dirs, files in os.walk(args.base_dir):
for file in files:
if CppUtil.is_header_file(file):
process(os.path.join(root, file), include_fixer, args)
path = os.path.join(root, file)
# preprocessing: execution time is before each file.
HeaderPreProcessor.process(path)
# processing: executed immediately after preprocessing is completed.
process(path, args)
if include_fixer:
include_fixer.run_fix()
# post-processing: executed after all files have been processed.
# during processing, files that require post-processing will be marked.
HeaderPostProcessor.process()

View File

@@ -1,52 +0,0 @@
import os
import util.cpp_language as CppUtil
class IncludeFixer:
_need_fix_queue = dict()
_class_defs_record = dict()
def __init__(self):
pass
def record_class_definition(self, path: str, namespace: str, class_name: str):
assert len(path) > 0 and len(class_name) > 0
assert '::' not in class_name # c++ does not support forward declaration for nested class.
if namespace not in self._class_defs_record:
self._class_defs_record[namespace] = {}
assert class_name not in self._class_defs_record[namespace]
self._class_defs_record[namespace][class_name] = path[path.find('src/') + 4 :]
def add_pending_fix_queue(self, path: str, decls: list, member_typeset: list):
assert os.path.isfile(path)
assert path not in self._need_fix_queue
if len(decls) > 0 and len(member_typeset):
self._need_fix_queue[path] = [decls, member_typeset]
def _find_definition(self, decl: str, in_types: list):
find_decl = CppUtil.find_class_forward_declaration(decl)
assert find_decl
namespace = find_decl.namespace_decl
clazz = find_decl.class_decl
if not CppUtil.is_full_type_required_for_typeset(namespace, clazz, in_types):
return None
assert namespace in self._class_defs_record, f'namespace not recorded, {namespace}'
assert clazz in self._class_defs_record[namespace], f'{clazz} not recorded, in {namespace}'
return self._class_defs_record[namespace][find_decl.class_decl]
def run_fix(self):
for path, decl_and_types in self._need_fix_queue.items():
with open(path, 'r', encoding='utf-8') as file:
content = file.read()
for decl in decl_and_types[0]:
define_location = self._find_definition(decl, decl_and_types[1])
if define_location:
include = f'#include "{define_location}"'
content = content.replace(decl, include)
with open(path, 'w', encoding='utf-8') as wfile:
wfile.write(content)

View File

@@ -1,13 +0,0 @@
"""
Preprocessor for _HeaderOutputPredefine.h
"""
def process(path_to_file: str):
with open(path_to_file, 'r', encoding='utf-8') as file:
content = file.read()
content += '\n#include <winsock2.h>'
with open(path_to_file, 'w', encoding='utf-8') as wfile:
wfile.write(content)