@@ -7,12 +7,8 @@ using namespace Microsoft::VisualStudio::Debugger;
77using namespace Microsoft ::VisualStudio::Debugger::Evaluation;
88using namespace std ::literals;
99using namespace winrt ;
10- using namespace winmd ::impl;
1110using namespace winmd ::reader;
1211
13- template <typename ...T> struct overloaded : T... { using T::operator ()...; };
14- template <typename ...T> overloaded (T...)->overloaded<T...>;
15-
1612#define IID_IInspectable L" AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90"
1713#define IID_IStringable L" 96369F54-8EB6-48F0-ABCE-C1B211E627C3"
1814
@@ -351,56 +347,11 @@ struct property_type
351347};
352348
353349void GetInterfaceData (
354- DkmProcess* process,
355350 coded_index<TypeDefOrRef> index,
356351 _Inout_ std::vector<PropertyData>& propertyData,
357352 _Out_ bool & isStringable
358353){
359- auto resolve_type_index = [](coded_index<TypeDefOrRef> index) -> TypeDef
360- {
361- switch (index.type ())
362- {
363- case TypeDefOrRef::TypeDef:
364- {
365- return index.TypeDef ();
366- }
367- case TypeDefOrRef::TypeRef:
368- {
369- return find_required (index.TypeRef ());
370- }
371- case TypeDefOrRef::TypeSpec:
372- {
373- auto type_signature = index.TypeSpec ().Signature ();
374- auto signature = type_signature.GenericTypeInst ();
375- return find_required (signature.GenericType ().TypeRef ());
376- }
377- }
378- return {};
379- };
380-
381- auto type = resolve_type_index (index);
382- auto attribute = get_attribute (type, " Windows.Foundation.Metadata" , " GuidAttribute" );
383- if (!attribute)
384- {
385- throw_invalid (" 'Windows.Foundation.Metadata.GuidAttribute' attribute for type '" , type.TypeNamespace (), " ." , type.TypeName (), " ' not found" );
386- }
387- auto args = attribute.Value ().FixedArgs ();
388- std::string guid (68 , ' ?' );
389- int count = sprintf_s (guid.data (), guid.size () + 1 ,
390- " %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
391- , std::get<uint32_t >(std::get<ElemSig>(args[0 ].value ).value )
392- , std::get<uint16_t >(std::get<ElemSig>(args[1 ].value ).value )
393- , std::get<uint16_t >(std::get<ElemSig>(args[2 ].value ).value )
394- , std::get<uint8_t >(std::get<ElemSig>(args[3 ].value ).value )
395- , std::get<uint8_t >(std::get<ElemSig>(args[4 ].value ).value )
396- , std::get<uint8_t >(std::get<ElemSig>(args[5 ].value ).value )
397- , std::get<uint8_t >(std::get<ElemSig>(args[6 ].value ).value )
398- , std::get<uint8_t >(std::get<ElemSig>(args[7 ].value ).value )
399- , std::get<uint8_t >(std::get<ElemSig>(args[8 ].value ).value )
400- , std::get<uint8_t >(std::get<ElemSig>(args[9 ].value ).value )
401- , std::get<uint8_t >(std::get<ElemSig>(args[10 ].value ).value ));
402- guid.resize (count);
403- std::wstring propIid (guid.cbegin (), guid.cend ());
354+ auto [type, propIid] = ResolveTypeInterface (index);
404355
405356 if (propIid == IID_IStringable)
406357 {
@@ -424,89 +375,85 @@ void GetInterfaceData(
424375 std::wstring propDisplayType;
425376
426377 auto retType = method.Signature ().ReturnType ();
427- std::visit (overloaded
378+ std::visit (overloaded{
379+ [&](ElementType type)
428380 {
429- [&]( ElementType type)
381+ if ((type < ElementType::Boolean) || ( type > ElementType::String) )
430382 {
431- if ((type < ElementType::Boolean) || (type > ElementType::String))
432- {
433- return ;
434- }
435- propCategory = (PropertyCategory)(static_cast <std::underlying_type<ElementType>::type>(type) -
436- static_cast <std::underlying_type<ElementType>::type>(ElementType::Boolean));
437- },
438- [&](coded_index<TypeDefOrRef> const & index)
383+ return ;
384+ }
385+ propCategory = (PropertyCategory)(static_cast <std::underlying_type<ElementType>::type>(type) -
386+ static_cast <std::underlying_type<ElementType>::type>(ElementType::Boolean));
387+ },
388+ [&](coded_index<TypeDefOrRef> const & index)
389+ {
390+ auto type = ResolveType (index);
391+ auto typeName = type.TypeName ();
392+ if (typeName == " GUID" sv)
439393 {
440- auto type = resolve_type_index (index);
441- auto typeName = type.TypeName ();
442- if (typeName == " GUID" sv)
394+ propCategory = PropertyCategory::Guid;
395+ }
396+ else
397+ {
398+ auto ns = std::string (type.TypeNamespace ());
399+ auto name = std::string (type.TypeName ());
400+
401+ // Map numeric type names
402+ if (ns == " Windows.Foundation.Numerics" )
443403 {
444- propCategory = PropertyCategory::Guid;
404+ if (name == " Matrix3x2" ) { name = " float3x2" ; }
405+ else if (name == " Matrix4x4" ) { name = " float4x4" ; }
406+ else if (name == " Plane" ) { name = " plane" ; }
407+ else if (name == " Quaternion" ) { name = " quaternion" ; }
408+ else if (name == " Vector2" ) { name = " float2" ; }
409+ else if (name == " Vector3" ) { name = " float3" ; }
410+ else if (name == " Vector4" ) { name = " float4" ; }
445411 }
446- else
447- {
448- auto ns = std::string (type.TypeNamespace ());
449- auto name = std::string (type.TypeName ());
450-
451- // Map numeric type names
452- if (ns == " Windows.Foundation.Numerics" )
453- {
454- if (name == " Matrix3x2" ) { name = " float3x2" ; }
455- else if (name == " Matrix4x4" ) { name = " float4x4" ; }
456- else if (name == " Plane" ) { name = " plane" ; }
457- else if (name == " Quaternion" ) { name = " quaternion" ; }
458- else if (name == " Vector2" ) { name = " float2" ; }
459- else if (name == " Vector3" ) { name = " float3" ; }
460- else if (name == " Vector4" ) { name = " float4" ; }
461- }
462412
463- // Types come back from winmd files with '.', need to be '::'
464- // Ex. Windows.Foundation.Uri needs to be Windows::Foundation::Uri
465- auto fullTypeName = ns + " ::" + name;
466- wchar_t cppTypename[500 ];
467- size_t i, j;
468- for (i = 0 , j = 0 ; i < (fullTypeName.length () + 1 ); i++, j++)
469- {
470- if (fullTypeName[i] == L' .' )
471- {
472- cppTypename[j++] = L' :' ;
473- cppTypename[j] = L' :' ;
474- }
475- else
476- {
477- cppTypename[j] = fullTypeName[i];
478- }
479- }
480-
481- propDisplayType = std::wstring (L" winrt::" ) + cppTypename;
482- if (get_category (type) == category::class_type)
413+ // Types come back from winmd files with '.', need to be '::'
414+ // Ex. Windows.Foundation.Uri needs to be Windows::Foundation::Uri
415+ auto fullTypeName = ns + " ::" + name;
416+ wchar_t cppTypename[500 ];
417+ size_t i, j;
418+ for (i = 0 , j = 0 ; i < (fullTypeName.length () + 1 ); i++, j++)
419+ {
420+ if (fullTypeName[i] == L' .' )
483421 {
484- propCategory = PropertyCategory::Class ;
485- propAbiType = L" winrt::impl::inspectable_abi* " ;
422+ cppTypename[j++] = L ' : ' ;
423+ cppTypename[j] = L' : ' ;
486424 }
487425 else
488426 {
489- propCategory = PropertyCategory::Value;
490- propAbiType = propDisplayType;
427+ cppTypename[j] = fullTypeName[i];
491428 }
492429 }
493- },
494- [&](GenericTypeIndex /* var*/ )
495- {
496- // TODO: generic properties
497- NatvisDiagnostic (process, L" Generics are not yet supported" , NatvisDiagnosticLevel::Verbose);
498- },
499- [&](GenericMethodTypeIndex /* var*/ )
500- {
501- throw_invalid (" Generic methods not supported." );
502- },
503- [&](GenericTypeInstSig const & /* type*/ )
504- {
505- // TODO: generic properties
506- NatvisDiagnostic (process, L" Generics are not yet supported" , NatvisDiagnosticLevel::Verbose);
430+
431+ propDisplayType = std::wstring (L" winrt::" ) + cppTypename;
432+ if (get_category (type) == category::class_type)
433+ {
434+ propCategory = PropertyCategory::Class;
435+ propAbiType = L" winrt::impl::inspectable_abi*" ;
436+ }
437+ else
438+ {
439+ propCategory = PropertyCategory::Value;
440+ propAbiType = propDisplayType;
441+ }
507442 }
508443 },
509- retType.Type ().Type ());
444+ [&](GenericTypeIndex /* var*/ )
445+ {
446+ throw_invalid (" Generics are not yet supported" );
447+ },
448+ [&](GenericMethodTypeIndex /* var*/ )
449+ {
450+ throw_invalid (" Generic methods not supported." );
451+ },
452+ [&](GenericTypeInstSig const & /* type*/ )
453+ {
454+ throw_invalid (" Generics are not yet supported" );
455+ }
456+ }, retType.Type ().Type ());
510457
511458 auto propName = method.Name ().substr (4 );
512459 std::wstring propDisplayName (propName.cbegin (), propName.cend ());
@@ -530,6 +477,7 @@ void object_visualizer::GetPropertyData()
530477
531478void object_visualizer::GetTypeProperties (Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const & type_name)
532479{
480+ // TODO: add support for direct generic interface implementations (e.g., key_value_pair)
533481 auto type = FindType (process, type_name);
534482 if (!type)
535483 {
@@ -550,17 +498,17 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm
550498 auto impls = type.InterfaceImpl ();
551499 for (auto && impl : impls)
552500 {
553- GetInterfaceData (process, impl.Interface (), m_propertyData, m_isStringable);
501+ GetInterfaceData (impl.Interface (), m_propertyData, m_isStringable);
554502 }
555503 }
556504 else if (get_category (type) == category::interface_type)
557505 {
558506 auto impls = type.InterfaceImpl ();
559507 for (auto && impl : impls)
560508 {
561- GetInterfaceData (process, impl.Interface (), m_propertyData, m_isStringable);
509+ GetInterfaceData (impl.Interface (), m_propertyData, m_isStringable);
562510 }
563- GetInterfaceData (process, type.coded_index <TypeDefOrRef>(), m_propertyData, m_isStringable);
511+ GetInterfaceData (type.coded_index <TypeDefOrRef>(), m_propertyData, m_isStringable);
564512 }
565513}
566514
@@ -630,6 +578,14 @@ HRESULT object_visualizer::GetChildren(
630578 {
631579 GetPropertyData ();
632580 }
581+ catch (std::invalid_argument const & e)
582+ {
583+ std::string_view message (e.what ());
584+ NatvisDiagnostic (m_pVisualizedExpression.get (),
585+ std::wstring (L" Exception in object_visualizer::GetPropertyData: " ) +
586+ std::wstring (message.begin (), message.end ()),
587+ NatvisDiagnosticLevel::Error, to_hresult ());
588+ }
633589 catch (...)
634590 {
635591 NatvisDiagnostic (m_pVisualizedExpression.get (),
0 commit comments