массивы вроде работают но тормозит. начата работа над оптимизацией
This commit is contained in:
parent
f271b2e82c
commit
ad7b9126b7
@ -24,7 +24,7 @@ class VariableSelectorDialog(QDialog):
|
|||||||
self.typedefs = typedefs
|
self.typedefs = typedefs
|
||||||
self.expanded_vars = []
|
self.expanded_vars = []
|
||||||
self.var_map = {v['name']: v for v in all_vars}
|
self.var_map = {v['name']: v for v in all_vars}
|
||||||
|
self.node_index = {}
|
||||||
self.xml_path = xml_path # сохраняем путь к xml
|
self.xml_path = xml_path # сохраняем путь к xml
|
||||||
|
|
||||||
# --- Добавляем чекбокс для автодополнения ---
|
# --- Добавляем чекбокс для автодополнения ---
|
||||||
@ -91,9 +91,32 @@ class VariableSelectorDialog(QDialog):
|
|||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
self.expanded_vars = setupVars.expand_vars(self.all_vars, self.structs, self.typedefs)
|
self.expanded_vars = setupVars.expand_vars(self.all_vars, self.structs, self.typedefs)
|
||||||
|
self.build_completion_list()
|
||||||
self.populate_tree()
|
self.populate_tree()
|
||||||
|
|
||||||
|
|
||||||
|
def get_full_item_name(self, item):
|
||||||
|
names = []
|
||||||
|
while item:
|
||||||
|
names.append(item.text(0))
|
||||||
|
item = item.parent()
|
||||||
|
return '.'.join(reversed(names))
|
||||||
|
|
||||||
|
def build_completion_list(self):
|
||||||
|
# Собираем список полных имён всех переменных и вложенных полей
|
||||||
|
completions = []
|
||||||
|
|
||||||
|
def recurse(var, prefix=''):
|
||||||
|
fullname = f"{prefix}.{var['name']}" if prefix else var['name']
|
||||||
|
completions.append(fullname)
|
||||||
|
for child in var.get('children', []):
|
||||||
|
recurse(child, fullname)
|
||||||
|
|
||||||
|
for v in self.expanded_vars:
|
||||||
|
recurse(v)
|
||||||
|
|
||||||
|
self.all_completions = completions
|
||||||
|
|
||||||
def add_tree_item_recursively(self, parent, var):
|
def add_tree_item_recursively(self, parent, var):
|
||||||
"""
|
"""
|
||||||
Рекурсивно добавляет переменную и её дочерние поля в дерево.
|
Рекурсивно добавляет переменную и её дочерние поля в дерево.
|
||||||
@ -105,6 +128,8 @@ class VariableSelectorDialog(QDialog):
|
|||||||
|
|
||||||
item = QTreeWidgetItem([name, type_str])
|
item = QTreeWidgetItem([name, type_str])
|
||||||
item.setData(0, Qt.UserRole, name)
|
item.setData(0, Qt.UserRole, name)
|
||||||
|
full_name = self.get_full_item_name(item)
|
||||||
|
self.node_index[full_name.lower()] = item
|
||||||
|
|
||||||
# Делаем bitfield-поля неактивными
|
# Делаем bitfield-поля неактивными
|
||||||
if "(bitfield:" in type_str:
|
if "(bitfield:" in type_str:
|
||||||
@ -130,6 +155,7 @@ class VariableSelectorDialog(QDialog):
|
|||||||
|
|
||||||
def populate_tree(self):
|
def populate_tree(self):
|
||||||
self.tree.clear()
|
self.tree.clear()
|
||||||
|
self.node_index.clear()
|
||||||
|
|
||||||
for var in self.expanded_vars:
|
for var in self.expanded_vars:
|
||||||
self.add_tree_item_recursively(None, var)
|
self.add_tree_item_recursively(None, var)
|
||||||
@ -209,74 +235,130 @@ class VariableSelectorDialog(QDialog):
|
|||||||
item = self.tree.topLevelItem(i)
|
item = self.tree.topLevelItem(i)
|
||||||
hide_all(item)
|
hide_all(item)
|
||||||
show_matching_path(item, 0)
|
show_matching_path(item, 0)
|
||||||
|
|
||||||
def update_completions(self, text = None):
|
def find_node_by_path(self, root_vars, path_list):
|
||||||
|
current_level = root_vars
|
||||||
|
node = None
|
||||||
|
for part in path_list:
|
||||||
|
node = None
|
||||||
|
for var in current_level:
|
||||||
|
if var['name'] == part:
|
||||||
|
node = var
|
||||||
|
break
|
||||||
|
if node is None:
|
||||||
|
return None
|
||||||
|
current_level = node.get('children', [])
|
||||||
|
return node
|
||||||
|
|
||||||
|
def update_completions(self, text=None):
|
||||||
if text is None:
|
if text is None:
|
||||||
text = self.search_input.text().strip()
|
text = self.search_input.text().strip()
|
||||||
else:
|
else:
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
|
|
||||||
parts = self.split_path(text)
|
parts = self.split_path(text)
|
||||||
path_parts = parts[:-1]
|
path_parts = parts[:-1] if parts else []
|
||||||
prefix = parts[-1].lower() if not text.endswith(('.', '>')) else ''
|
prefix = parts[-1].lower() if parts else ''
|
||||||
|
ends_with_sep = text.endswith('.') or text.endswith('->') or text.endswith('[')
|
||||||
|
is_index_suggestion = text.endswith('[')
|
||||||
|
|
||||||
# Если путь есть (например: project.adc или project.adc.), ищем внутри него
|
completions = []
|
||||||
search_deep = len(path_parts) > 0
|
|
||||||
|
|
||||||
def find_path_items(path_parts):
|
def find_path_items(parts):
|
||||||
items = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
|
items = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
|
||||||
|
for part in parts:
|
||||||
for part in path_parts:
|
|
||||||
part_lower = part.lower()
|
part_lower = part.lower()
|
||||||
matched = []
|
matched = []
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
# Берём последний фрагмент имени item, разделённого точками
|
name_parts = self.split_path(item.text(0).lower())
|
||||||
item_name_part = self.split_path(item.text(0))[-1].lower()
|
if name_parts and name_parts[-1] == part_lower:
|
||||||
|
|
||||||
if item_name_part == part_lower:
|
|
||||||
matched.append(item)
|
matched.append(item)
|
||||||
|
|
||||||
if not matched:
|
if not matched:
|
||||||
return []
|
return []
|
||||||
items = []
|
items = []
|
||||||
# Собираем детей для следующего уровня поиска
|
|
||||||
for node in matched:
|
for node in matched:
|
||||||
for i in range(node.childCount()):
|
for i in range(node.childCount()):
|
||||||
items.append(node.child(i))
|
items.append(node.child(i))
|
||||||
|
|
||||||
return matched
|
return matched
|
||||||
|
|
||||||
if not search_deep:
|
if is_index_suggestion:
|
||||||
# Без точки — ищем только в топ-уровне, фильтруя по prefix
|
# Предлагаем индексы (ищем всех детей с форматом foo[0], foo[1], ...)
|
||||||
items = []
|
base_text = text[:-1] # убираем '[', получаем, например, 'foo'
|
||||||
|
parent_node = self.find_node_by_fullname(base_text)
|
||||||
|
if not parent_node:
|
||||||
|
parent_node = self.find_node_by_fullname(base_text.rstrip('0123456789[]'))
|
||||||
|
if parent_node:
|
||||||
|
seen = set()
|
||||||
|
for i in range(parent_node.childCount()):
|
||||||
|
child = parent_node.child(i)
|
||||||
|
cname = child.text(0)
|
||||||
|
m = re.match(rf'^{re.escape(base_text)}\[(\d+)\]$', cname)
|
||||||
|
if m and cname not in seen:
|
||||||
|
completions.append(cname)
|
||||||
|
seen.add(cname)
|
||||||
|
self.completer.setModel(QStringListModel(completions))
|
||||||
|
return completions
|
||||||
|
|
||||||
|
if ends_with_sep:
|
||||||
|
# Завершён путь (например: project.adc[0].), показываем детей
|
||||||
|
node = self.find_node_by_fullname(text[:-1])
|
||||||
|
if node:
|
||||||
|
for i in range(node.childCount()):
|
||||||
|
completions.append(node.child(i).text(0))
|
||||||
|
elif not path_parts:
|
||||||
|
# Первый уровень — по вхождению
|
||||||
for i in range(self.tree.topLevelItemCount()):
|
for i in range(self.tree.topLevelItemCount()):
|
||||||
item = self.tree.topLevelItem(i)
|
item = self.tree.topLevelItem(i)
|
||||||
name_part = self.split_path(item.text(0))[-1].lower()
|
name = item.text(0).lower()
|
||||||
if name_part.startswith(prefix):
|
if prefix in name:
|
||||||
items.append(item)
|
completions.append(item.text(0))
|
||||||
completions = [item.text(0) for item in items]
|
|
||||||
else:
|
else:
|
||||||
# С точкой — углубляемся по пути и показываем имена детей
|
# Углубляемся: на последнем уровне используем startswith(prefix)
|
||||||
if len(path_parts) == 0:
|
matched_items = find_path_items(path_parts)
|
||||||
items = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
|
for item in matched_items:
|
||||||
else:
|
|
||||||
items = find_path_items(path_parts)
|
|
||||||
|
|
||||||
completions = []
|
|
||||||
for item in items:
|
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
name_part = self.split_path(child.text(0))[-1].lower()
|
name = child.text(0)
|
||||||
if prefix == '' or name_part.startswith(prefix):
|
name_parts = self.split_path(name)
|
||||||
completions.append(child.text(0))
|
if not name_parts:
|
||||||
|
continue
|
||||||
|
last_part = name_parts[-1].lower()
|
||||||
|
if prefix == '' or last_part.startswith(prefix):
|
||||||
|
completions.append(name)
|
||||||
|
|
||||||
self.completer.setModel(QStringListModel(completions))
|
self.completer.setModel(QStringListModel(completions))
|
||||||
return completions
|
return completions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Функция для поиска узла с полным именем
|
||||||
|
def find_node_by_fullname(self, name):
|
||||||
|
return self.node_index.get(name.lower())
|
||||||
|
|
||||||
|
def insert_completion(self, text):
|
||||||
|
node = self.find_node_by_fullname(text)
|
||||||
|
if node and node.childCount() > 0 and not (text.endswith('.') or text.endswith('->') or text.endswith('[')):
|
||||||
|
# Определяем разделитель по имени первого ребёнка
|
||||||
|
child_name = node.child(0).text(0)
|
||||||
|
if child_name.startswith(text + '->'):
|
||||||
|
text += '->'
|
||||||
|
elif child_name.startswith(text + '.'):
|
||||||
|
text += '.'
|
||||||
|
elif '[' in child_name:
|
||||||
|
text += '[' # для массивов
|
||||||
|
else:
|
||||||
|
text += '.' # fallback
|
||||||
|
|
||||||
|
self.search_input.setText(text)
|
||||||
|
self.search_input.setCursorPosition(len(text))
|
||||||
|
self.update_completions()
|
||||||
|
self.completer.complete()
|
||||||
|
else:
|
||||||
|
self.search_input.setText(text)
|
||||||
|
self.search_input.setCursorPosition(len(text))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def eventFilter(self, obj, event):
|
def eventFilter(self, obj, event):
|
||||||
if obj == self.search_input and isinstance(event, QKeyEvent):
|
if obj == self.search_input and isinstance(event, QKeyEvent):
|
||||||
if event.key() == Qt.Key_Space and event.modifiers() & Qt.ControlModifier:
|
if event.key() == Qt.Key_Space and event.modifiers() & Qt.ControlModifier:
|
||||||
@ -325,36 +407,6 @@ class VariableSelectorDialog(QDialog):
|
|||||||
|
|
||||||
return super().eventFilter(obj, event)
|
return super().eventFilter(obj, event)
|
||||||
|
|
||||||
# Функция для поиска узла с полным именем
|
|
||||||
def find_node_by_fullname(self, name):
|
|
||||||
stack = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
|
|
||||||
while stack:
|
|
||||||
node = stack.pop()
|
|
||||||
if node.text(0).lower() == name.lower():
|
|
||||||
return node
|
|
||||||
for i in range(node.childCount()):
|
|
||||||
stack.append(node.child(i))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def insert_completion(self, text):
|
|
||||||
|
|
||||||
node = self.find_node_by_fullname(text)
|
|
||||||
if node and node.childCount() > 0 and not (text.endswith('.') or text.endswith('->')):
|
|
||||||
# Определяем разделитель по имени первого ребёнка
|
|
||||||
child_name = node.child(0).text(0)
|
|
||||||
if child_name.startswith(text + '->'):
|
|
||||||
text += '->'
|
|
||||||
else:
|
|
||||||
text += '.'
|
|
||||||
|
|
||||||
self.search_input.setText(text)
|
|
||||||
self.search_input.setCursorPosition(len(text))
|
|
||||||
self.update_completions()
|
|
||||||
self.completer.complete()
|
|
||||||
else:
|
|
||||||
self.search_input.setText(text)
|
|
||||||
self.search_input.setCursorPosition(len(text))
|
|
||||||
|
|
||||||
def on_search_text_changed(self, text):
|
def on_search_text_changed(self, text):
|
||||||
if self.autocomplete_checkbox.isChecked():
|
if self.autocomplete_checkbox.isChecked():
|
||||||
completions = self.update_completions(text)
|
completions = self.update_completions(text)
|
||||||
@ -532,6 +584,49 @@ class VariableSelectorDialog(QDialog):
|
|||||||
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
|
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def split_path(self, path):
|
def split_path(self, path):
|
||||||
# Разбиваем по точке или по -> (учитываем, что -> длиной 2 символа)
|
"""
|
||||||
return re.split(r'\.|->', path)
|
Разбивает путь на компоненты:
|
||||||
|
- 'foo[2].bar[1]->baz' → ['foo', [2]', 'bar', '[1]' 'baz']
|
||||||
|
"""
|
||||||
|
tokens = []
|
||||||
|
token = ''
|
||||||
|
i = 0
|
||||||
|
while i < len(path):
|
||||||
|
c = path[i]
|
||||||
|
# Разделители: '->' и '.'
|
||||||
|
if c == '-' and path[i:i+2] == '->':
|
||||||
|
if token:
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
elif c == '.':
|
||||||
|
if token:
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
elif c == '[':
|
||||||
|
# Заканчиваем текущий токен, если есть
|
||||||
|
if token:
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
# Собираем индекс [N]
|
||||||
|
idx = ''
|
||||||
|
while i < len(path) and path[i] != ']':
|
||||||
|
idx += path[i]
|
||||||
|
i += 1
|
||||||
|
if i < len(path) and path[i] == ']':
|
||||||
|
idx += ']'
|
||||||
|
i += 1
|
||||||
|
tokens.append(idx)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
token += c
|
||||||
|
i += 1
|
||||||
|
if token:
|
||||||
|
tokens.append(token)
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
170
Src/setupVars.py
170
Src/setupVars.py
@ -153,37 +153,158 @@ def parse_structs(filename):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_array_dims(type_str):
|
||||||
|
"""Возвращает базовый тип и список размеров массива"""
|
||||||
|
dims = list(map(int, re.findall(r'\[(\d+)\]', type_str)))
|
||||||
|
base_type = re.sub(r'\[\d+\]', '', type_str).strip()
|
||||||
|
return base_type, dims
|
||||||
|
|
||||||
|
def generate_array_names(prefix, dims, depth=0):
|
||||||
|
"""Рекурсивно генерирует имена для всех элементов многомерного массива"""
|
||||||
|
if not dims:
|
||||||
|
return [prefix]
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for i in range(dims[0]):
|
||||||
|
new_prefix = f"{prefix}[{i}]"
|
||||||
|
children = generate_array_names(new_prefix, dims[1:], depth + 1)
|
||||||
|
result.append({
|
||||||
|
'name': new_prefix,
|
||||||
|
'children': children if len(dims) > 1 else None
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def flatten_array_tree(array_tree):
|
||||||
|
"""Разворачивает дерево массивов в линейный список с вложенными children"""
|
||||||
|
result = []
|
||||||
|
for node in array_tree:
|
||||||
|
entry = {'name': node['name']}
|
||||||
|
if node['children']:
|
||||||
|
entry['children'] = flatten_array_tree(node['children'])
|
||||||
|
result.append(entry)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, depth=0):
|
def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, depth=0):
|
||||||
if depth > 10:
|
if depth > 10:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Если type_str — словарь структуры
|
# Вспомогательная функция для обработки массивов
|
||||||
|
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
|
||||||
|
|
||||||
|
# Если type_str — уже распарсенная структура (dict)
|
||||||
if isinstance(type_str, dict):
|
if isinstance(type_str, dict):
|
||||||
fields = type_str
|
fields = type_str
|
||||||
else:
|
else:
|
||||||
|
# Проверяем, массив ли это
|
||||||
|
base_type, array_dims = parse_array_dims(type_str)
|
||||||
|
if array_dims:
|
||||||
|
return process_array(prefix, base_type, array_dims)
|
||||||
|
|
||||||
|
# Ищем структуру по имени типа
|
||||||
base_type = scanVars.strip_ptr_and_array(type_str)
|
base_type = scanVars.strip_ptr_and_array(type_str)
|
||||||
fields = structs.get(base_type)
|
fields = structs.get(base_type)
|
||||||
if not isinstance(fields, dict):
|
if not isinstance(fields, dict):
|
||||||
|
# Не структура и не массив — просто возвращаем пустой список
|
||||||
return []
|
return []
|
||||||
|
|
||||||
children = []
|
children = []
|
||||||
for field_name, field_value in fields.items():
|
for field_name, field_value in fields.items():
|
||||||
# Пропускаем поле 'type', оно служит для хранения имени типа
|
|
||||||
if field_name == 'type':
|
if field_name == 'type':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Определяем разделитель между prefix и полем
|
# Формируем полное имя поля
|
||||||
if prefix.endswith('*'):
|
if prefix.endswith('*'):
|
||||||
separator = '->'
|
separator = '->'
|
||||||
# Для красоты можно убрать пробелы у указателя
|
|
||||||
# например, если prefix="ptr*" -> "ptr->field"
|
|
||||||
full_name = f"{prefix[:-1]}{separator}{field_name}"
|
full_name = f"{prefix[:-1]}{separator}{field_name}"
|
||||||
else:
|
else:
|
||||||
separator = '.'
|
separator = '.'
|
||||||
full_name = f"{prefix}{separator}{field_name}"
|
full_name = f"{prefix}{separator}{field_name}"
|
||||||
|
|
||||||
|
# Определяем тип поля
|
||||||
|
if isinstance(field_value, dict) and isinstance(field_value.get('type'), str):
|
||||||
|
field_type_str = field_value['type']
|
||||||
|
elif isinstance(field_value, str):
|
||||||
|
field_type_str = field_value
|
||||||
|
else:
|
||||||
|
field_type_str = None
|
||||||
|
|
||||||
|
# Обработка, если поле — строка (тип или массив)
|
||||||
|
if field_type_str:
|
||||||
|
base_subtype, sub_dims = parse_array_dims(field_type_str)
|
||||||
|
if sub_dims:
|
||||||
|
# Массив — раскрываем элементы
|
||||||
|
array_parent = {
|
||||||
|
'name': full_name,
|
||||||
|
'type': field_type_str,
|
||||||
|
'pt_type': '',
|
||||||
|
'iq_type': '',
|
||||||
|
'return_type': '',
|
||||||
|
'file': var_attrs.get('file'),
|
||||||
|
'extern': var_attrs.get('extern'),
|
||||||
|
'static': var_attrs.get('static'),
|
||||||
|
}
|
||||||
|
|
||||||
|
array_children = []
|
||||||
|
flat_names = generate_array_names(full_name, sub_dims)
|
||||||
|
for node in flat_names:
|
||||||
|
# node — dict с ключом 'name' и (возможно) 'children'
|
||||||
|
sub_items = expand_struct_recursively(node['name'], base_subtype, structs, typedefs, var_attrs, depth + 1)
|
||||||
|
child_node = {
|
||||||
|
'name': node['name'],
|
||||||
|
'type': base_subtype,
|
||||||
|
'pt_type': '',
|
||||||
|
'iq_type': '',
|
||||||
|
'return_type': '',
|
||||||
|
'file': var_attrs.get('file'),
|
||||||
|
'extern': var_attrs.get('extern'),
|
||||||
|
'static': var_attrs.get('static'),
|
||||||
|
}
|
||||||
|
if sub_items:
|
||||||
|
child_node['children'] = sub_items
|
||||||
|
array_children.append(child_node)
|
||||||
|
|
||||||
|
array_parent['children'] = array_children
|
||||||
|
children.append(array_parent)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Игнорируем указатели на функции
|
||||||
|
if "(" in field_type_str and "*" in field_type_str and ")" in field_type_str:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Обычное поле (не массив, не функция)
|
||||||
|
child = {
|
||||||
|
'name': full_name,
|
||||||
|
'type': field_type_str,
|
||||||
|
'pt_type': '',
|
||||||
|
'iq_type': '',
|
||||||
|
'return_type': '',
|
||||||
|
'file': var_attrs.get('file'),
|
||||||
|
'extern': var_attrs.get('extern'),
|
||||||
|
'static': var_attrs.get('static'),
|
||||||
|
}
|
||||||
|
children.append(child)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Если поле — dict без 'type' или со сложной структурой, обрабатываем как вложенную структуру
|
||||||
if isinstance(field_value, dict):
|
if isinstance(field_value, dict):
|
||||||
# Если вложенная структура — берем её имя типа из поля 'type' или пустую строку
|
|
||||||
type_name = field_value.get('type', '')
|
type_name = field_value.get('type', '')
|
||||||
child = {
|
child = {
|
||||||
'name': full_name,
|
'name': full_name,
|
||||||
@ -195,35 +316,14 @@ def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, de
|
|||||||
'extern': var_attrs.get('extern'),
|
'extern': var_attrs.get('extern'),
|
||||||
'static': var_attrs.get('static'),
|
'static': var_attrs.get('static'),
|
||||||
}
|
}
|
||||||
if '*' in type_name and not full_name.endswith('*'):
|
|
||||||
full_name += '*'
|
|
||||||
# Рекурсивно раскрываем вложенные поля
|
|
||||||
subchildren = expand_struct_recursively(full_name, field_value, structs, typedefs, var_attrs, depth + 1)
|
subchildren = expand_struct_recursively(full_name, field_value, structs, typedefs, var_attrs, depth + 1)
|
||||||
if subchildren:
|
if subchildren:
|
||||||
child['children'] = subchildren
|
child['children'] = subchildren
|
||||||
else:
|
children.append(child)
|
||||||
# Простое поле — строка типа
|
|
||||||
# Пропускаем указатели на функции
|
|
||||||
if isinstance(field_value, str) and "(" in field_value and "*" in field_value and ")" in field_value:
|
|
||||||
continue
|
|
||||||
|
|
||||||
child = {
|
|
||||||
'name': full_name,
|
|
||||||
'type': field_value,
|
|
||||||
'pt_type': '',
|
|
||||||
'iq_type': '',
|
|
||||||
'return_type': '',
|
|
||||||
'file': var_attrs.get('file'),
|
|
||||||
'extern': var_attrs.get('extern'),
|
|
||||||
'static': var_attrs.get('static'),
|
|
||||||
}
|
|
||||||
|
|
||||||
children.append(child)
|
|
||||||
|
|
||||||
return children
|
return children
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def expand_vars(vars_list, structs, typedefs):
|
def expand_vars(vars_list, structs, typedefs):
|
||||||
"""
|
"""
|
||||||
Раскрывает структуры и массивы структур в деревья.
|
Раскрывает структуры и массивы структур в деревья.
|
||||||
@ -233,26 +333,26 @@ def expand_vars(vars_list, structs, typedefs):
|
|||||||
for var in vars_list:
|
for var in vars_list:
|
||||||
pt_type = var.get('pt_type', '')
|
pt_type = var.get('pt_type', '')
|
||||||
raw_type = var.get('type', '')
|
raw_type = var.get('type', '')
|
||||||
base_type = scanVars.strip_ptr_and_array(raw_type)
|
|
||||||
|
|
||||||
fields = structs.get(base_type)
|
if var['name'] == 'project':
|
||||||
|
a = 1
|
||||||
if pt_type.startswith('pt_ptr_') and isinstance(fields, dict):
|
|
||||||
|
if pt_type.startswith('pt_ptr_'):
|
||||||
new_var = var.copy()
|
new_var = var.copy()
|
||||||
new_var['children'] = expand_struct_recursively(var['name']+'*', raw_type, structs, typedefs, var)
|
new_var['children'] = expand_struct_recursively(var['name']+'*', raw_type, structs, typedefs, var)
|
||||||
expanded.append(new_var)
|
expanded.append(new_var)
|
||||||
|
|
||||||
if pt_type.startswith('pt_arr_') and isinstance(fields, dict):
|
if pt_type.startswith('pt_arr_'):
|
||||||
new_var = var.copy()
|
new_var = var.copy()
|
||||||
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
||||||
expanded.append(new_var)
|
expanded.append(new_var)
|
||||||
|
|
||||||
elif pt_type == 'pt_struct' and isinstance(fields, dict):
|
elif pt_type == 'pt_struct':
|
||||||
new_var = var.copy()
|
new_var = var.copy()
|
||||||
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
||||||
expanded.append(new_var)
|
expanded.append(new_var)
|
||||||
|
|
||||||
elif pt_type == 'pt_union' and isinstance(fields, dict):
|
elif pt_type == 'pt_union':
|
||||||
new_var = var.copy()
|
new_var = var.copy()
|
||||||
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
new_var['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
|
||||||
expanded.append(new_var)
|
expanded.append(new_var)
|
||||||
|
4
vars.xml
4
vars.xml
@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<analysis makefile_path="Debug/makefile" proj_path="E:/.WORK/TMS/TMS_new_bus" structs_path="Src/DebugTools/structs.xml">
|
<analysis makefile_path="Debug/makefile" proj_path="F:/Work/Projects/TMS/TMS_new_bus" structs_path="Src/DebugTools/structs.xml">
|
||||||
<variables>
|
<variables>
|
||||||
<var name="ADC0finishAddr">
|
<var name="ADC0finishAddr">
|
||||||
<show_var>true</show_var>
|
<show_var>true</show_var>
|
||||||
@ -3592,7 +3592,7 @@
|
|||||||
<var name="project.cds_tk.count_elements_pbus">
|
<var name="project.cds_tk.count_elements_pbus">
|
||||||
<show_var>true</show_var>
|
<show_var>true</show_var>
|
||||||
<enable>true</enable>
|
<enable>true</enable>
|
||||||
<shortname>project.cds_tk.count_elements=_pbus</shortname>
|
<shortname>project.cds_tk.count_elements_pbus</shortname>
|
||||||
<pt_type>pt_uint64</pt_type>
|
<pt_type>pt_uint64</pt_type>
|
||||||
<iq_type>t_iq_none</iq_type>
|
<iq_type>t_iq_none</iq_type>
|
||||||
<return_type>t_iq_none</return_type>
|
<return_type>t_iq_none</return_type>
|
||||||
|
Loading…
Reference in New Issue
Block a user