per request, provide implementation-side visualizations. and always show raw data. (#1128)

This commit is contained in:
Scott Jones 2022-03-24 10:06:41 -07:00 коммит произвёл GitHub
Родитель 27adc6b382
Коммит b69f40d6ec
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 45 добавлений и 43 удалений

Просмотреть файл

@ -14,6 +14,11 @@
<CustomVisualizer Condition="this != 0" VisualizerId="2ec1a02f-997c-4693-840e-88ffa1e21b56"/>
<DisplayString Condition="this == 0">null</DisplayString>
</Type>
<!-- Visualize C++/WinRT object implementations -->
<Type Name="winrt::impl::producer&lt;*&gt;">
<CustomVisualizer Condition="this != 0" VisualizerId="2ec1a02f-997c-4693-840e-88ffa1e21b56"/>
<DisplayString Condition="this == 0">null</DisplayString>
</Type>
<!--Visualize all raw IInspectable pointers-->
<Type Name="IInspectable">
<CustomVisualizer Condition="this != 0" VisualizerId="2ec1a02f-997c-4693-840e-88ffa1e21b56"/>

Просмотреть файл

@ -207,21 +207,26 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression(
IF_FAIL_RET(pTypeSymbol->get_name(&bstrTypeName));
// Visualize top-level C++/WinRT objects containing ABI pointers
bool isAbiObject;
ObjectType objectType;
if (wcscmp(bstrTypeName, L"winrt::Windows::Foundation::IInspectable") == 0)
{
isAbiObject = false;
objectType = ObjectType::Projection;
}
// Visualize nested object properties via raw ABI pointers
else if ((wcscmp(bstrTypeName, L"winrt::impl::IInspectable") == 0) ||
(wcscmp(bstrTypeName, L"winrt::impl::inspectable_abi") == 0))
{
isAbiObject = true;
objectType = ObjectType::Abi;
}
// Visualize C++/WinRT object implementations
else if (wcsncmp(bstrTypeName, L"winrt::impl::producer<", wcslen(L"winrt::impl::producer<")) == 0)
{
objectType = ObjectType::Abi;
}
// Visualize all raw IInspectable pointers
else if (wcscmp(bstrTypeName, L"IInspectable") == 0)
{
isAbiObject = true;
objectType = ObjectType::Abi;
}
else
{
@ -231,7 +236,7 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression(
return S_OK;
}
IF_FAIL_RET(object_visualizer::CreateEvaluationResult(pVisualizedExpression, isAbiObject, ppResultObject));
IF_FAIL_RET(object_visualizer::CreateEvaluationResult(pVisualizedExpression, objectType, ppResultObject));
return S_OK;
}

Просмотреть файл

@ -99,14 +99,14 @@ static HRESULT EvaluatePropertyExpression(
_In_ PropertyData const& prop,
_In_ DkmVisualizedExpression* pExpression,
_In_ DkmPointerValueHome* pObject,
bool isAbiObject,
ObjectType objectType,
_Out_ com_ptr<DkmEvaluationResult>& pEvaluationResult
)
{
wchar_t abiAddress[40];
auto process = pExpression->RuntimeInstance()->Process();
bool is64Bit = ((process->SystemInformation()->Flags() & DefaultPort::DkmSystemInformationFlags::Is64Bit) != 0);
swprintf_s(abiAddress, is64Bit ? L"%s0x%I64x" : L"%s0x%08x", isAbiObject ? L"(::IUnknown*)" : L"*(::IUnknown**)", pObject->Address());
swprintf_s(abiAddress, is64Bit ? L"%s0x%I64x" : L"%s0x%08x", objectType == ObjectType::Abi ? L"(::IUnknown*)" : L"*(::IUnknown**)", pObject->Address());
wchar_t wszEvalText[500];
std::wstring propCast;
PCWSTR propField;
@ -174,12 +174,12 @@ static HRESULT EvaluatePropertyString(
_In_ PropertyData const& prop,
_In_ DkmVisualizedExpression* pExpression,
_In_ DkmPointerValueHome* pObject,
bool isAbiObject,
ObjectType objectType,
_Out_ com_ptr<DkmString>& pValue
)
{
com_ptr<DkmEvaluationResult> pEvaluationResult;
IF_FAIL_RET(EvaluatePropertyExpression(prop, pExpression, pObject, isAbiObject, pEvaluationResult));
IF_FAIL_RET(EvaluatePropertyExpression(prop, pExpression, pObject, objectType, pEvaluationResult));
if (pEvaluationResult->TagValue() != DkmEvaluationResult::Tag::SuccessResult)
{
return E_FAIL;
@ -195,11 +195,11 @@ static HRESULT EvaluatePropertyString(
static std::string GetRuntimeClass(
_In_ DkmVisualizedExpression* pExpression,
_In_ DkmPointerValueHome* pObject,
bool isAbiObject
ObjectType objectType
)
{
com_ptr<DkmString> pValue;
EvaluatePropertyString({ IID_IInspectable, -2, PropertyCategory::String }, pExpression, pObject, isAbiObject, pValue);
EvaluatePropertyString({ IID_IInspectable, -2, PropertyCategory::String }, pExpression, pObject, objectType, pValue);
if (!pValue || pValue->Length() == 0)
{
return "";
@ -210,16 +210,11 @@ static std::string GetRuntimeClass(
static HRESULT ObjectToString(
_In_ DkmVisualizedExpression* pExpression,
_In_ DkmPointerValueHome* pObject,
bool isAbiObject,
_Out_ com_ptr<DkmString>& pValue,
bool* unavailable = nullptr
ObjectType objectType,
_Out_ com_ptr<DkmString>& pValue
)
{
if (unavailable)
{
*unavailable = false;
}
if (SUCCEEDED(EvaluatePropertyString({ IID_IStringable, 0, PropertyCategory::String }, pExpression, pObject, isAbiObject, pValue)))
if (SUCCEEDED(EvaluatePropertyString({ IID_IStringable, 0, PropertyCategory::String }, pExpression, pObject, objectType, pValue)))
{
if (pValue && pValue->Length() > 0)
{
@ -229,7 +224,7 @@ static HRESULT ObjectToString(
// WINRT_abi_val returned 0, which may be success or failure (due to VirtualQuery validation)
// Call back for the runtime class name to determine which it was
if (!GetRuntimeClass(pExpression, pObject, isAbiObject).empty())
if (!GetRuntimeClass(pExpression, pObject, objectType).empty())
{
return DkmString::Create(L"<Expand object to view properties>", pValue.put());
}
@ -237,17 +232,13 @@ static HRESULT ObjectToString(
// VirtualQuery validation failed (as determined by no runtime class name) or an
// exception escaped WINRT_abi_val (e.g, bad pointer, which we try to avoid via VirtualQuery)
if (unavailable)
{
*unavailable = true;
}
return DkmString::Create(L"<Object uninitialized or information unavailable>", pValue.put());
}
static HRESULT CreateChildVisualizedExpression(
_In_ PropertyData const& prop,
_In_ DkmVisualizedExpression* pParent,
bool isAbiObject,
ObjectType objectType,
_Deref_out_ DkmChildVisualizedExpression** ppResult
)
{
@ -256,7 +247,7 @@ static HRESULT CreateChildVisualizedExpression(
com_ptr<DkmEvaluationResult> pEvaluationResult;
auto valueHome = make_com_ptr(pParent->ValueHome());
com_ptr<DkmPointerValueHome> pParentPointer = valueHome.as<DkmPointerValueHome>();
IF_FAIL_RET(EvaluatePropertyExpression(prop, pParent, pParentPointer.get(), isAbiObject, pEvaluationResult));
IF_FAIL_RET(EvaluatePropertyExpression(prop, pParent, pParentPointer.get(), objectType, pEvaluationResult));
if (pEvaluationResult->TagValue() != DkmEvaluationResult::Tag::SuccessResult)
{
return E_FAIL;
@ -273,7 +264,7 @@ static HRESULT CreateChildVisualizedExpression(
{
isNonNullObject = true;
IF_FAIL_RET(DkmPointerValueHome::Create(childObjectAddress, pChildPointer.put()));
IF_FAIL_RET(ObjectToString(pParent, pChildPointer.get(), true, pValue));
IF_FAIL_RET(ObjectToString(pParent, pChildPointer.get(), ObjectType::Abi, pValue));
}
}
if(!isNonNullObject)
@ -335,7 +326,7 @@ static HRESULT CreateChildVisualizedExpression(
if (isNonNullObject)
{
com_ptr<object_visualizer> pObjectVisualizer = make_self<object_visualizer>(pChildVisualizedExpression.get(), true);
com_ptr<object_visualizer> pObjectVisualizer = make_self<object_visualizer>(pChildVisualizedExpression.get(), ObjectType::Abi);
IF_FAIL_RET(pChildVisualizedExpression->SetDataItem(DkmDataCreationDisposition::CreateNew, pObjectVisualizer.get()));
}
else
@ -492,7 +483,7 @@ void object_visualizer::GetPropertyData()
{
auto valueHome = make_com_ptr(m_pVisualizedExpression->ValueHome());
com_ptr<DkmPointerValueHome> pObject = valueHome.as<DkmPointerValueHome>();
auto rc = GetRuntimeClass(m_pVisualizedExpression.get(), pObject.get(), m_isAbiObject);
auto rc = GetRuntimeClass(m_pVisualizedExpression.get(), pObject.get(), m_objectType);
if (rc.empty())
{
return;
@ -539,9 +530,9 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm
}
}
HRESULT object_visualizer::CreateEvaluationResult(_In_ DkmVisualizedExpression* pVisualizedExpression, _In_ bool isAbiObject, _Deref_out_ DkmEvaluationResult** ppResultObject)
HRESULT object_visualizer::CreateEvaluationResult(_In_ DkmVisualizedExpression* pVisualizedExpression, _In_ ObjectType objectType, _Deref_out_ DkmEvaluationResult** ppResultObject)
{
com_ptr<object_visualizer> pObjectVisualizer = make_self<object_visualizer>(pVisualizedExpression, isAbiObject);
com_ptr<object_visualizer> pObjectVisualizer = make_self<object_visualizer>(pVisualizedExpression, objectType);
IF_FAIL_RET(pVisualizedExpression->SetDataItem(DkmDataCreationDisposition::CreateNew, pObjectVisualizer.get()));
@ -582,7 +573,7 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul
auto address = pPointerValueHome->Address();
com_ptr<DkmString> pValue;
DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly;
DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly | DkmEvaluationResultFlags::Expandable;;
if (requires_refresh(address, m_pVisualizedExpression->InspectionContext()->EvaluationFlags()))
{
IF_FAIL_RET(DkmString::Create(L"<Refresh to view properties>", pValue.put()));
@ -591,12 +582,7 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul
else
{
cache_refresh(address);
bool unavailable;
IF_FAIL_RET(ObjectToString(m_pVisualizedExpression.get(), pPointerValueHome.get(), m_isAbiObject, pValue, &unavailable));
if (!unavailable)
{
evalResultFlags |= DkmEvaluationResultFlags::Expandable;
}
IF_FAIL_RET(ObjectToString(m_pVisualizedExpression.get(), pPointerValueHome.get(), m_objectType, pValue));
}
com_ptr<DkmDataAddress> pAddress;
@ -689,7 +675,7 @@ HRESULT object_visualizer::GetItems(
{
auto& prop = m_propertyData[i + (size_t)StartIndex];
com_ptr<DkmChildVisualizedExpression> pPropertyVisualized;
if (FAILED(CreateChildVisualizedExpression(prop, pParent, m_isAbiObject, pPropertyVisualized.put())))
if(FAILED(CreateChildVisualizedExpression(prop, pParent, m_objectType, pPropertyVisualized.put())))
{
com_ptr<DkmString> pErrorMessage;
IF_FAIL_RET(DkmString::Create(L"<Property evaluation failed>", pErrorMessage.put()));

Просмотреть файл

@ -20,6 +20,12 @@ enum class PropertyCategory
Class,
};
enum class ObjectType
{
Abi,
Projection,
};
// Metatdata for resolving a runtime class property value
struct PropertyData
{
@ -36,17 +42,17 @@ struct PropertyData
struct __declspec(uuid("c7da92da-3bc9-4312-8a93-46f480663980"))
object_visualizer : winrt::implements<object_visualizer, ::IUnknown>
{
object_visualizer(Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, bool isAbiObject)
object_visualizer(Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, ObjectType objectType)
{
m_pVisualizedExpression = make_com_ptr(pVisualizedExpression);
m_isAbiObject = isAbiObject;
m_objectType = objectType;
}
~object_visualizer()
{
}
static HRESULT CreateEvaluationResult(_In_ Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, _In_ bool isAbiObject, _Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject);
static HRESULT CreateEvaluationResult(_In_ Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, _In_ ObjectType objectType, _Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject);
HRESULT CreateEvaluationResult(_Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject);
@ -69,7 +75,7 @@ private:
void GetPropertyData();
void GetTypeProperties(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& type_name);
winrt::com_ptr<Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression> m_pVisualizedExpression;
bool m_isAbiObject;
ObjectType m_objectType;
std::vector<PropertyData> m_propertyData;
bool m_isStringable{ false };
};