2022-03-11 16:55:02 +00:00
|
|
|
# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
|
|
|
|
|
|
# HACK: LLDB's python API doesn't afford anything helpful for getting at variadic template parameters.
|
|
|
|
# We're forced to resort to parsing names as strings.
|
|
|
|
def templateParams(s):
|
|
|
|
depth = 0
|
|
|
|
start = s.find('<') + 1
|
|
|
|
result = []
|
|
|
|
for i, c in enumerate(s[start:], start):
|
|
|
|
if c == '<':
|
|
|
|
depth += 1
|
|
|
|
elif c == '>':
|
|
|
|
if depth == 0:
|
|
|
|
result.append(s[start: i].strip())
|
|
|
|
break
|
|
|
|
depth -= 1
|
|
|
|
elif c == ',' and depth == 0:
|
|
|
|
result.append(s[start: i].strip())
|
|
|
|
start = i + 1
|
|
|
|
return result
|
|
|
|
|
|
|
|
def getType(target, typeName):
|
|
|
|
stars = 0
|
|
|
|
|
|
|
|
typeName = typeName.strip()
|
|
|
|
while typeName.endswith('*'):
|
|
|
|
stars += 1
|
|
|
|
typeName = typeName[:-1]
|
|
|
|
|
|
|
|
if typeName.startswith('const '):
|
|
|
|
typeName = typeName[6:]
|
|
|
|
|
|
|
|
ty = target.FindFirstType(typeName.strip())
|
|
|
|
for _ in range(stars):
|
|
|
|
ty = ty.GetPointerType()
|
|
|
|
|
|
|
|
return ty
|
|
|
|
|
|
|
|
def luau_variant_summary(valobj, internal_dict, options):
|
2022-04-07 22:29:01 +01:00
|
|
|
type_id = valobj.GetChildMemberWithName("typeId").GetValueAsUnsigned()
|
2022-03-11 16:55:02 +00:00
|
|
|
storage = valobj.GetChildMemberWithName("storage")
|
|
|
|
params = templateParams(valobj.GetType().GetCanonicalType().GetName())
|
|
|
|
stored_type = params[type_id]
|
|
|
|
value = storage.Cast(stored_type.GetPointerType()).Dereference()
|
|
|
|
return stored_type.GetDisplayTypeName() + " [" + value.GetValue() + "]"
|
|
|
|
|
|
|
|
class LuauVariantSyntheticChildrenProvider:
|
|
|
|
node_names = ["type", "value"]
|
|
|
|
|
|
|
|
def __init__(self, valobj, internal_dict):
|
|
|
|
self.valobj = valobj
|
|
|
|
self.type_index = None
|
|
|
|
self.current_type = None
|
|
|
|
self.type_params = []
|
|
|
|
self.stored_value = None
|
|
|
|
|
|
|
|
def num_children(self):
|
|
|
|
return len(self.node_names)
|
|
|
|
|
|
|
|
def has_children(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def get_child_index(self, name):
|
|
|
|
try:
|
|
|
|
return self.node_names.index(name)
|
|
|
|
except ValueError:
|
|
|
|
return -1
|
|
|
|
|
|
|
|
def get_child_at_index(self, index):
|
|
|
|
try:
|
|
|
|
node = self.node_names[index]
|
|
|
|
except IndexError:
|
|
|
|
return None
|
|
|
|
|
|
|
|
if node == "type":
|
|
|
|
if self.current_type:
|
|
|
|
return self.valobj.CreateValueFromExpression(node, f"(const char*)\"{self.current_type.GetDisplayTypeName()}\"")
|
|
|
|
else:
|
|
|
|
return self.valobj.CreateValueFromExpression(node, "(const char*)\"<unknown type>\"")
|
|
|
|
elif node == "value":
|
|
|
|
if self.stored_value is not None:
|
|
|
|
if self.current_type is not None:
|
|
|
|
return self.valobj.CreateValueFromData(node, self.stored_value.GetData(), self.current_type)
|
|
|
|
else:
|
|
|
|
return self.valobj.CreateValueExpression(node, "(const char*)\"<unknown type>\"")
|
|
|
|
else:
|
|
|
|
return self.valobj.CreateValueFromExpression(node, "(const char*)\"<no stored value>\"")
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def update(self):
|
2022-04-07 22:29:01 +01:00
|
|
|
self.type_index = self.valobj.GetChildMemberWithName("typeId").GetValueAsSigned()
|
2022-03-11 16:55:02 +00:00
|
|
|
self.type_params = templateParams(self.valobj.GetType().GetCanonicalType().GetName())
|
|
|
|
|
|
|
|
if len(self.type_params) > self.type_index:
|
|
|
|
self.current_type = getType(self.valobj.GetTarget(), self.type_params[self.type_index])
|
|
|
|
|
|
|
|
if self.current_type:
|
|
|
|
storage = self.valobj.GetChildMemberWithName("storage")
|
|
|
|
self.stored_value = storage.Cast(self.current_type.GetPointerType()).Dereference()
|
|
|
|
else:
|
|
|
|
self.stored_value = None
|
|
|
|
else:
|
|
|
|
self.current_type = None
|
|
|
|
self.stored_value = None
|
|
|
|
|
|
|
|
return False
|