массивы вроде работают но тормозит. начата работа над оптимизацией
This commit is contained in:
		
							parent
							
								
									f271b2e82c
								
							
						
					
					
						commit
						ad7b9126b7
					
				@ -24,7 +24,7 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
        self.typedefs = typedefs
 | 
			
		||||
        self.expanded_vars = []
 | 
			
		||||
        self.var_map = {v['name']: v for v in all_vars}
 | 
			
		||||
 | 
			
		||||
        self.node_index = {}
 | 
			
		||||
        self.xml_path = xml_path  # сохраняем путь к xml
 | 
			
		||||
 | 
			
		||||
        # --- Добавляем чекбокс для автодополнения ---
 | 
			
		||||
@ -91,9 +91,32 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
        self.setLayout(layout)
 | 
			
		||||
        
 | 
			
		||||
        self.expanded_vars = setupVars.expand_vars(self.all_vars, self.structs, self.typedefs)
 | 
			
		||||
 | 
			
		||||
        self.build_completion_list()
 | 
			
		||||
        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):
 | 
			
		||||
        """
 | 
			
		||||
        Рекурсивно добавляет переменную и её дочерние поля в дерево.
 | 
			
		||||
@ -105,6 +128,8 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
 | 
			
		||||
        item = QTreeWidgetItem([name, type_str])
 | 
			
		||||
        item.setData(0, Qt.UserRole, name)
 | 
			
		||||
        full_name = self.get_full_item_name(item)
 | 
			
		||||
        self.node_index[full_name.lower()] = item
 | 
			
		||||
 | 
			
		||||
        # Делаем bitfield-поля неактивными
 | 
			
		||||
        if "(bitfield:" in type_str:
 | 
			
		||||
@ -130,6 +155,7 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
 | 
			
		||||
    def populate_tree(self):
 | 
			
		||||
        self.tree.clear()
 | 
			
		||||
        self.node_index.clear()
 | 
			
		||||
 | 
			
		||||
        for var in self.expanded_vars:
 | 
			
		||||
            self.add_tree_item_recursively(None, var)
 | 
			
		||||
@ -210,73 +236,129 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
                hide_all(item)
 | 
			
		||||
                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:
 | 
			
		||||
            text = self.search_input.text().strip()
 | 
			
		||||
        else:
 | 
			
		||||
            text = text.strip()
 | 
			
		||||
 | 
			
		||||
        parts = self.split_path(text)
 | 
			
		||||
        path_parts = parts[:-1]
 | 
			
		||||
        prefix = parts[-1].lower() if not text.endswith(('.', '>')) else ''
 | 
			
		||||
        path_parts = parts[:-1] if parts 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.), ищем внутри него
 | 
			
		||||
        search_deep = len(path_parts) > 0
 | 
			
		||||
        completions = []
 | 
			
		||||
 | 
			
		||||
        def find_path_items(path_parts):
 | 
			
		||||
        def find_path_items(parts):
 | 
			
		||||
            items = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
 | 
			
		||||
 | 
			
		||||
            for part in path_parts:
 | 
			
		||||
            for part in parts:
 | 
			
		||||
                part_lower = part.lower()
 | 
			
		||||
                matched = []
 | 
			
		||||
 | 
			
		||||
                for item in items:
 | 
			
		||||
                    # Берём последний фрагмент имени item, разделённого точками
 | 
			
		||||
                    item_name_part = self.split_path(item.text(0))[-1].lower()
 | 
			
		||||
                    
 | 
			
		||||
                    if item_name_part == part_lower:
 | 
			
		||||
                    name_parts = self.split_path(item.text(0).lower())
 | 
			
		||||
                    if name_parts and name_parts[-1] == part_lower:
 | 
			
		||||
                        matched.append(item)
 | 
			
		||||
 | 
			
		||||
                if not matched:
 | 
			
		||||
                    return []
 | 
			
		||||
                items = []
 | 
			
		||||
                # Собираем детей для следующего уровня поиска
 | 
			
		||||
                for node in matched:
 | 
			
		||||
                    for i in range(node.childCount()):
 | 
			
		||||
                        items.append(node.child(i))
 | 
			
		||||
 | 
			
		||||
            return matched
 | 
			
		||||
 | 
			
		||||
        if not search_deep:
 | 
			
		||||
            # Без точки — ищем только в топ-уровне, фильтруя по prefix
 | 
			
		||||
            items = []
 | 
			
		||||
        if is_index_suggestion:
 | 
			
		||||
            # Предлагаем индексы (ищем всех детей с форматом foo[0], foo[1], ...)
 | 
			
		||||
            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()):
 | 
			
		||||
                item = self.tree.topLevelItem(i)
 | 
			
		||||
                name_part = self.split_path(item.text(0))[-1].lower()
 | 
			
		||||
                if name_part.startswith(prefix):
 | 
			
		||||
                    items.append(item)
 | 
			
		||||
            completions = [item.text(0) for item in items]
 | 
			
		||||
                name = item.text(0).lower()
 | 
			
		||||
                if prefix in name:
 | 
			
		||||
                    completions.append(item.text(0))
 | 
			
		||||
        else:
 | 
			
		||||
            # С точкой — углубляемся по пути и показываем имена детей
 | 
			
		||||
            if len(path_parts) == 0:
 | 
			
		||||
                items = [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())]
 | 
			
		||||
            else:
 | 
			
		||||
                items = find_path_items(path_parts)
 | 
			
		||||
 | 
			
		||||
            completions = []
 | 
			
		||||
            for item in items:
 | 
			
		||||
            # Углубляемся: на последнем уровне используем startswith(prefix)
 | 
			
		||||
            matched_items = find_path_items(path_parts)
 | 
			
		||||
            for item in matched_items:
 | 
			
		||||
                for i in range(item.childCount()):
 | 
			
		||||
                    child = item.child(i)
 | 
			
		||||
                    name_part = self.split_path(child.text(0))[-1].lower()
 | 
			
		||||
                    if prefix == '' or name_part.startswith(prefix):
 | 
			
		||||
                        completions.append(child.text(0))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    name = child.text(0)
 | 
			
		||||
                    name_parts = self.split_path(name)
 | 
			
		||||
                    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))
 | 
			
		||||
        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):
 | 
			
		||||
        if obj == self.search_input and isinstance(event, QKeyEvent):
 | 
			
		||||
            if event.key() == Qt.Key_Space and event.modifiers() & Qt.ControlModifier:
 | 
			
		||||
@ -325,36 +407,6 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
 | 
			
		||||
        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):
 | 
			
		||||
        if self.autocomplete_checkbox.isChecked():
 | 
			
		||||
            completions = self.update_completions(text)
 | 
			
		||||
@ -532,6 +584,49 @@ class VariableSelectorDialog(QDialog):
 | 
			
		||||
        self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										168
									
								
								Src/setupVars.py
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								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):
 | 
			
		||||
    if depth > 10:
 | 
			
		||||
        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):
 | 
			
		||||
        fields = type_str
 | 
			
		||||
    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)
 | 
			
		||||
        fields = structs.get(base_type)
 | 
			
		||||
        if not isinstance(fields, dict):
 | 
			
		||||
            # Не структура и не массив — просто возвращаем пустой список
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
    children = []
 | 
			
		||||
    for field_name, field_value in fields.items():
 | 
			
		||||
        # Пропускаем поле 'type', оно служит для хранения имени типа
 | 
			
		||||
        if field_name == 'type':
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # Определяем разделитель между prefix и полем
 | 
			
		||||
        # Формируем полное имя поля
 | 
			
		||||
        if prefix.endswith('*'):
 | 
			
		||||
            separator = '->'
 | 
			
		||||
            # Для красоты можно убрать пробелы у указателя
 | 
			
		||||
            # например, если prefix="ptr*" -> "ptr->field"
 | 
			
		||||
            full_name = f"{prefix[:-1]}{separator}{field_name}"
 | 
			
		||||
        else:
 | 
			
		||||
            separator = '.'
 | 
			
		||||
            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):
 | 
			
		||||
            # Если вложенная структура — берем её имя типа из поля 'type' или пустую строку
 | 
			
		||||
            type_name = field_value.get('type', '')
 | 
			
		||||
            child = {
 | 
			
		||||
                'name': full_name,
 | 
			
		||||
@ -195,35 +316,14 @@ def expand_struct_recursively(prefix, type_str, structs, typedefs, var_attrs, de
 | 
			
		||||
                'extern': var_attrs.get('extern'),
 | 
			
		||||
                '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)
 | 
			
		||||
            if subchildren:
 | 
			
		||||
                child['children'] = subchildren
 | 
			
		||||
        else:
 | 
			
		||||
            # Простое поле — строка типа
 | 
			
		||||
            # Пропускаем указатели на функции
 | 
			
		||||
            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)
 | 
			
		||||
            children.append(child)
 | 
			
		||||
 | 
			
		||||
    return children
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def expand_vars(vars_list, structs, typedefs):
 | 
			
		||||
    """
 | 
			
		||||
    Раскрывает структуры и массивы структур в деревья.
 | 
			
		||||
@ -233,26 +333,26 @@ def expand_vars(vars_list, structs, typedefs):
 | 
			
		||||
    for var in vars_list:
 | 
			
		||||
        pt_type = var.get('pt_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['children'] = expand_struct_recursively(var['name']+'*', raw_type, structs, typedefs, 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['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, 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['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, 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['children'] = expand_struct_recursively(var['name'], raw_type, structs, typedefs, var)
 | 
			
		||||
            expanded.append(new_var)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								vars.xml
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								vars.xml
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
			
		||||
<?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>
 | 
			
		||||
    <var name="ADC0finishAddr">
 | 
			
		||||
      <show_var>true</show_var>
 | 
			
		||||
@ -3592,7 +3592,7 @@
 | 
			
		||||
    <var name="project.cds_tk.count_elements_pbus">
 | 
			
		||||
      <show_var>true</show_var>
 | 
			
		||||
      <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>
 | 
			
		||||
      <iq_type>t_iq_none</iq_type>
 | 
			
		||||
      <return_type>t_iq_none</return_type>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user