Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python script for generating Natvis file and update file for 3.11.2 #3697

Merged
merged 3 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 246 additions & 2 deletions nlohmann_json.natvis
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<!-- * * * * * * * * AUTO-GENERATED FILE * * * * * * * * -->
<!-- Edit ./tools/generate_natvis/nlohmann_json.natvis.j2 -->
<!-- * * * * * * * * AUTO-GENERATED FILE * * * * * * * * -->
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<!-- Namespace nlohmann -->
<Type Name="nlohmann::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::object">{*(m_value.object)}</DisplayString>
Expand All @@ -20,13 +24,253 @@
</Expand>
</Type>

<!-- skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi -->
<Type Name="nlohmann::json_abi::basic_json&lt;*&gt;">
Copy link
Contributor

@gregmarr gregmarr Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use wildcards for the namespace? nlohmann::*::basic_json...? If so, could we also hardcode the values for nlohmann::*::detail::value_t::*? This would allow a single natvis file that would work for any version?

Otherwise, would it make sense to include the version number in the filename so that users could have multiple version files installed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wildcards are only supported for template parameters according to the documentation.

Users will have to comment on whether versioning the Natvis file would be helpful. (ping @jheydebrand)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wildcards are only supported for template parameters according to the documentation.

I saw documentation that said that they worked for templates, but it didn't specifically say that it was only used there, so I wasn't sure if it was limited to templates or just poorly documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fully qualified name of each Type element is specified in its Name attribute.

and

Templated classes

The Name attribute of the Type element accepts an asterisk * as a wildcard character that can be used for templated class names.

In the following example, the same visualization is used whether the object is a CAtlArray or a CAtlArray. If there's a specific visualization entry for a CAtlArray, then it takes precedence over the generic one.

The very specific wording suggests to me it only works for templates. 🤷‍♂️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed that it only works for templates. :(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the swift responses.

Versioning the natvis file would not provide any benefit for me.
When consuming the library via its CMake integration the correct / matching natvis file will be included anyway and I have no desire to copy the file to some system-wide directory (which is supported by Visual Studio and might have been the use-case for versioned natvis files you were thinking about?).

<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_v3_11_2 -->
<Type Name="nlohmann::json_abi_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_diag -->
<Type Name="nlohmann::json_abi_diag::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_diag_v3_11_2 -->
<Type Name="nlohmann::json_abi_diag_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_ldvcmp -->
<Type Name="nlohmann::json_abi_ldvcmp::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_ldvcmp::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_ldvcmp_v3_11_2 -->
<Type Name="nlohmann::json_abi_ldvcmp_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_ldvcmp_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_diag_ldvcmp -->
<Type Name="nlohmann::json_abi_diag_ldvcmp::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_ldvcmp::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

<!-- Namespace nlohmann::json_abi_diag_ldvcmp_v3_11_2 -->
<Type Name="nlohmann::json_abi_diag_ldvcmp_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>

<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_ldvcmp_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
</Expand>
</Type>

</AutoVisualizer>
10 changes: 10 additions & 0 deletions tools/generate_natvis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
generate_natvis.py
==================

Generate the Natvis debugger visualization file for all supported namespace combinations.

## Usage

```
./generate_natvis.py --version X.Y.Z output_directory/
```
35 changes: 35 additions & 0 deletions tools/generate_natvis/generate_natvis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3

import argparse
import itertools
import jinja2
import os
import sys

if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--version', required=True, help='Library version number')
parser.add_argument('output', help='Output directory for nlohmann_json.natvis')
args = parser.parse_args()

namespaces = ['nlohmann']
abi_prefix = 'json_abi'
abi_tags = ['_diag', '_ldvcmp']
version = '_v' + args.version.replace('.', '_')
inline_namespaces = []

for n in range(0, len(abi_tags) + 1):
for tags in itertools.combinations(abi_tags, n):
ns = abi_prefix + ''.join(tags)
inline_namespaces += [ns]
inline_namespaces += [ns + version]

namespaces += [f'{namespaces[0]}::{ns}' for ns in inline_namespaces]

env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=sys.path[0]), autoescape=True, trim_blocks=True,
lstrip_blocks=True, keep_trailing_newline=True)
template = env.get_template('nlohmann_json.natvis.j2')
natvis = template.render(namespaces=namespaces)

with open(os.path.join(args.output, 'nlohmann_json.natvis'), 'w') as f:
f.write(natvis)
Loading