aboutsummaryrefslogtreecommitdiffstats
path: root/tools/snippets_translate/handlers.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/snippets_translate/handlers.py')
-rw-r--r--tools/snippets_translate/handlers.py157
1 files changed, 79 insertions, 78 deletions
diff --git a/tools/snippets_translate/handlers.py b/tools/snippets_translate/handlers.py
index 72c70eef8..26633fc50 100644
--- a/tools/snippets_translate/handlers.py
+++ b/tools/snippets_translate/handlers.py
@@ -44,8 +44,37 @@ from parse_utils import (dstrip, get_indent, get_qt_module_class,
parse_arguments, remove_ref, replace_main_commas)
IF_PATTERN = re.compile(r'^\s*if\s*\(')
+PARENTHESES_NONEMPTY_CONTENT_PATTERN = re.compile(r"\((.+)\)")
+LOCAL_INCLUDE_PATTERN = re.compile(r'"(.*)"')
+GLOBAL_INCLUDE_PATTERN = re.compile(r"<(.*)>")
+IF_CONDITION_PATTERN = PARENTHESES_NONEMPTY_CONTENT_PATTERN
ELSE_IF_PATTERN = re.compile(r'^\s*}?\s*else if\s*\(')
WHILE_PATTERN = re.compile(r'^\s*while\s*\(')
+CAST_PATTERN = re.compile(r"[a-z]+_cast<(.*?)>\((.*?)\)") # Non greedy match of <>
+ITERATOR_LOOP_PATTERN = re.compile(r"= *(.*)egin\(")
+REMOVE_TEMPLATE_PARAMETER_PATTERN = re.compile("<.*>")
+PARENTHESES_CONTENT_PATTERN = re.compile(r"\((.*)\)")
+CONSTRUCTOR_BODY_PATTERN = re.compile(".*{ *}.*")
+CONSTRUCTOR_BODY_REPLACEMENT_PATTERN = re.compile("{ *}")
+CONSTRUCTOR_BASE_PATTERN = re.compile("^ *: *")
+NEGATE_PATTERN = re.compile(r"!(.)")
+CLASS_TEMPLATE_PATTERN = re.compile(r".*<.*>")
+EMPTY_CLASS_PATTERN = re.compile(r".*{.*}")
+EMPTY_CLASS_REPLACEMENT_PATTERN = re.compile(r"{.*}")
+FUNCTION_BODY_PATTERN = re.compile(r"\{(.*)\}")
+ARRAY_DECLARATION_PATTERN = re.compile(r"^[a-zA-Z0-9\<\>]+ ([\w\*]+) *\[?\]?")
+RETURN_TYPE_PATTERN = re.compile(r"^ *[a-zA-Z0-9]+ [\w]+::([\w\*\&]+\(.*\)$)")
+CAPTURE_PATTERN = re.compile(r"^ *([a-zA-Z0-9]+) ([\w\*\&]+\(.*\)$)")
+USELESS_QT_CLASSES_PATTERNS = [
+ re.compile(r"QLatin1String\((.*)\)"),
+ re.compile(r"QLatin1Char\((.*)\)")
+]
+COMMENT1_PATTERN = re.compile(r" *# *[\w\ ]+$")
+COMMENT2_PATTERN = re.compile(r" *# *(.*)$")
+COUT_ENDL_PATTERN = re.compile(r"cout *<<(.*)<< *.*endl")
+COUT1_PATTERN = re.compile(r" *<< *")
+COUT2_PATTERN = re.compile(r".*cout *<<")
+COUT_ENDL2_PATTERN = re.compile(r"<< +endl")
def handle_condition(x, name):
@@ -62,10 +91,9 @@ def handle_condition(x, name):
comment = f" #{comment_content[-1]}"
x = x.replace(f"//{comment_content[-1]}", "")
- re_par = re.compile(r"\((.+)\)")
- match = re_par.search(x)
+ match = IF_CONDITION_PATTERN.search(x)
if match:
- condition = re_par.search(x).group(1)
+ condition = match.group(1)
return f"{get_indent(x)}{name} {condition.strip()}:{comment}"
else:
print(f'snippets_translate: Warning "{x}" does not match condition pattern',
@@ -93,34 +121,23 @@ def handle_inc_dec(x, operator):
def handle_casts(x):
- re_type = re.compile(r"<(.*)>")
- re_data = re.compile(r"_cast<.*>\((.*)\)")
- type_name = re_type.search(x)
- data_name = re_data.search(x)
-
- if type_name and data_name:
- type_name = type_name.group(1).replace("*", "")
- data_name = data_name.group(1)
- new_value = f"{type_name}({data_name})"
-
- if "static_cast" in x:
- x = re.sub(r"static_cast<.*>\(.*\)", new_value, x)
- elif "dynamic_cast" in x:
- x = re.sub(r"dynamic_cast<.*>\(.*\)", new_value, x)
- elif "const_cast" in x:
- x = re.sub(r"const_cast<.*>\(.*\)", new_value, x)
- elif "reinterpret_cast" in x:
- x = re.sub(r"reinterpret_cast<.*>\(.*\)", new_value, x)
- elif "qobject_cast" in x:
- x = re.sub(r"qobject_cast<.*>\(.*\)", new_value, x)
+ while True:
+ match = CAST_PATTERN.search(x)
+ if not match:
+ break
+ type_name = match.group(1).strip()
+ while type_name.endswith("*") or type_name.endswith("&") or type_name.endswith(" "):
+ type_name = type_name[:-1]
+ data_name = match.group(2).strip()
+ python_cast = f"{type_name}({data_name})"
+ x = x[0:match.start(0)] + python_cast + x[match.end(0):]
return x
def handle_include(x):
if '"' in x:
- re_par = re.compile(r'"(.*)"')
- header = re_par.search(x)
+ header = LOCAL_INCLUDE_PATTERN.search(x)
if header:
header_name = header.group(1).replace(".h", "")
module_name = header_name.replace('/', '.')
@@ -130,8 +147,7 @@ def handle_include(x):
# besides '"something.h"'
x = ""
elif "<" in x and ">" in x:
- re_par = re.compile(r"<(.*)>")
- name = re_par.search(x).group(1)
+ name = GLOBAL_INCLUDE_PATTERN.search(x).group(1)
t = get_qt_module_class(name)
# if it's not a Qt module or class, we discard it.
if t is None:
@@ -159,8 +175,7 @@ def handle_conditions(x):
def handle_for(x):
- re_content = re.compile(r"\((.*)\)")
- content = re_content.search(x)
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
new_x = x
if content:
@@ -175,7 +190,7 @@ def handle_for(x):
# iterators
if "begin(" in x.lower() and "end(" in x.lower():
- name = re.search(r"= *(.*)egin\(", start)
+ name = ITERATOR_LOOP_PATTERN.search(start)
iterable = None
iterator = None
if name:
@@ -256,23 +271,22 @@ def handle_for(x):
def handle_foreach(x):
- re_content = re.compile(r"\((.*)\)")
- content = re_content.search(x)
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
if content:
parenthesis = content.group(1)
iterator, iterable = parenthesis.split(",", 1)
# remove iterator type
it = dstrip(iterator.split()[-1])
# remove <...> from iterable
- value = re.sub("<.*>", "", iterable)
+ value = REMOVE_TEMPLATE_PARAMETER_PATTERN.sub("", iterable)
return f"{get_indent(x)}for {it} in {value}:"
def handle_type_var_declaration(x):
# remove content between <...>
if "<" in x and ">" in x:
- x = " ".join(re.sub("<.*>", "", i) for i in x.split())
- content = re.search(r"\((.*)\)", x)
+ x = " ".join(REMOVE_TEMPLATE_PARAMETER_PATTERN.sub("", i) for i in x.split())
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
if content:
# this means we have something like:
# QSome thing(...)
@@ -288,8 +302,7 @@ def handle_type_var_declaration(x):
def handle_constructors(x):
- re_content = re.compile(r"\((.*)\)")
- arguments = re_content.search(x).group(1)
+ arguments = PARENTHESES_CONTENT_PATTERN.search(x).group(1)
class_method = x.split("(")[0].split("::")
if len(class_method) == 2:
# Equal 'class name' and 'method name'
@@ -307,8 +320,8 @@ def handle_constructor_default_values(x):
# we discard that section completely, since even with a single
# value, we don't need to take care of it, for example:
# ' : a(1) { } -> self.a = 1
- if re.search(".*{ *}.*", x):
- x = re.sub("{ *}", "", x)
+ if CONSTRUCTOR_BODY_PATTERN.search(x):
+ x = CONSTRUCTOR_BODY_REPLACEMENT_PATTERN.sub("", x)
values = "".join(x.split(":", 1))
# Check the commas that are not inside round parenthesis
@@ -323,26 +336,24 @@ def handle_constructor_default_values(x):
if "@" in values:
return_values = ""
for arg in values.split("@"):
- arg = re.sub("^ *: *", "", arg).strip()
+ arg = CONSTRUCTOR_BASE_PATTERN.sub("", arg).strip()
if arg.startswith("Q"):
class_name = arg.split("(")[0]
content = arg.replace(class_name, "")[1:-1]
return_values += f" {class_name}.__init__(self, {content})\n"
elif arg:
var_name = arg.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- content = re_par.search(arg).group(1)
+ content = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(arg).group(1)
return_values += f" self.{var_name} = {content}\n"
else:
- arg = re.sub("^ *: *", "", values).strip()
+ arg = CONSTRUCTOR_BASE_PATTERN.sub("", values).strip()
if arg.startswith("Q"):
class_name = arg.split("(")[0]
content = arg.replace(class_name, "")[1:-1]
return f" {class_name}.__init__(self, {content})"
elif arg:
var_name = arg.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- match = re_par.search(arg)
+ match = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(arg)
if match:
content = match.group(1)
return f" self.{var_name} = {content}"
@@ -356,27 +367,27 @@ def handle_constructor_default_values(x):
def handle_cout_endl(x):
# if comment at the end
comment = ""
- if re.search(r" *# *[\w\ ]+$", x):
- comment = f' # {re.search(" *# *(.*)$", x).group(1)}'
+ if COMMENT1_PATTERN.search(x):
+ match = COMMENT2_PATTERN.search(x).group(1)
+ comment = f' # {match}'
x = x.split("#")[0]
if "qDebug()" in x:
x = x.replace("qDebug()", "cout")
if "cout" in x and "endl" in x:
- re_cout_endl = re.compile(r"cout *<<(.*)<< *.*endl")
- data = re_cout_endl.search(x)
+ data = COUT_ENDL_PATTERN.search(x)
if data:
data = data.group(1)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
elif "cout" in x:
- data = re.sub(".*cout *<<", "", x)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT2_PATTERN.sub("", x)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
elif "endl" in x:
- data = re.sub("<< +endl", "", x)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT_ENDL2_PATTERN.sub("", x)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
x = x.replace("( ", "(").replace(" )", ")").replace(" ,", ",").replace("(, ", "(")
@@ -392,8 +403,7 @@ def handle_negate(x):
elif "/*" in x:
if x.index("/*") < x.index("!"):
return x
- re_negate = re.compile(r"!(.)")
- next_char = re_negate.search(x).group(1)
+ next_char = NEGATE_PATTERN.search(x).group(1)
if next_char not in ("=", '"'):
x = x.replace("!", "not ")
return x
@@ -401,8 +411,7 @@ def handle_negate(x):
def handle_emit(x):
function_call = x.replace("emit ", "").strip()
- re_content = re.compile(r"\((.*)\)")
- match = re_content.search(function_call)
+ match = PARENTHESES_CONTENT_PATTERN.search(function_call)
if not match:
stmt = x.strip()
print(f'snippets_translate: Warning "{stmt}" does not match function call',
@@ -425,15 +434,14 @@ def handle_void_functions(x):
# if the arguments are in the same line:
arguments = None
if ")" in x:
- re_content = re.compile(r"\((.*)\)")
- parenthesis = re_content.search(x).group(1)
+ parenthesis = PARENTHESES_CONTENT_PATTERN.search(x).group(1)
arguments = dstrip(parse_arguments(parenthesis))
elif "," in x:
arguments = dstrip(parse_arguments(x.split("(")[-1]))
# check if includes a '{ ... }' after the method signature
after_signature = x.split(")")[-1]
- re_decl = re.compile(r"\{(.*)\}").search(after_signature)
+ re_decl = FUNCTION_BODY_PATTERN.search(after_signature)
extra = ""
if re_decl:
extra = re_decl.group(1)
@@ -469,13 +477,13 @@ def handle_class(x):
bases_name = ""
# Check if the class_name is templated, then remove it
- if re.search(r".*<.*>", class_name):
+ if CLASS_TEMPLATE_PATTERN.search(class_name):
class_name = class_name.split("<")[0]
# Special case: invalid notation for an example:
# class B() {...} -> clas B(): pass
- if re.search(r".*{.*}", class_name):
- class_name = re.sub(r"{.*}", "", class_name).rstrip()
+ if EMPTY_CLASS_PATTERN.search(class_name):
+ class_name = EMPTY_CLASS_REPLACEMENT_PATTERN.sub("", class_name).rstrip()
return f"{class_name}(): pass"
# Special case: check if the line ends in ','
@@ -491,8 +499,7 @@ def handle_class(x):
def handle_array_declarations(x):
- re_varname = re.compile(r"^[a-zA-Z0-9\<\>]+ ([\w\*]+) *\[?\]?")
- content = re_varname.search(x.strip())
+ content = ARRAY_DECLARATION_PATTERN.search(x.strip())
if content:
var_name = content.group(1)
rest_line = "".join(x.split("{")[1:])
@@ -501,13 +508,11 @@ def handle_array_declarations(x):
def handle_methods_return_type(x):
- re_capture = re.compile(r"^ *[a-zA-Z0-9]+ [\w]+::([\w\*\&]+\(.*\)$)")
- capture = re_capture.search(x)
+ capture = RETURN_TYPE_PATTERN.search(x)
if capture:
content = capture.group(1)
method_name = content.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- par_capture = re_par.search(x)
+ par_capture = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(x)
arguments = "(self)"
if par_capture:
arguments = f"(self, {par_capture.group(1)})"
@@ -516,16 +521,14 @@ def handle_methods_return_type(x):
def handle_functions(x):
- re_capture = re.compile(r"^ *([a-zA-Z0-9]+) ([\w\*\&]+\(.*\)$)")
- capture = re_capture.search(x)
+ capture = CAPTURE_PATTERN.search(x)
if capture:
return_type = capture.group(1)
if return_type == "return": # "return QModelIndex();"
return x
content = capture.group(2)
function_name = content.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- par_capture = re_par.search(x)
+ par_capture = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(x)
arguments = ""
if par_capture:
for arg in par_capture.group(1).split(","):
@@ -538,10 +541,8 @@ def handle_functions(x):
def handle_useless_qt_classes(x):
- _classes = ("QLatin1String", "QLatin1Char")
- for i in _classes:
- re_content = re.compile(fr"{i}\((.*)\)")
- content = re_content.search(x)
+ for c in USELESS_QT_CLASSES_PATTERNS:
+ content = c.search(x)
if content:
x = x.replace(content.group(0), content.group(1))
return x