Skip to content

Commit 33dc362

Browse files
committed
Use temporary local impl of winmd lib
1 parent f2a7ffb commit 33dc362

File tree

21 files changed

+5820
-5
lines changed

21 files changed

+5820
-5
lines changed

natvis/cppwinrtvisualizer.vcxproj

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3-
<Import Project="packages\Microsoft.Windows.WinMD.1.0.210629.2\build\native\Microsoft.Windows.WinMD.props" Condition="Exists('packages\Microsoft.Windows.WinMD.1.0.210629.2\build\native\Microsoft.Windows.WinMD.props')" />
43
<ItemGroup Label="ProjectConfigurations">
54
<ProjectConfiguration Include="Debug|ARM64">
65
<Configuration>Debug</Configuration>
@@ -131,7 +130,7 @@
131130
<Optimization>Disabled</Optimization>
132131
<SDLCheck>false</SDLCheck>
133132
<PreprocessorDefinitions>VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
134-
<AdditionalIncludeDirectories>$(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
133+
<AdditionalIncludeDirectories>.\winmd;$(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
135134
<LanguageStandard>stdcpp20</LanguageStandard>
136135
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
137136
</ClCompile>
@@ -211,7 +210,7 @@
211210
<IntrinsicFunctions>true</IntrinsicFunctions>
212211
<SDLCheck>false</SDLCheck>
213212
<PreprocessorDefinitions>VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
214-
<AdditionalIncludeDirectories>$(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
213+
<AdditionalIncludeDirectories>.\winmd;$(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
215214
<LanguageStandard>stdcpp20</LanguageStandard>
216215
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
217216
<ControlFlowGuard>Guard</ControlFlowGuard>
@@ -321,6 +320,5 @@
321320
</PropertyGroup>
322321
<Error Condition="!Exists('packages\Microsoft.VSSDK.Debugger.VSDConfigTool.16.0.2012201-preview\build\Microsoft.VSSDK.Debugger.VSDConfigTool.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.VSSDK.Debugger.VSDConfigTool.16.0.2012201-preview\build\Microsoft.VSSDK.Debugger.VSDConfigTool.targets'))" />
323322
<Error Condition="!Exists('packages\Microsoft.VSSDK.Debugger.VSDebugEng.16.0.2012201-preview\Microsoft.VSSDK.Debugger.VSDebugEng.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.VSSDK.Debugger.VSDebugEng.16.0.2012201-preview\Microsoft.VSSDK.Debugger.VSDebugEng.targets'))" />
324-
<Error Condition="!Exists('packages\Microsoft.Windows.WinMD.1.0.210629.2\build\native\Microsoft.Windows.WinMD.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.WinMD.1.0.210629.2\build\native\Microsoft.Windows.WinMD.props'))" />
325323
</Target>
326324
</Project>

natvis/packages.config

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22
<packages>
33
<package id="Microsoft.VSSDK.Debugger.VSDConfigTool" version="16.0.2012201-preview" developmentDependency="true" />
44
<package id="Microsoft.VSSDK.Debugger.VSDebugEng" version="16.0.2012201-preview" developmentDependency="true" />
5-
<package id="Microsoft.Windows.WinMD" version="1.0.210629.2" targetFramework="native" />
65
</packages>

natvis/winmd/impl/base.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#if defined(_WIN32)
4+
#include <windows.h>
5+
#include <shlwapi.h>
6+
#else
7+
#include <sys/stat.h>
8+
#include <fcntl.h>
9+
#include <sys/mman.h>
10+
#include <unistd.h>
11+
#endif
12+
13+
#include <stdexcept>
14+
#include <assert.h>
15+
#include <array>
16+
#include <bitset>
17+
#include <fstream>
18+
#include <future>
19+
#include <list>
20+
#include <map>
21+
#include <optional>
22+
#include <regex>
23+
#include <string>
24+
#include <string_view>
25+
#include <variant>
26+
#include <vector>
27+
#include <set>
28+
#include <filesystem>
29+
30+
#if defined(_DEBUG)
31+
#define XLANG_DEBUG
32+
#define XLANG_ASSERT assert
33+
#else
34+
#define XLANG_ASSERT(expression) ((void)0)
35+
#endif
36+
37+
namespace winmd
38+
{
39+
using namespace std::literals;
40+
41+
namespace impl
42+
{
43+
[[noreturn]] inline void throw_invalid(std::string const& message)
44+
{
45+
throw std::invalid_argument(message);
46+
}
47+
48+
template <typename...T>
49+
[[noreturn]] inline void throw_invalid(std::string message, T const&... args)
50+
{
51+
(message.append(args), ...);
52+
throw std::invalid_argument(message);
53+
}
54+
55+
template <typename T>
56+
auto c_str(std::basic_string_view<T> const& view) noexcept
57+
{
58+
if (*(view.data() + view.size()))
59+
{
60+
std::terminate();
61+
}
62+
63+
return view.data();
64+
}
65+
66+
inline bool starts_with(std::string_view const& value, std::string_view const& match) noexcept
67+
{
68+
return 0 == value.compare(0, match.size(), match);
69+
}
70+
}
71+
}
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
2+
namespace winmd::reader
3+
{
4+
struct cache
5+
{
6+
cache() = default;
7+
cache(cache const&) = delete;
8+
cache& operator=(cache const&) = delete;
9+
10+
template<typename C, typename T = typename C::value_type, typename TypeFilter>
11+
explicit cache(C const& files, TypeFilter filter)
12+
{
13+
for (auto&& file : files)
14+
{
15+
auto& db = m_databases.emplace_back(file, this);
16+
17+
for (auto&& type : db.TypeDef)
18+
{
19+
if (type.Flags().value == 0 || is_nested(type) || !filter(type))
20+
{
21+
continue;
22+
}
23+
24+
auto& ns = m_namespaces[type.TypeNamespace()];
25+
ns.types.try_emplace(type.TypeName(), type);
26+
}
27+
28+
for (auto&& row : db.NestedClass)
29+
{
30+
m_nested_types[row.EnclosingType()].push_back(row.NestedType());
31+
}
32+
}
33+
34+
for (auto&&[namespace_name, members] : m_namespaces)
35+
{
36+
for (auto&&[name, type] : members.types)
37+
{
38+
add_type_to_members(type, members);
39+
}
40+
}
41+
}
42+
43+
template<typename C, typename T = typename C::value_type>
44+
explicit cache(C const& files) : cache{ files, default_type_filter{} }
45+
{
46+
}
47+
48+
template <typename TypeFilter>
49+
explicit cache(std::string const& file, TypeFilter filter) : cache{ std::vector<std::string>{ file }, filter }
50+
{
51+
}
52+
53+
explicit cache(std::string const& file) : cache{ std::vector<std::string>{ file }, default_type_filter{} }
54+
{
55+
}
56+
57+
struct default_type_filter
58+
{
59+
bool operator()(TypeDef const&) const noexcept
60+
{
61+
return true;
62+
}
63+
};
64+
65+
TypeDef find(std::string_view const& type_namespace, std::string_view const& type_name) const noexcept
66+
{
67+
auto ns = m_namespaces.find(type_namespace);
68+
69+
if (ns == m_namespaces.end())
70+
{
71+
return {};
72+
}
73+
74+
auto type = ns->second.types.find(type_name);
75+
76+
if (type == ns->second.types.end())
77+
{
78+
return {};
79+
}
80+
81+
return type->second;
82+
}
83+
84+
TypeDef find(std::string_view const& type_string) const
85+
{
86+
auto pos = type_string.rfind('.');
87+
88+
if (pos == std::string_view::npos)
89+
{
90+
impl::throw_invalid("Type '", type_string, "' is missing a namespace qualifier");
91+
}
92+
93+
return find(type_string.substr(0, pos), type_string.substr(pos + 1, type_string.size()));
94+
}
95+
96+
TypeDef find_required(std::string_view const& type_namespace, std::string_view const& type_name) const
97+
{
98+
auto definition = find(type_namespace, type_name);
99+
100+
if (!definition)
101+
{
102+
impl::throw_invalid("Type '", type_namespace, ".", type_name, "' could not be found");
103+
}
104+
105+
return definition;
106+
}
107+
108+
TypeDef find_required(std::string_view const& type_string) const
109+
{
110+
auto pos = type_string.rfind('.');
111+
112+
if (pos == std::string_view::npos)
113+
{
114+
impl::throw_invalid("Type '", type_string, "' is missing a namespace qualifier");
115+
}
116+
117+
return find_required(type_string.substr(0, pos), type_string.substr(pos + 1, type_string.size()));
118+
}
119+
120+
auto const& databases() const noexcept
121+
{
122+
return m_databases;
123+
}
124+
125+
auto const& namespaces() const noexcept
126+
{
127+
return m_namespaces;
128+
}
129+
130+
void remove_type(std::string_view const& ns, std::string_view const& name)
131+
{
132+
auto m = m_namespaces.find(ns);
133+
if (m == m_namespaces.end())
134+
{
135+
return;
136+
}
137+
auto& members = m->second;
138+
139+
auto remove = [&](auto&& collection, auto&& name)
140+
{
141+
auto pos = std::find_if(collection.begin(), collection.end(), [&](auto&& type)
142+
{
143+
return type.TypeName() == name;
144+
});
145+
146+
if (pos != collection.end())
147+
{
148+
collection.erase(pos);
149+
}
150+
};
151+
152+
remove(members.interfaces, name);
153+
remove(members.classes, name);
154+
remove(members.enums, name);
155+
remove(members.structs, name);
156+
remove(members.delegates, name);
157+
}
158+
159+
// This won't invalidate any existing database or row_base (e.g. TypeDef) instances
160+
// However, it may invalidate iterators and references to namespace_members, because those are stored in std::vector
161+
template <typename TypeFilter>
162+
void add_database(std::string_view const& file, TypeFilter filter)
163+
{
164+
auto& db = m_databases.emplace_back(file, this);
165+
for (auto&& type : db.TypeDef)
166+
{
167+
if (type.Flags().value == 0 || is_nested(type) || !filter(type))
168+
{
169+
continue;
170+
}
171+
172+
auto& ns = m_namespaces[type.TypeNamespace()];
173+
auto[iter, inserted] = ns.types.try_emplace(type.TypeName(), type);
174+
if (inserted)
175+
{
176+
add_type_to_members(type, ns);
177+
}
178+
}
179+
180+
for (auto&& row : db.NestedClass)
181+
{
182+
m_nested_types[row.EnclosingType()].push_back(row.NestedType());
183+
}
184+
}
185+
186+
void add_database(std::string_view const& file)
187+
{
188+
add_database(file, default_type_filter{});
189+
}
190+
191+
std::vector<TypeDef> const& nested_types(TypeDef const& enclosing_type) const
192+
{
193+
auto it = m_nested_types.find(enclosing_type);
194+
if (it != m_nested_types.end())
195+
{
196+
return it->second;
197+
}
198+
else
199+
{
200+
static const std::vector<TypeDef> empty;
201+
return empty;
202+
}
203+
}
204+
205+
struct namespace_members
206+
{
207+
std::map<std::string_view, TypeDef> types;
208+
std::vector<TypeDef> interfaces;
209+
std::vector<TypeDef> classes;
210+
std::vector<TypeDef> enums;
211+
std::vector<TypeDef> structs;
212+
std::vector<TypeDef> delegates;
213+
std::vector<TypeDef> attributes;
214+
std::vector<TypeDef> contracts;
215+
};
216+
217+
using namespace_type = std::pair<std::string_view const, namespace_members> const&;
218+
219+
private:
220+
221+
void add_type_to_members(TypeDef const& type, namespace_members& members)
222+
{
223+
switch (get_category(type))
224+
{
225+
case category::interface_type:
226+
members.interfaces.push_back(type);
227+
return;
228+
case category::class_type:
229+
if (extends_type(type, "System"sv, "Attribute"sv))
230+
{
231+
members.attributes.push_back(type);
232+
return;
233+
}
234+
members.classes.push_back(type);
235+
return;
236+
case category::enum_type:
237+
members.enums.push_back(type);
238+
return;
239+
case category::struct_type:
240+
if (get_attribute(type, "Windows.Foundation.Metadata"sv, "ApiContractAttribute"sv))
241+
{
242+
members.contracts.push_back(type);
243+
return;
244+
}
245+
members.structs.push_back(type);
246+
return;
247+
case category::delegate_type:
248+
members.delegates.push_back(type);
249+
return;
250+
}
251+
}
252+
253+
std::list<database> m_databases;
254+
std::map<std::string_view, namespace_members> m_namespaces;
255+
std::map<TypeDef, std::vector<TypeDef>> m_nested_types;
256+
};
257+
}

0 commit comments

Comments
 (0)