refactor: move is_full_type_required into CppUtils.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
import util.cpp_language as CppUtil
|
||||
|
||||
@@ -32,7 +31,7 @@ class IncludeFixer:
|
||||
namespace = find_decl.namespace_decl
|
||||
clazz = find_decl.class_decl
|
||||
|
||||
if not _is_full_type_needed(namespace, clazz, in_types):
|
||||
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}'
|
||||
@@ -51,114 +50,3 @@ class IncludeFixer:
|
||||
content = content.replace(decl, include)
|
||||
with open(path, 'w', encoding='utf-8') as wfile:
|
||||
wfile.write(content)
|
||||
|
||||
|
||||
def _is_full_type_needed(namespace_decl: str, class_decl: str, in_types: list):
|
||||
# Y: T
|
||||
# Y: std::optional<T>
|
||||
# Y: std::variant<T>
|
||||
# Y: std::array<T, _>
|
||||
# Y: std::pair<T, T>
|
||||
# Y: std::unordered_set<T>
|
||||
# Y: std::unordered_map<T, _>
|
||||
# Y: std::deque<T> // under msstl only
|
||||
# Y: std::queue<T> // under msstl only
|
||||
# N: T&
|
||||
# N: T*
|
||||
# N: std::map<T, T>
|
||||
# N: std::shared_ptr<T>
|
||||
# N: std::unique_ptr<T>
|
||||
# N: std::weak_ptr<T>
|
||||
# N: std::vector<T>
|
||||
# N: std::set<T>
|
||||
# N: std::unordered_map<_, T>
|
||||
# N: std::function<T(T)>
|
||||
|
||||
def is_subtk_ends_with(full: str, tk: str, whats: list):
|
||||
founded = False
|
||||
for matched in re.finditer(rf'\b{re.escape(tk)}\b', full):
|
||||
founded = True
|
||||
if len(full) > matched.end():
|
||||
for what in whats:
|
||||
if full[matched.end() : matched.end() + len(what)] == what:
|
||||
return founded, True
|
||||
return founded, False
|
||||
|
||||
def find_template_name(full: str, what: str):
|
||||
for matched in re.finditer(rf'\b{re.escape(what)}\b', full):
|
||||
endpos = matched.start()
|
||||
while True:
|
||||
r_angle_bracket_pos = full.rfind('>', 0, endpos)
|
||||
l_angle_bracket_pos = full.rfind('<', 0, endpos)
|
||||
if l_angle_bracket_pos == -1:
|
||||
return None
|
||||
if r_angle_bracket_pos > l_angle_bracket_pos:
|
||||
endpos = l_angle_bracket_pos
|
||||
continue
|
||||
ret = full[:l_angle_bracket_pos]
|
||||
matched_non_name = list(re.finditer(r'[^a-zA-Z_]', ret))
|
||||
if len(matched_non_name) > 0:
|
||||
ret = ret[matched_non_name[-1].start() + 1 :]
|
||||
assert len(ret) > 0
|
||||
return ret
|
||||
|
||||
return None
|
||||
|
||||
for type_name in in_types:
|
||||
founded, endswith = is_subtk_ends_with(
|
||||
type_name, class_decl, ['&', '*', ' const&', ' const*']
|
||||
)
|
||||
# is not reference or pointer type
|
||||
if founded and not endswith:
|
||||
# is template parameter?
|
||||
template_name = find_template_name(type_name, class_decl)
|
||||
if template_name:
|
||||
if template_name in [ # NOT Need full type.
|
||||
'map',
|
||||
'shared_ptr',
|
||||
'unique_ptr',
|
||||
'weak_ptr',
|
||||
'vector',
|
||||
'queue',
|
||||
'set',
|
||||
'function',
|
||||
]:
|
||||
pass # don't return false directly
|
||||
elif template_name in [ # Need full type.
|
||||
'optional',
|
||||
'variant',
|
||||
'array',
|
||||
'pair',
|
||||
'unordered_set',
|
||||
'deque',
|
||||
'queue',
|
||||
]:
|
||||
return True
|
||||
elif template_name in [ # EMPTY TEMPLATE CLASS
|
||||
'ScriptFilteredEventSignal',
|
||||
'OwnerPtr',
|
||||
'UniqueOwnerPointer',
|
||||
'NotNullNonOwnerPtr',
|
||||
'NonOwnerPointer',
|
||||
'ServiceRegistrationToken',
|
||||
'IDType',
|
||||
'WeakRef',
|
||||
'SubChunkStorage',
|
||||
'ServiceReference',
|
||||
'typeid_t',
|
||||
'List',
|
||||
'MemoryPool',
|
||||
'ThreadOwner',
|
||||
'StrongTypedObjectHandle',
|
||||
'Promise',
|
||||
'Factory',
|
||||
'Publisher',
|
||||
'ServiceRegistrationToken',
|
||||
]:
|
||||
pass
|
||||
else:
|
||||
return True # on default
|
||||
else:
|
||||
return True # not a template parameter
|
||||
|
||||
return False
|
||||
|
||||
@@ -3,6 +3,8 @@ C++ Language Utility
|
||||
* some methods may not be designed to be universal.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
|
||||
class ForwardDeclaration:
|
||||
namespace_decl = str()
|
||||
@@ -85,3 +87,106 @@ def find_namespace_declaration(line: str) -> str | None:
|
||||
return None
|
||||
|
||||
return line[namespace_pos + len('namespace') : left_brace_pos].strip()
|
||||
|
||||
|
||||
def find_template_name(full: str, what: str):
|
||||
for matched in re.finditer(rf'\b{re.escape(what)}\b', full):
|
||||
endpos = matched.start()
|
||||
while True:
|
||||
r_angle_bracket_pos = full.rfind('>', 0, endpos)
|
||||
l_angle_bracket_pos = full.rfind('<', 0, endpos)
|
||||
if l_angle_bracket_pos == -1:
|
||||
return None
|
||||
if r_angle_bracket_pos > l_angle_bracket_pos:
|
||||
endpos = l_angle_bracket_pos
|
||||
continue
|
||||
ret = full[:l_angle_bracket_pos]
|
||||
matched_non_name = list(re.finditer(r'[^a-zA-Z_]', ret))
|
||||
if len(matched_non_name) > 0:
|
||||
ret = ret[matched_non_name[-1].start() + 1 :]
|
||||
assert len(ret) > 0
|
||||
return ret
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def is_full_type_required(namespace_decl: str, class_decl: str, type_decl: str):
|
||||
"""
|
||||
Determine whether `class_decl` requires a full type for `type_decl`.
|
||||
|
||||
TODO: namespace_decl (currently UNUSED).
|
||||
"""
|
||||
|
||||
# Y: T
|
||||
# Y: std::optional<T>
|
||||
# Y: std::variant<T>
|
||||
# Y: std::array<T, _>
|
||||
# Y: std::pair<T, T>
|
||||
# Y: std::unordered_set<T>
|
||||
# Y: std::unordered_map<T, _>
|
||||
# Y: std::deque<T> // under msstl only
|
||||
# Y: std::queue<T> // under msstl only
|
||||
# N: T&
|
||||
# N: T*
|
||||
# N: std::map<T, T>
|
||||
# N: std::shared_ptr<T>
|
||||
# N: std::unique_ptr<T>
|
||||
# N: std::weak_ptr<T>
|
||||
# N: std::vector<T>
|
||||
# N: std::set<T>
|
||||
# N: std::unordered_map<_, T>
|
||||
# N: std::function<T(T)>
|
||||
|
||||
def is_subtk_ends_with(full: str, tk: str, whats: list):
|
||||
founded = False
|
||||
for matched in re.finditer(rf'\b{re.escape(tk)}\b', full):
|
||||
founded = True
|
||||
if len(full) > matched.end():
|
||||
for what in whats:
|
||||
if full[matched.end() : matched.end() + len(what)] == what:
|
||||
return founded, True
|
||||
return founded, False
|
||||
|
||||
# is reference or pointer type?
|
||||
founded, is_endswith = is_subtk_ends_with(
|
||||
type_decl, class_decl, ['&', '*', ' const&', ' const*']
|
||||
)
|
||||
|
||||
if not founded or is_endswith:
|
||||
return False
|
||||
|
||||
# is template params?
|
||||
template_name = find_template_name(type_decl, class_decl)
|
||||
if not template_name:
|
||||
return True # moreover, is not a template parameter
|
||||
|
||||
if template_name in [ # forward declarations are allowed.
|
||||
'map',
|
||||
'shared_ptr',
|
||||
'unique_ptr',
|
||||
'weak_ptr',
|
||||
'vector',
|
||||
'queue',
|
||||
'set',
|
||||
'function',
|
||||
]:
|
||||
return False
|
||||
elif template_name in [ # full type is required.
|
||||
'optional',
|
||||
'variant',
|
||||
'array',
|
||||
'pair',
|
||||
'unordered_set',
|
||||
'deque',
|
||||
'queue',
|
||||
]:
|
||||
return True
|
||||
else:
|
||||
return True # by default, we assume that a full type is required.
|
||||
|
||||
|
||||
def is_full_type_required_for_typeset(namespace_decl: str, class_decl: str, typeset: list):
|
||||
for type_decl in typeset:
|
||||
if is_full_type_required(namespace_decl, class_decl, type_decl):
|
||||
return True
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user