Доработана функции для считывания переменных
Добавлены бета-функции для считывания переменны по адресу +фиксы багов future: - в селекторе сделать две таблички для всех переменных и для выборанных - по кнопке переносить переменные из всех в выбранные - переменные из выбранных и добавлять в основную табличку - сделать отдельный класс для таблички - который будет принимать спиоск переменных для отображения
This commit is contained in:
@@ -8,12 +8,11 @@ import xml.etree.ElementTree as ET
|
||||
from generateVars import type_map
|
||||
from enum import IntEnum
|
||||
import threading
|
||||
from scanVars import run_scan
|
||||
from generateVars import run_generate
|
||||
import setupVars
|
||||
from VariableSelector import VariableSelectorDialog
|
||||
from VariableTable import VariableTableWidget, rows
|
||||
from scanVarGUI import ProcessOutputWindowDummy
|
||||
from scanVarGUI import ProcessOutputWindow
|
||||
import scanVars
|
||||
import myXML
|
||||
import time
|
||||
@@ -202,25 +201,10 @@ class VarEditor(QWidget):
|
||||
|
||||
|
||||
# Создаём окно с кнопкой "Готово"
|
||||
self.proc_win = ProcessOutputWindowDummy(self.__after_scanvars_finished)
|
||||
self.emitting_stream = self.proc_win.emitting_stream # ключевая строка!
|
||||
self.proc_win.show()
|
||||
self.proc_win = ProcessOutputWindow(self.proj_path, self.makefile_path, self.xml_path,
|
||||
on_done_callback=self.__after_scanvars_finished)
|
||||
self.proc_win.start_scan()
|
||||
|
||||
def run_scan_wrapper():
|
||||
try:
|
||||
old_stdout = sys.stdout
|
||||
sys.stdout = self.emitting_stream
|
||||
|
||||
run_scan(self.proj_path, self.makefile_path, self.xml_path)
|
||||
|
||||
except Exception as e:
|
||||
self.emitting_stream.text_written.emit(f"\n[ОШИБКА] {e}")
|
||||
finally:
|
||||
sys.stdout = old_stdout
|
||||
self.emitting_stream.text_written.emit("\n--- Анализ завершён ---")
|
||||
self.proc_win.btn_close.setEnabled(True)
|
||||
|
||||
threading.Thread(target=run_scan_wrapper, daemon=True).start()
|
||||
|
||||
|
||||
def save_build(self):
|
||||
@@ -433,17 +417,12 @@ class VarEditor(QWidget):
|
||||
def delete_selected_rows(self):
|
||||
selected_rows = sorted(set(index.row() for index in self.table.selectedIndexes()), reverse=True)
|
||||
if not selected_rows:
|
||||
return
|
||||
return
|
||||
|
||||
# Удаляем из vars_list те, у кого show_var == true и имя совпадает
|
||||
filtered_vars = [v for v in self.vars_list if v.get('show_var', 'false') == 'true']
|
||||
for row in selected_rows:
|
||||
if 0 <= row < len(filtered_vars):
|
||||
var_to_remove = filtered_vars[row]
|
||||
for v in self.vars_list:
|
||||
if v['name'] == var_to_remove['name']:
|
||||
v['show_var'] = 'false'
|
||||
break
|
||||
if 0 <= row < len(self.vars_list):
|
||||
# Меняем флаг show_var для переменной с этим индексом
|
||||
self.vars_list[row]['show_var'] = 'false'
|
||||
|
||||
self.table.populate(self.vars_list, self.structs, self.write_to_xml)
|
||||
self.write_to_xml()
|
||||
@@ -454,7 +433,7 @@ class VarEditor(QWidget):
|
||||
QMessageBox.warning(self, "Нет переменных", f"Сначала загрузите переменные ({scan_title}).")
|
||||
return
|
||||
|
||||
dlg = VariableSelectorDialog(self.vars_list, self.structs, self.typedef_map, self.xml_path, self)
|
||||
dlg = VariableSelectorDialog(self.table, self.vars_list, self.structs, self.typedef_map, self.xml_path, self)
|
||||
if dlg.exec_():
|
||||
self.write_to_xml()
|
||||
self.update()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from PySide2.QtWidgets import (
|
||||
QDialog, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QPushButton,
|
||||
QLineEdit, QLabel, QHeaderView, QCompleter, QCheckBox, QHBoxLayout
|
||||
)
|
||||
from PySide2.QtGui import QKeySequence, QKeyEvent
|
||||
from PySide2.QtCore import Qt, QStringListModel, QSettings
|
||||
import VariableTable
|
||||
import setupVars
|
||||
import myXML
|
||||
import time
|
||||
@@ -13,14 +15,14 @@ import time
|
||||
array_re = re.compile(r'^(\w+)\[(\d+)\]$')
|
||||
|
||||
class VariableSelectorDialog(QDialog):
|
||||
def __init__(self, all_vars, structs, typedefs, xml_path=None, parent=None):
|
||||
def __init__(self, table, all_vars, structs, typedefs, xml_path=None, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Выбор переменных")
|
||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||
self.resize(600, 500)
|
||||
self.selected_names = []
|
||||
self._bckspc_pressed = False # флаг подавления добавления разделителя
|
||||
|
||||
self.table = table
|
||||
self.all_vars = all_vars
|
||||
self.structs = structs
|
||||
self.typedefs = typedefs
|
||||
@@ -28,6 +30,7 @@ class VariableSelectorDialog(QDialog):
|
||||
self.var_map = {v['name']: v for v in all_vars}
|
||||
self.node_index = {}
|
||||
self.xml_path = xml_path # сохраняем путь к xml
|
||||
self.manual_completion_active = False
|
||||
|
||||
# --- Добавляем чекбокс для автодополнения ---
|
||||
self.autocomplete_checkbox = QCheckBox("Включить автодополнение")
|
||||
@@ -289,8 +292,9 @@ class VariableSelectorDialog(QDialog):
|
||||
if not name_parts:
|
||||
continue
|
||||
last_part = name_parts[-1].lower()
|
||||
if prefix == '' or last_part.startswith(prefix):
|
||||
if prefix == '' or prefix in last_part: # здесь изменено
|
||||
completions.append(name)
|
||||
|
||||
|
||||
self.completer.complete()
|
||||
return completions
|
||||
@@ -328,9 +332,16 @@ class VariableSelectorDialog(QDialog):
|
||||
def eventFilter(self, obj, event):
|
||||
if obj == self.search_input and isinstance(event, QKeyEvent):
|
||||
if event.key() == Qt.Key_Space and event.modifiers() & Qt.ControlModifier:
|
||||
self.manual_completion_active = True
|
||||
text = self.search_input.text().strip()
|
||||
self.run_completions(text)
|
||||
return True
|
||||
elif event.key() == Qt.Key_Escape:
|
||||
# Esc — выключаем ручной режим и скрываем подсказки, если autocomplete выключен
|
||||
if not self.autocomplete_checkbox.isChecked():
|
||||
self.manual_completion_active = False
|
||||
self.completer.popup().hide()
|
||||
return True
|
||||
|
||||
if event.key() == Qt.Key_Backspace:
|
||||
self._bckspc_pressed = True
|
||||
else:
|
||||
@@ -341,6 +352,9 @@ class VariableSelectorDialog(QDialog):
|
||||
def run_completions(self, text):
|
||||
completions = self.update_completions(text)
|
||||
|
||||
if not self.autocomplete_checkbox.isChecked() and self._bckspc_pressed:
|
||||
text = text[:-1]
|
||||
|
||||
if len(completions) == 1 and completions[0].lower() == text.lower():
|
||||
# Найдем узел с таким именем
|
||||
def find_exact_item(name):
|
||||
@@ -391,6 +405,12 @@ class VariableSelectorDialog(QDialog):
|
||||
text = self.search_input.text().strip()
|
||||
if self.autocomplete_checkbox.isChecked():
|
||||
self.run_completions(text)
|
||||
else:
|
||||
# Если выключено, показываем подсказки только если флаг ручного вызова True
|
||||
if self.manual_completion_active:
|
||||
self.run_completions(text)
|
||||
else:
|
||||
self.completer.popup().hide()
|
||||
|
||||
def on_add_clicked(self):
|
||||
self.selected_names = []
|
||||
@@ -462,9 +482,7 @@ class VariableSelectorDialog(QDialog):
|
||||
QMessageBox.warning(self, "Ошибка", "Путь к XML не задан, невозможно обновить переменные.")
|
||||
return
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
tree = ET.parse(self.xml_path)
|
||||
root = tree.getroot()
|
||||
root, tree = myXML.safe_parse_xml(self.xml_path)
|
||||
if root is None:
|
||||
return
|
||||
|
||||
@@ -485,7 +503,6 @@ class VariableSelectorDialog(QDialog):
|
||||
|
||||
myXML.fwrite(root, self.xml_path)
|
||||
|
||||
self.populate_tree()
|
||||
self.done(QDialog.Accepted)
|
||||
|
||||
|
||||
@@ -503,8 +520,50 @@ class VariableSelectorDialog(QDialog):
|
||||
def delete_selected_vars(self):
|
||||
selected_names = self._get_selected_var_names()
|
||||
if not selected_names:
|
||||
print("nothing selected")
|
||||
return
|
||||
|
||||
# Обновляем var_map и all_vars
|
||||
for name in selected_names:
|
||||
if name in self.var_map:
|
||||
self.var_map[name]['show_var'] = 'false'
|
||||
self.var_map[name]['enable'] = 'false'
|
||||
|
||||
for v in self.all_vars:
|
||||
if v['name'] == name:
|
||||
v['show_var'] = 'false'
|
||||
v['enable'] = 'false'
|
||||
break
|
||||
|
||||
# Проверка пути к XML
|
||||
if not hasattr(self, 'xml_path') or not self.xml_path:
|
||||
from PySide2.QtWidgets import QMessageBox
|
||||
QMessageBox.warning(self, "Ошибка", "Путь к XML не задан, невозможно обновить переменные.")
|
||||
return
|
||||
|
||||
root, tree = myXML.safe_parse_xml(self.xml_path)
|
||||
if root is None:
|
||||
return
|
||||
|
||||
vars_section = root.find('variables')
|
||||
if vars_section is None:
|
||||
return
|
||||
|
||||
for var_elem in vars_section.findall('var'):
|
||||
name = var_elem.attrib.get('name')
|
||||
if name in selected_names:
|
||||
def set_text(tag, value):
|
||||
el = var_elem.find(tag)
|
||||
if el is None:
|
||||
el = ET.SubElement(var_elem, tag)
|
||||
el.text = value
|
||||
set_text('show_var', 'false')
|
||||
set_text('enable', 'false')
|
||||
|
||||
myXML.fwrite(root, self.xml_path)
|
||||
|
||||
self.table.populate(self.all_vars, self.structs, None)
|
||||
|
||||
# Проверка пути к XML
|
||||
if not hasattr(self, 'xml_path') or not self.xml_path:
|
||||
from PySide2.QtWidgets import QMessageBox
|
||||
@@ -512,8 +571,7 @@ class VariableSelectorDialog(QDialog):
|
||||
return
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
tree = ET.parse(self.xml_path)
|
||||
root = tree.getroot()
|
||||
root, tree = myXML.safe_parse_xml(self.xml_path)
|
||||
if root is None:
|
||||
return
|
||||
|
||||
@@ -532,10 +590,22 @@ class VariableSelectorDialog(QDialog):
|
||||
# Удаляем из all_vars (глобально)
|
||||
self.all_vars[:] = [v for v in self.all_vars if v['name'] not in selected_names]
|
||||
|
||||
# Удаляем из expanded_vars (тоже глобально)
|
||||
def filter_out_selected(vars_list):
|
||||
filtered = []
|
||||
for v in vars_list:
|
||||
if v['name'] not in selected_names:
|
||||
# Рекурсивно фильтруем детей, если есть
|
||||
if 'children' in v:
|
||||
v = v.copy()
|
||||
v['children'] = filter_out_selected(v['children'])
|
||||
filtered.append(v)
|
||||
return filtered
|
||||
|
||||
self.expanded_vars[:] = filter_out_selected(self.expanded_vars)
|
||||
if removed_any:
|
||||
myXML.fwrite(root, self.xml_path)
|
||||
|
||||
self.populate_tree()
|
||||
self.filter_tree()
|
||||
|
||||
def _get_selected_var_names(self):
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
|
||||
import sys
|
||||
import re
|
||||
import multiprocessing
|
||||
import sys
|
||||
import contextlib
|
||||
import io
|
||||
import json
|
||||
from scanVars import run_scan
|
||||
from VariableTable import VariableTableWidget, rows
|
||||
|
||||
from PySide2.QtWidgets import (
|
||||
@@ -10,7 +16,7 @@ from PySide2.QtWidgets import (
|
||||
QDialog, QTreeWidget, QTreeWidgetItem, QSizePolicy, QHeaderView, QProgressBar
|
||||
)
|
||||
from PySide2.QtGui import QTextCursor, QKeyEvent
|
||||
from PySide2.QtCore import Qt, QProcess, QObject, Signal, QSettings
|
||||
from PySide2.QtCore import Qt, QProcess, QObject, Signal, QTimer
|
||||
|
||||
|
||||
class EmittingStream(QObject):
|
||||
@@ -67,24 +73,28 @@ class EmittingStream(QObject):
|
||||
self._buffer = ""
|
||||
|
||||
|
||||
class ProcessOutputWindowDummy(QDialog):
|
||||
def __init__(self, on_done_callback):
|
||||
|
||||
class ProcessOutputWindow(QDialog):
|
||||
def __init__(self, proj_path, makefile_path, xml_path, on_done_callback=None):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Поиск переменных...")
|
||||
self.resize(600, 480)
|
||||
self.setModal(True)
|
||||
|
||||
self.proj_path = proj_path
|
||||
self.makefile_path = makefile_path
|
||||
self.xml_path = xml_path
|
||||
self._on_done_callback = on_done_callback
|
||||
|
||||
self.layout = QVBoxLayout(self)
|
||||
|
||||
self.output_edit = QTextEdit()
|
||||
self.output_edit.setReadOnly(True)
|
||||
self.layout.addWidget(self.output_edit)
|
||||
|
||||
# Метка с именем прогрессбара
|
||||
self.progress_label = QLabel("Progress:")
|
||||
self.layout.addWidget(self.progress_label)
|
||||
|
||||
# Прогрессбар
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setMinimum(0)
|
||||
self.progress_bar.setValue(0)
|
||||
@@ -93,33 +103,117 @@ class ProcessOutputWindowDummy(QDialog):
|
||||
self.btn_close = QPushButton("Закрыть")
|
||||
self.btn_close.setEnabled(False)
|
||||
self.layout.addWidget(self.btn_close)
|
||||
|
||||
self.btn_close.clicked.connect(self.__handle_done)
|
||||
self._on_done_callback = on_done_callback
|
||||
|
||||
self.emitting_stream = EmittingStream()
|
||||
self.emitting_stream.text_written.connect(self.append_text)
|
||||
self.emitting_stream.progress_updated.connect(self.update_progress)
|
||||
self.queue = None
|
||||
self.proc = None
|
||||
|
||||
sys.stdout = self.emitting_stream
|
||||
|
||||
def __handle_done(self):
|
||||
sys.stdout = sys.__stdout__ # восстановить stdout
|
||||
if self._on_done_callback:
|
||||
self._on_done_callback()
|
||||
self.accept()
|
||||
def start_scan(self):
|
||||
self.queue = multiprocessing.Queue()
|
||||
self.proc = multiprocessing.Process(
|
||||
target=run_scan_process,
|
||||
args=(self.proj_path, self.makefile_path, self.xml_path, self.queue),
|
||||
daemon=True)
|
||||
self.proc.start()
|
||||
|
||||
self.timer = QTimer(self)
|
||||
self.timer.timeout.connect(self.poll_queue)
|
||||
self.timer.start(100)
|
||||
|
||||
self.show()
|
||||
|
||||
def poll_queue(self):
|
||||
try:
|
||||
while True:
|
||||
msg = self.queue.get_nowait()
|
||||
if msg is None:
|
||||
# Конец процесса
|
||||
self.btn_close.setEnabled(True)
|
||||
self.append_text("\n--- Анализ завершён ---")
|
||||
self.timer.stop()
|
||||
return
|
||||
# Пытаемся разобрать JSON-сообщение
|
||||
if isinstance(msg, str) and msg.startswith("PROGRESS_MSG:"):
|
||||
try:
|
||||
data = json.loads(msg[len("PROGRESS_MSG:"):])
|
||||
self.update_progress(data["bar_name"], data["current"], data["total"])
|
||||
except Exception:
|
||||
# Если не удалось распарсить, выводим как текст
|
||||
self.append_text(msg)
|
||||
else:
|
||||
self.append_text(msg)
|
||||
except Exception:
|
||||
pass # Очередь пустая
|
||||
|
||||
def append_text(self, text):
|
||||
cursor = self.output_edit.textCursor()
|
||||
cursor.movePosition(QTextCursor.End)
|
||||
if not text.endswith('\n'):
|
||||
text += '\n'
|
||||
for line in text.splitlines(True):
|
||||
cursor.insertText(line)
|
||||
cursor.insertText(text)
|
||||
self.output_edit.setTextCursor(cursor)
|
||||
self.output_edit.ensureCursorVisible()
|
||||
|
||||
def update_progress(self, bar_name, current, total):
|
||||
self.progress_label.setText(f"{bar_name}")
|
||||
self.progress_bar.setMaximum(total)
|
||||
self.progress_bar.setValue(current)
|
||||
self.progress_bar.setValue(current)
|
||||
|
||||
def __handle_done(self):
|
||||
self.close()
|
||||
|
||||
def closeEvent(self, event):
|
||||
if self.proc and self.proc.is_alive():
|
||||
self.proc.terminate()
|
||||
self.proc.join()
|
||||
self.btn_close.setEnabled(True)
|
||||
self.append_text("Сканирование прервано.")
|
||||
|
||||
|
||||
def run_scan_process(proj_path, makefile_path, xml_path, queue):
|
||||
class QueueWriter(io.TextIOBase):
|
||||
def __init__(self):
|
||||
self._buffer = ""
|
||||
self._current_bar_name = None
|
||||
|
||||
def write(self, txt):
|
||||
self._buffer += txt
|
||||
while '\n' in self._buffer:
|
||||
line, self._buffer = self._buffer.split('\n', 1)
|
||||
# Обработка прогресса
|
||||
if line.startswith('Progress: "') and line.endswith('"'):
|
||||
# Название прогресс-бара
|
||||
bar_name = line[len('Progress: "'):-1]
|
||||
self._current_bar_name = bar_name
|
||||
elif re.match(r'^Progress:\s*\d+\s*/\s*\d+$', line):
|
||||
m = re.match(r'^Progress:\s*(\d+)\s*/\s*(\d+)$', line)
|
||||
if m:
|
||||
current = int(m.group(1))
|
||||
total = int(m.group(2))
|
||||
bar_name = self._current_bar_name or "Progress"
|
||||
# Отправляем специальное сообщение в очередь в формате JSON
|
||||
msg = {
|
||||
"bar_name": bar_name,
|
||||
"current": current,
|
||||
"total": total
|
||||
}
|
||||
queue.put("PROGRESS_MSG:" + json.dumps(msg))
|
||||
else:
|
||||
# Обычный вывод
|
||||
queue.put(line)
|
||||
|
||||
def flush(self):
|
||||
if self._buffer.strip():
|
||||
queue.put(self._buffer.strip())
|
||||
self._buffer = ""
|
||||
|
||||
sys.stdout = QueueWriter()
|
||||
sys.stderr = sys.stdout
|
||||
|
||||
try:
|
||||
run_scan(proj_path, makefile_path, xml_path)
|
||||
except Exception as e:
|
||||
queue.put(f"[ОШИБКА] {e}")
|
||||
finally:
|
||||
queue.put(None) # сигнал окончания
|
||||
@@ -14,7 +14,6 @@ from xml.dom import minidom
|
||||
from parseMakefile import parse_makefile
|
||||
from collections import deque
|
||||
import argparse
|
||||
from setupVars import make_relative_path
|
||||
import myXML
|
||||
BITFIELD_WIDTHS = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
|
||||
|
||||
@@ -582,12 +581,12 @@ def generate_xml_output(proj_path, xml_path, unique_vars, h_files_needed, vars_n
|
||||
}
|
||||
|
||||
if makefile_path:
|
||||
rel_makefile = make_relative_path(makefile_path, proj_path)
|
||||
rel_makefile = myXML.make_relative_path(makefile_path, proj_path)
|
||||
if not os.path.isabs(rel_makefile):
|
||||
analysis_attrs["makefile_path"] = rel_makefile.replace("\\", "/")
|
||||
|
||||
if structs_xml_path:
|
||||
rel_struct = make_relative_path(structs_xml_path, proj_path)
|
||||
rel_struct = myXML.make_relative_path(structs_xml_path, proj_path)
|
||||
if not os.path.isabs(rel_struct):
|
||||
analysis_attrs["structs_path"] = rel_struct.replace("\\", "/")
|
||||
|
||||
@@ -919,6 +918,5 @@ def run_scan(proj_path, makefile_path, output_xml, verbose=2):
|
||||
|
||||
print("[XML] Creating vars.xml...")
|
||||
generate_xml_output(proj_path, output_xml, vars, includes, externs, structs_xml, makefile_path)
|
||||
print("Progress: 2/2")
|
||||
print('Progress: "Done"')
|
||||
print('Progress: 1/1')
|
||||
print("Progress: 2/2")
|
||||
|
||||
@@ -190,24 +190,44 @@ def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, de
|
||||
return []
|
||||
|
||||
# Вспомогательная функция для обработки массивов
|
||||
def process_array(prefix, base_type, dims):
|
||||
array_tree = generate_array_names(prefix, dims)
|
||||
array_flat = flatten_array_tree(array_tree)
|
||||
for node in array_flat:
|
||||
sub_items = expand_struct_recursively(node['name'], base_type, structs, typedefs, var_attrs, depth + 1)
|
||||
if sub_items:
|
||||
node['children'] = sub_items
|
||||
else:
|
||||
node.update({
|
||||
'type': base_type,
|
||||
'pt_type': '',
|
||||
'iq_type': '',
|
||||
'return_type': '',
|
||||
'file': var_attrs.get('file'),
|
||||
'extern': var_attrs.get('extern'),
|
||||
'static': var_attrs.get('static'),
|
||||
})
|
||||
return array_flat
|
||||
def process_array(prefix, type_str, structs, typedefs, var_attrs, depth=0):
|
||||
base_type, array_dims = parse_array_dims(type_str)
|
||||
if not array_dims:
|
||||
return []
|
||||
|
||||
# На текущем уровне берем первый размер массива
|
||||
current_dim = array_dims[0]
|
||||
# Оставшиеся размеры — все, кроме первого
|
||||
remaining_dims = array_dims[1:]
|
||||
|
||||
# Для создания типа с оставшимися размерами:
|
||||
if remaining_dims:
|
||||
# Формируем строку типа для оставшихся измерений массива, например int[16]
|
||||
remaining_type_str = f"{base_type}{''.join(f'[{d}]' for d in remaining_dims)}"
|
||||
else:
|
||||
remaining_type_str = base_type
|
||||
|
||||
array_tree = []
|
||||
for i in range(current_dim):
|
||||
name = f"{prefix}[{i}]"
|
||||
# Для каждого элемента передаем уже оставшийся тип массива
|
||||
children = expand_struct_recursively(name, remaining_type_str, structs, typedefs, var_attrs, depth + 1)
|
||||
node = {
|
||||
'name': name,
|
||||
'type': remaining_type_str if remaining_dims else base_type,
|
||||
'pt_type': '',
|
||||
'iq_type': '',
|
||||
'return_type': '',
|
||||
'file': var_attrs.get('file'),
|
||||
'extern': var_attrs.get('extern'),
|
||||
'static': var_attrs.get('static'),
|
||||
}
|
||||
if children:
|
||||
node['children'] = children
|
||||
array_tree.append(node)
|
||||
|
||||
return array_tree
|
||||
|
||||
|
||||
# Если type_str — уже распарсенная структура (dict)
|
||||
if isinstance(type_str, dict):
|
||||
@@ -216,7 +236,7 @@ def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, de
|
||||
# Проверяем, массив ли это
|
||||
base_type, array_dims = parse_array_dims(type_str)
|
||||
if array_dims:
|
||||
return process_array(prefix, base_type, array_dims)
|
||||
return process_array(prefix, type_str, structs, typedefs, var_attrs, depth)
|
||||
|
||||
# Ищем структуру по имени типа
|
||||
base_type = scanVars.strip_ptr_and_array(type_str)
|
||||
@@ -289,13 +309,9 @@ def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, de
|
||||
if "(" in field_type_str and "*" in field_type_str and ")" in field_type_str:
|
||||
continue
|
||||
|
||||
# Проверим, является ли тип структурой (по имени)
|
||||
clean_type = scanVars.strip_ptr_and_array(field_type_str)
|
||||
struct_fields = structs.get(clean_type)
|
||||
|
||||
if isinstance(struct_fields, dict):
|
||||
if isinstance(field_value, dict):
|
||||
# Это одиночная структура — раскрываем рекурсивно
|
||||
sub_items = expand_struct_recursively(full_name, field_type_str, structs, typedefs, var_attrs, depth + 1)
|
||||
sub_items = expand_struct_recursively(full_name, field_value, structs, typedefs, var_attrs, depth + 1)
|
||||
child = {
|
||||
'name': full_name,
|
||||
'type': field_type_str,
|
||||
|
||||
Reference in New Issue
Block a user