可用的回归测试通过的标准版本
This commit is contained in:
@@ -1,207 +1,207 @@
|
||||
from __future__ import annotations
|
||||
from typing import Any, Dict, Optional, TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
|
||||
from lib.includes import t
|
||||
|
||||
|
||||
class SymbolNode:
|
||||
"""符号表节点,类似 AST 节点的树形结构
|
||||
|
||||
attributes 存储 CTypeInfo 对象,不再使用 TypeInfo
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, NodeType: str, lineno: int = 0, file: str = '', parent: SymbolNode | None = None):
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
self.name: str = name
|
||||
self.type: str = NodeType
|
||||
self.lineno: int = lineno
|
||||
self.file: str = file
|
||||
self.parent: SymbolNode | None = parent
|
||||
self.children: Dict[str, SymbolNode] = {}
|
||||
self.attributes: CTypeInfo = CTypeInfo()
|
||||
self.attributes.Name = name
|
||||
self.attributes.Lineno = lineno
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""获取属性值"""
|
||||
if hasattr(self.attributes, key):
|
||||
return getattr(self.attributes, key)
|
||||
return self.attributes._extra.get(key, default)
|
||||
|
||||
def set(self, key: str, value: Any):
|
||||
"""设置属性值"""
|
||||
if hasattr(self.attributes, key):
|
||||
attr = getattr(type(self.attributes), key, None)
|
||||
if isinstance(attr, property) and attr.fset is None:
|
||||
return
|
||||
setattr(self.attributes, key, value)
|
||||
else:
|
||||
self.attributes._extra[key] = value
|
||||
|
||||
def HasChild(self, name: str) -> bool:
|
||||
"""检查是否有子节点"""
|
||||
return name in self.children
|
||||
|
||||
def GetChild(self, name: str) -> Optional[SymbolNode]:
|
||||
"""获取子节点"""
|
||||
return self.children.get(name)
|
||||
|
||||
def AddChild(self, node: SymbolNode):
|
||||
"""添加子节点"""
|
||||
node.parent = self
|
||||
self.children[node.name] = node
|
||||
|
||||
def RemoveChild(self, name: str) -> bool:
|
||||
"""删除子节点"""
|
||||
if name in self.children:
|
||||
del self.children[name]
|
||||
return True
|
||||
return False
|
||||
|
||||
def find(self, path: str, separator: str = '.') -> Optional[SymbolNode]:
|
||||
"""根据路径查找节点,如 'test.ClassA'"""
|
||||
parts = path.split(separator)
|
||||
current = self
|
||||
|
||||
for part in parts:
|
||||
if current.HasChild(part):
|
||||
current = current.GetChild(part)
|
||||
else:
|
||||
return None
|
||||
|
||||
return current
|
||||
|
||||
def ToDict(self) -> Dict[str, Any]:
|
||||
"""转换为字典格式"""
|
||||
result = {
|
||||
'type': self.type,
|
||||
'lineno': self.lineno,
|
||||
'file': self.file,
|
||||
**self.attributes.entry
|
||||
}
|
||||
|
||||
if self.children:
|
||||
result['children'] = {name: child.ToDict() for name, child in self.children.items()}
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def FromDict(cls, name: str, data: Dict[str, Any]) -> SymbolNode:
|
||||
"""从字典创建节点(兼容性)"""
|
||||
node = cls(name=name, NodeType=data.get('type', 'unknown'))
|
||||
node.lineno = data.get('lineno', 0)
|
||||
node.file = data.get('file', '')
|
||||
|
||||
for key, value in data.items():
|
||||
if key not in ('type', 'lineno', 'file', 'children'):
|
||||
node.set(key, value)
|
||||
|
||||
if 'children' in data:
|
||||
for ChildName, ChildData in data['children'].items():
|
||||
node.AddChild(cls.FromDict(ChildName, ChildData))
|
||||
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateMember(cls, name: str, TypeName: str | None = None, TypeInfo: 'CTypeInfo | None' = None, IsPtr: bool = False, dims: list[int] | None = None, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建成员节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType='member', lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
if TypeInfo is not None:
|
||||
node.attributes = TypeInfo
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
else:
|
||||
if TypeName is not None:
|
||||
node.attributes.BaseType = CTypeInfo.CreateFromTypeName(TypeName)
|
||||
if IsPtr:
|
||||
node.attributes.PtrCount = 1
|
||||
if dims:
|
||||
node.attributes.ArrayDims = list(dims)
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateClass(cls, name: str, TypeKind: type, members: dict | None = None, lineno: int = 0, file: str = '', IsCpythonObject: bool = False, IsPacked: bool = False) -> SymbolNode:
|
||||
"""创建类节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsCpythonObject = IsCpythonObject
|
||||
node.attributes.IsPacked = IsPacked
|
||||
if members:
|
||||
for MemberName, MemberInfo in members.items():
|
||||
if isinstance(MemberInfo, CTypeInfo):
|
||||
node.attributes.Members[MemberName] = MemberInfo
|
||||
elif isinstance(MemberInfo, dict):
|
||||
CTypeMember = CTypeInfo()
|
||||
type_str = MemberInfo.get('type', 'int')
|
||||
is_ptr = MemberInfo.get('IsPtr', False)
|
||||
if isinstance(type_str, str):
|
||||
try:
|
||||
resolved = CTypeInfo.FromTypeName(type_str)
|
||||
if resolved and resolved.BaseType:
|
||||
CTypeMember = resolved
|
||||
else:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
except Exception:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
else:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
if is_ptr and not CTypeMember.IsPtr:
|
||||
CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1)
|
||||
node.attributes.Members[MemberName] = CTypeMember
|
||||
if TypeKind == 'struct':
|
||||
node.attributes.IsStruct = True
|
||||
elif TypeKind == 'enum':
|
||||
node.attributes.IsEnum = True
|
||||
elif TypeKind == 'union':
|
||||
node.attributes.IsUnion = True
|
||||
elif TypeKind == 'typedef':
|
||||
node.attributes.IsTypedef = True
|
||||
elif TypeKind == 'exception':
|
||||
node.attributes.IsExceptionClass = True
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateTypedef(cls, name: str, OriginalType, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType='typedef', lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsTypedef = True
|
||||
if isinstance(OriginalType, CTypeInfo):
|
||||
node.attributes.OriginalType = OriginalType
|
||||
elif isinstance(OriginalType, str):
|
||||
node.attributes.OriginalType = CTypeInfo.FromTypeName(OriginalType) if OriginalType else None
|
||||
else:
|
||||
node.attributes.OriginalType = OriginalType
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建匿名类型节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
NodeType = t.CUnion if IsUnion else t.CStruct
|
||||
node = cls(name=name, NodeType=NodeType, lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsAnonymous = True
|
||||
if IsUnion:
|
||||
node.attributes.IsUnion = True
|
||||
else:
|
||||
node.attributes.IsStruct = True
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateModule(cls, name: str, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建模块节点(工厂函数)"""
|
||||
return cls(name=name, NodeType='module', lineno=lineno, file=file)
|
||||
from __future__ import annotations
|
||||
from typing import Any, Dict, Optional, TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
|
||||
from lib.includes import t
|
||||
|
||||
|
||||
class SymbolNode:
|
||||
"""符号表节点,类似 AST 节点的树形结构
|
||||
|
||||
attributes 存储 CTypeInfo 对象,不再使用 TypeInfo
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, NodeType: str, lineno: int = 0, file: str = '', parent: SymbolNode | None = None):
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
self.name: str = name
|
||||
self.type: str = NodeType
|
||||
self.lineno: int = lineno
|
||||
self.file: str = file
|
||||
self.parent: SymbolNode | None = parent
|
||||
self.children: Dict[str, SymbolNode] = {}
|
||||
self.attributes: CTypeInfo = CTypeInfo()
|
||||
self.attributes.Name = name
|
||||
self.attributes.Lineno = lineno
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""获取属性值"""
|
||||
if hasattr(self.attributes, key):
|
||||
return getattr(self.attributes, key)
|
||||
return self.attributes._extra.get(key, default)
|
||||
|
||||
def set(self, key: str, value: Any):
|
||||
"""设置属性值"""
|
||||
if hasattr(self.attributes, key):
|
||||
attr = getattr(type(self.attributes), key, None)
|
||||
if isinstance(attr, property) and attr.fset is None:
|
||||
return
|
||||
setattr(self.attributes, key, value)
|
||||
else:
|
||||
self.attributes._extra[key] = value
|
||||
|
||||
def HasChild(self, name: str) -> bool:
|
||||
"""检查是否有子节点"""
|
||||
return name in self.children
|
||||
|
||||
def GetChild(self, name: str) -> Optional[SymbolNode]:
|
||||
"""获取子节点"""
|
||||
return self.children.get(name)
|
||||
|
||||
def AddChild(self, node: SymbolNode):
|
||||
"""添加子节点"""
|
||||
node.parent = self
|
||||
self.children[node.name] = node
|
||||
|
||||
def RemoveChild(self, name: str) -> bool:
|
||||
"""删除子节点"""
|
||||
if name in self.children:
|
||||
del self.children[name]
|
||||
return True
|
||||
return False
|
||||
|
||||
def find(self, path: str, separator: str = '.') -> Optional[SymbolNode]:
|
||||
"""根据路径查找节点,如 'test.ClassA'"""
|
||||
parts = path.split(separator)
|
||||
current = self
|
||||
|
||||
for part in parts:
|
||||
if current.HasChild(part):
|
||||
current = current.GetChild(part)
|
||||
else:
|
||||
return None
|
||||
|
||||
return current
|
||||
|
||||
def ToDict(self) -> Dict[str, Any]:
|
||||
"""转换为字典格式"""
|
||||
result = {
|
||||
'type': self.type,
|
||||
'lineno': self.lineno,
|
||||
'file': self.file,
|
||||
**self.attributes.entry
|
||||
}
|
||||
|
||||
if self.children:
|
||||
result['children'] = {name: child.ToDict() for name, child in self.children.items()}
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def FromDict(cls, name: str, data: Dict[str, Any]) -> SymbolNode:
|
||||
"""从字典创建节点(兼容性)"""
|
||||
node = cls(name=name, NodeType=data.get('type', 'unknown'))
|
||||
node.lineno = data.get('lineno', 0)
|
||||
node.file = data.get('file', '')
|
||||
|
||||
for key, value in data.items():
|
||||
if key not in ('type', 'lineno', 'file', 'children'):
|
||||
node.set(key, value)
|
||||
|
||||
if 'children' in data:
|
||||
for ChildName, ChildData in data['children'].items():
|
||||
node.AddChild(cls.FromDict(ChildName, ChildData))
|
||||
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateMember(cls, name: str, TypeName: str | None = None, TypeInfo: 'CTypeInfo | None' = None, IsPtr: bool = False, dims: list[int] | None = None, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建成员节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType='member', lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
if TypeInfo is not None:
|
||||
node.attributes = TypeInfo
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
else:
|
||||
if TypeName is not None:
|
||||
node.attributes.BaseType = CTypeInfo.create_FromTypeName(TypeName)
|
||||
if IsPtr:
|
||||
node.attributes.PtrCount = 1
|
||||
if dims:
|
||||
node.attributes.ArrayDims = list(dims)
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateClass(cls, name: str, TypeKind: type, members: dict | None = None, lineno: int = 0, file: str = '', IsCpythonObject: bool = False, IsPacked: bool = False) -> SymbolNode:
|
||||
"""创建类节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsCpythonObject = IsCpythonObject
|
||||
node.attributes.IsPacked = IsPacked
|
||||
if members:
|
||||
for MemberName, MemberInfo in members.items():
|
||||
if isinstance(MemberInfo, CTypeInfo):
|
||||
node.attributes.Members[MemberName] = MemberInfo
|
||||
elif isinstance(MemberInfo, dict):
|
||||
CTypeMember = CTypeInfo()
|
||||
type_str = MemberInfo.get('type', 'int')
|
||||
IsPtr = MemberInfo.get('IsPtr', False)
|
||||
if isinstance(type_str, str):
|
||||
try:
|
||||
resolved = CTypeInfo.FromTypeName(type_str)
|
||||
if resolved and resolved.BaseType:
|
||||
CTypeMember = resolved
|
||||
else:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
except Exception:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
else:
|
||||
CTypeMember.BaseType = t.CInt()
|
||||
if IsPtr and not CTypeMember.IsPtr:
|
||||
CTypeMember.PtrCount = max(CTypeMember.PtrCount, 1)
|
||||
node.attributes.Members[MemberName] = CTypeMember
|
||||
if TypeKind == 'struct':
|
||||
node.attributes.is_struct = True
|
||||
elif TypeKind == 'enum':
|
||||
node.attributes.IsEnum = True
|
||||
elif TypeKind == 'union':
|
||||
node.attributes.IsUnion = True
|
||||
elif TypeKind == 'typedef':
|
||||
node.attributes.IsTypedef = True
|
||||
elif TypeKind == 'exception':
|
||||
node.attributes.IsExceptionClass = True
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateTypedef(cls, name: str, OriginalType, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
node = cls(name=name, NodeType='typedef', lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsTypedef = True
|
||||
if isinstance(OriginalType, CTypeInfo):
|
||||
node.attributes.OriginalType = OriginalType
|
||||
elif isinstance(OriginalType, str):
|
||||
node.attributes.OriginalType = CTypeInfo.FromTypeName(OriginalType) if OriginalType else None
|
||||
else:
|
||||
node.attributes.OriginalType = OriginalType
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建匿名类型节点(工厂函数)"""
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
NodeType = t.CUnion if IsUnion else t.CStruct
|
||||
node = cls(name=name, NodeType=NodeType, lineno=lineno, file=file)
|
||||
node.attributes = CTypeInfo()
|
||||
node.attributes.Name = name
|
||||
node.attributes.Lineno = lineno
|
||||
node.attributes.IsAnonymous = True
|
||||
if IsUnion:
|
||||
node.attributes.IsUnion = True
|
||||
else:
|
||||
node.attributes.is_struct = True
|
||||
return node
|
||||
|
||||
@classmethod
|
||||
def CreateModule(cls, name: str, lineno: int = 0, file: str = '') -> SymbolNode:
|
||||
"""创建模块节点(工厂函数)"""
|
||||
return cls(name=name, NodeType='module', lineno=lineno, file=file)
|
||||
|
||||
Reference in New Issue
Block a user