Skip to content

Commit 50e9869

Browse files
committed
Synthesizing GenericTypeInstSig and generating guid
1 parent b63aef1 commit 50e9869

File tree

3 files changed

+97
-47
lines changed

3 files changed

+97
-47
lines changed

natvis/cppwinrt_visualizer.cpp

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,33 +150,81 @@ TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeNamespac
150150
return type;
151151
}
152152

153-
TypeSig FindType(DkmProcess* process, std::string_view const& typeName)
153+
std::vector<std::string> ParseTypeName(std::string_view name)
154154
{
155-
auto paramIndex = typeName.find('<');
156-
if (paramIndex == std::string_view::npos)
155+
DWORD count;
156+
HSTRING* parts;
157+
auto wide_name = winrt::to_hstring(name);
158+
winrt::check_hresult(::RoParseTypeName(static_cast<HSTRING>(get_abi(wide_name)), &count, &parts));
159+
160+
winrt::com_array<winrt::hstring> wide_parts{ parts, count, winrt::take_ownership_from_abi };
161+
std::vector<std::string> result;
162+
for (auto&& part : wide_parts)
157163
{
158-
return TypeSig{ FindSimpleType(process, typeName).coded_index<TypeDefOrRef>() };
164+
result.push_back(winrt::to_string(part));
159165
}
160-
else
166+
return result;
167+
}
168+
169+
template <std::input_iterator iter, std::sentinel_for<iter> sent>
170+
TypeSig ResolveGenericTypePart(DkmProcess* process, iter& it, sent const& end)
171+
{
172+
constexpr std::pair<std::string_view, ElementType> elementNames[] = {
173+
{"Boolean", ElementType::Boolean},
174+
{"Int8", ElementType::I1},
175+
{"Int16", ElementType::I2},
176+
{"Int32", ElementType::I4},
177+
{"Int64", ElementType::I8},
178+
{"UInt8", ElementType::U1},
179+
{"UInt16", ElementType::U2},
180+
{"UInt32", ElementType::U4},
181+
{"UInt64", ElementType::U8},
182+
{"Single", ElementType::R4},
183+
{"Double", ElementType::R8},
184+
{"String", ElementType::String},
185+
{"Object", ElementType::Object}
186+
};
187+
std::string_view partName = *it;
188+
auto basic_type_pos = std::find_if(std::begin(elementNames), std::end(elementNames), [&partName](auto&& elem) { return elem.first == partName; });
189+
if (basic_type_pos != std::end(elementNames))
190+
{
191+
return TypeSig{ basic_type_pos->second };
192+
}
193+
194+
TypeDef type = FindSimpleType(process, partName);
195+
auto tickPos = partName.rfind('`');
196+
if (tickPos == std::string_view::basic_string_view::npos)
161197
{
162-
XLANG_ASSERT(typeName.back() == '>');
163-
return TypeSig{ FindSimpleType(process, typeName.substr(0, paramIndex)).coded_index<TypeDefOrRef>() };
164-
// TODO: Assemble the GenericTypeInstSig
198+
return TypeSig{ type.coded_index<TypeDefOrRef>() };
165199
}
200+
201+
int paramCount = 0;
202+
std::from_chars(partName.data() + tickPos + 1, partName.data() + partName.size(), paramCount);
203+
std::vector<TypeSig> genericArgs;
204+
for (int i = 0; i < paramCount; ++i)
205+
{
206+
genericArgs.push_back(ResolveGenericTypePart(process, ++it, end));
207+
}
208+
return TypeSig{ GenericTypeInstSig{ type.coded_index<TypeDefOrRef>(), std::move(genericArgs) } };
166209
}
167210

168-
TypeSig FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName)
211+
TypeSig ResolveGenericType(DkmProcess* process, std::string_view genericName)
212+
{
213+
auto parts = ParseTypeName(genericName);
214+
auto begin = parts.begin();
215+
return ResolveGenericTypePart(process, begin, parts.end());
216+
}
217+
218+
TypeSig FindType(DkmProcess* process, std::string_view const& typeName)
169219
{
170220
auto paramIndex = typeName.find('<');
171221
if (paramIndex == std::string_view::npos)
172222
{
173-
return TypeSig{ FindSimpleType(process, typeNamespace, typeName).coded_index<TypeDefOrRef>() };
223+
return TypeSig{ FindSimpleType(process, typeName).coded_index<TypeDefOrRef>() };
174224
}
175225
else
176226
{
177-
XLANG_ASSERT(typeName.back() == '>');
178-
return TypeSig{ FindSimpleType(process, typeNamespace, typeName.substr(0, paramIndex)).coded_index<TypeDefOrRef>() };
179-
// TODO: Assemble the GenericTypeInstSig
227+
return ResolveGenericType(process, typeName);
180228
}
181229
}
182230

