diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-09-02 09:43:41 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-09-02 12:16:45 +0200 |
| commit | 065766883f5e34d20ca88084cd747813a84ed2d3 (patch) | |
| tree | 2bca2c34d113f0198564155ac21789466d4b8b96 /tools/qtpy2cpp_lib/formatter.py | |
| parent | 4cfa700d5965922b5156517a64790369deac354f (diff) | |
Move qtpy2cpp to sources/pyside-tools
Preparing the entry point.
Task-number: PYSIDE-1945
Change-Id: I4a2fbe6d35b4f97bf0ab7cfc2085b86a40bc2558
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'tools/qtpy2cpp_lib/formatter.py')
| -rw-r--r-- | tools/qtpy2cpp_lib/formatter.py | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/tools/qtpy2cpp_lib/formatter.py b/tools/qtpy2cpp_lib/formatter.py deleted file mode 100644 index 9a38e803d..000000000 --- a/tools/qtpy2cpp_lib/formatter.py +++ /dev/null @@ -1,265 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -"""C++ formatting helper functions and formatter class""" - - -import ast - -from .qt import ClassFlag, qt_class_flags - -CLOSING = {"{": "}", "(": ")", "[": "]"} # Closing parenthesis for C++ - - -def _fix_function_argument_type(type, for_return): - """Fix function argument/return qualifiers using some heuristics for Qt.""" - if type == "float": - return "double" - if type == "str": - type = "QString" - if not type.startswith("Q"): - return type - flags = qt_class_flags(type) - if flags & ClassFlag.PASS_BY_VALUE: - return type - if flags & ClassFlag.PASS_BY_CONSTREF: - return type if for_return else f"const {type} &" - if flags & ClassFlag.PASS_BY_REF: - return type if for_return else f"{type} &" - return type + " *" # Assume pointer by default - - -def to_string(node): - """Helper to retrieve a string from the (Lists of)Name/Attribute - aggregated into some nodes""" - if isinstance(node, ast.Name): - return node.id - if isinstance(node, ast.Attribute): - return node.attr - return '' - - -def format_inheritance(class_def_node): - """Returns inheritance specification of a class""" - result = '' - for base in class_def_node.bases: - name = to_string(base) - if name != 'object': - result += ', public ' if result else ' : public ' - result += name - return result - - -def format_for_target(target_node): - if isinstance(target_node, ast.Tuple): # for i,e in enumerate() - result = '' - for i, el in enumerate(target_node.elts): - if i > 0: - result += ', ' - result += format_reference(el) - return result - return format_reference(target_node) - - -def format_for_loop(f_node): - """Format a for loop - This applies some heuristics to detect: - 1) "for a in [1,2])" -> "for (f: {1, 2}) {" - 2) "for i in range(5)" -> "for (i = 0; i < 5; ++i) {" - 3) "for i in range(2,5)" -> "for (i = 2; i < 5; ++i) {" - - TODO: Detect other cases, maybe including enumerate(). - """ - loop_vars = format_for_target(f_node.target) - result = 'for (' + loop_vars - if isinstance(f_node.iter, ast.Call): - f = format_reference(f_node.iter.func) - if f == 'range': - start = 0 - end = -1 - if len(f_node.iter.args) == 2: - start = format_literal(f_node.iter.args[0]) - end = format_literal(f_node.iter.args[1]) - elif len(f_node.iter.args) == 1: - end = format_literal(f_node.iter.args[0]) - result += f' = {start}; {loop_vars} < {end}; ++{loop_vars}' - elif isinstance(f_node.iter, ast.List): - # Range based for over list - result += ': ' + format_literal_list(f_node.iter) - elif isinstance(f_node.iter, ast.Name): - # Range based for over variable - result += ': ' + f_node.iter.id - result += ') {' - return result - - -def format_name_constant(node): - """Format a ast.NameConstant.""" - if node.value is None: - return "nullptr" - return "true" if node.value else "false" - - -def format_literal(node): - """Returns the value of number/string literals""" - if isinstance(node, ast.NameConstant): - return format_name_constant(node) - if isinstance(node, ast.Num): - return str(node.n) - if isinstance(node, ast.Str): - # Fixme: escaping - return f'"{node.s}"' - return '' - - -def format_literal_list(l_node, enclosing='{'): - """Formats a list/tuple of number/string literals as C++ initializer list""" - result = enclosing - for i, el in enumerate(l_node.elts): - if i > 0: - result += ', ' - result += format_literal(el) - result += CLOSING[enclosing] - return result - - -def format_member(attrib_node, qualifier_in='auto'): - """Member access foo->member() is expressed as an attribute with - further nested Attributes/Names as value""" - n = attrib_node - result = '' - # Black magic: Guess '::' if name appears to be a class name - qualifier = qualifier_in - if qualifier_in == 'auto': - qualifier = '::' if n.attr[0:1].isupper() else '->' - while isinstance(n, ast.Attribute): - result = n.attr if not result else n.attr + qualifier + result - n = n.value - if isinstance(n, ast.Name) and n.id != 'self': - if qualifier_in == 'auto' and n.id == "Qt": # Qt namespace - qualifier = "::" - result = n.id + qualifier + result - return result - - -def format_reference(node, qualifier='auto'): - """Format member reference or free item""" - return node.id if isinstance(node, ast.Name) else format_member(node, qualifier) - - -def format_function_def_arguments(function_def_node): - """Formats arguments of a function definition""" - # Default values is a list of the last default values, expand - # so that indexes match - argument_count = len(function_def_node.args.args) - default_values = function_def_node.args.defaults - while len(default_values) < argument_count: - default_values.insert(0, None) - result = '' - for i, a in enumerate(function_def_node.args.args): - if result: - result += ', ' - if a.arg != 'self': - if a.annotation and isinstance(a.annotation, ast.Name): - result += _fix_function_argument_type(a.annotation.id, False) + ' ' - result += a.arg - if default_values[i]: - result += ' = ' - default_value = default_values[i] - if isinstance(default_value, ast.Attribute): - result += format_reference(default_value) - else: - result += format_literal(default_value) - return result - - -def format_start_function_call(call_node): - """Format a call of a free or member function""" - return format_reference(call_node.func) + '(' - - -def write_import(file, i_node): - """Print an import of a Qt class as #include""" - for alias in i_node.names: - if alias.name.startswith('Q'): - file.write(f'#include <{alias.name}>\n') - - -def write_import_from(file, i_node): - """Print an import from Qt classes as #include sequence""" - # "from PySide6.QtGui import QGuiApplication" or - # "from PySide6 import QtGui" - mod = i_node.module - if not mod.startswith('PySide') and not mod.startswith('PyQt'): - return - dot = mod.find('.') - qt_module = mod[dot + 1:] + '/' if dot >= 0 else '' - for i in i_node.names: - if i.name.startswith('Q'): - file.write(f'#include <{qt_module}{i.name}>\n') - - -class Indenter: - """Helper for Indentation""" - - def __init__(self, output_file): - self._indent_level = 0 - self._indentation = '' - self._output_file = output_file - - def indent_string(self, string): - """Start a new line by a string""" - self._output_file.write(self._indentation) - self._output_file.write(string) - - def indent_line(self, line): - """Write an indented line""" - self._output_file.write(self._indentation) - self._output_file.write(line) - self._output_file.write('\n') - - def INDENT(self): - """Write indentation""" - self._output_file.write(self._indentation) - - def indent(self): - """Increase indentation level""" - self._indent_level = self._indent_level + 1 - self._indentation = ' ' * self._indent_level - - def dedent(self): - """Decrease indentation level""" - self._indent_level = self._indent_level - 1 - self._indentation = ' ' * self._indent_level - - -class CppFormatter(Indenter): - """Provides helpers for formatting multi-line C++ constructs""" - - def __init__(self, output_file): - Indenter.__init__(self, output_file) - - def write_class_def(self, class_node): - """Print a class definition with inheritance""" - self._output_file.write('\n') - inherits = format_inheritance(class_node) - self.indent_line(f'class {class_node.name}{inherits}') - self.indent_line('{') - self.indent_line('public:') - - def write_function_def(self, f_node, class_context): - """Print a function definition with arguments""" - self._output_file.write('\n') - arguments = format_function_def_arguments(f_node) - if f_node.name == '__init__' and class_context: # Constructor - name = class_context - elif f_node.name == '__del__' and class_context: # Destructor - name = '~' + class_context - else: - return_type = "void" - if f_node.returns and isinstance(f_node.returns, ast.Name): - return_type = _fix_function_argument_type(f_node.returns.id, True) - name = return_type + " " + f_node.name - self.indent_string(f'{name}({arguments})') - self._output_file.write('\n') - self.indent_line('{') |