natvis/pch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <variant>
4444
#include <cmd_reader.h>
4545
#include <winmd_reader.h>
46+
#include <rometadataresolution.h>
4647

4748
#ifndef IF_FAIL_RET
4849
#define IF_FAIL_RET(expr) { HRESULT _hr = (expr); if(FAILED(_hr)) { return(_hr); } }
@@ -94,7 +95,6 @@ inline bool starts_with(std::string_view const& value, std::string_view const& m
9495
winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName);
9596
winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName);
9697
winmd::reader::TypeSig FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName);
97-
winmd::reader::TypeSig FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName);
9898

9999
inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index<winmd::reader::TypeDefOrRef> index) noexcept
100100
{

natvis/type_resolver.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ struct signature_generator
9898
}
9999
}
100100

101+
static std::string get_signature(GenericTypeInstSig const& type)
102+
{
103+
std::string sig = "pinterface(" + get_guid_signature(type.GenericType());
104+
for (auto&& arg : type.GenericArgs())
105+
{
106+
sig += ";";
107+
sig += get_signature(arg);
108+
}
109+
sig += ")";
110+
return sig;
111+
}
112+
101113
private:
102114
static std::string get_class_signature(TypeDef const& type)
103115
{
@@ -152,20 +164,8 @@ struct signature_generator
152164
case TypeDefOrRef::TypeRef:
153165
return get_guid_signature(find_required(type.TypeRef()));
154166
default: //case TypeDefOrRef::TypeSpec:
155-
return get_guid_signature(type.TypeSpec().Signature().GenericTypeInst().GenericType());
156-
}
157-
}
158-
159-
static std::string get_signature(GenericTypeInstSig const& type)
160-
{
161-
std::string sig = "pinterface(" + get_guid_signature(type.GenericType());
162-
for (auto&& arg : type.GenericArgs())
163-
{
164-
sig += ";";
165-
sig += get_signature(arg);
167+
return get_signature(type.TypeSpec().Signature().GenericTypeInst());
166168
}
167-
sig += ")";
168-
return sig;
169169
}
170170

171171
static std::string get_signature(TypeSig::value_type const& type)
@@ -266,7 +266,7 @@ static auto calculate_sha1(std::vector<uint8_t> const& input)
266266
return get_result(intermediate_hash);
267267
}
268268

269-
static guid generate_guid(coded_index<TypeDefOrRef> const& type)
269+
static guid generate_guid(GenericTypeInstSig const& type)
270270
{
271271
constexpr guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } };
272272
constexpr auto namespace_bytes = winrt::impl::to_array(namespace_guid);
@@ -284,30 +284,32 @@ std::pair<TypeDef, std::wstring> ResolveTypeInterface(DkmProcess* process, winmd
284284
if (auto ptrIndex = std::get_if<coded_index<TypeDefOrRef>>(&typeSig.Type()))
285285
{
286286
index = *ptrIndex;
287+
// TODO: Cache on the whole TypeSig, not just the generic index
288+
if (auto found = _cache.find(index); found != _cache.end())
289+
{
290+
return found->second;
291+
}
292+
293+
TypeDef type = ResolveType(process, index);
294+
if (!type)
295+
{
296+
return {};
297+
}
298+
299+
auto guid = index.type() == TypeDefOrRef::TypeSpec ?
300+
format_guid(generate_guid(index.TypeSpec().Signature().GenericTypeInst())) : format_guid(get_guid(type));
301+
302+
auto type_guid = std::pair{ type, guid };
303+
_cache[index] = type_guid;
304+
return type_guid;
287305
}
288306
else if (auto* ptrGeneric = std::get_if<GenericTypeInstSig>(&typeSig.Type()))
289307
{
290308
index = ptrGeneric->GenericType();
309+
auto guid = format_guid(generate_guid(*ptrGeneric));
310+
return { index.TypeDef(), guid };
291311
}
292-
293-
// TODO: Cache on the whole TypeSig, not just the generic index
294-
if (auto found = _cache.find(index); found != _cache.end())
295-
{
296-
return found->second;
297-
}
298-
299-
TypeDef type = ResolveType(process, index);
300-
if (!type)
301-
{
302-
return {};
303-
}
304-
305-
auto guid = index.type() == TypeDefOrRef::TypeSpec ?
306-
format_guid(generate_guid(index)) : format_guid(get_guid(type));
307-
308-
auto type_guid = std::pair{ type, guid };
309-
_cache[index] = type_guid;
310-
return type_guid;
312+
return {};
311313
};
312314

313315
void ClearTypeResolver()

0 commit comments

Comments
 (0)