From 15fa583c56f1b6bdaddd25837c6a311074a2adc8 Mon Sep 17 00:00:00 2001 From: Matthias Heil Date: Tue, 31 Mar 2026 13:16:22 +0200 Subject: [PATCH] Deleted MemoryStreamDebugVisualizer Deleted NrxDebugVisualizer --- .../Directory.Build.props | 14 -- .../MemoryStreamObjectSource.csproj | 14 -- .../MemoryStreamVisualizerObjectSource.cs | 64 ------ .../MemoryStreamVisualizer.slnx | 5 - .../ExtensionEntrypoint.cs | 33 --- .../MemoryStreamVisualizer/HexEditorRow.cs | 50 ----- .../MemoryStreamData.cs | 80 ------- .../MemoryStreamDebuggerVisualizerProvider.cs | 36 ---- .../MemoryStreamVisualizer.csproj | 29 --- .../MemoryStreamVisualizerUserControl.cs | 150 -------------- .../MemoryStreamVisualizerUserControl.xaml | 115 ---------- .../TestApp/Program.cs | 23 -- .../TestApp/TestApp.csproj | 14 -- NrxDebugVisualizer/Directory.Build.props | 51 ----- NrxDebugVisualizer/NrxDebugVisualizer.sln | 32 --- NrxDebugVisualizer/README.md | 196 ------------------ .../TestDebugVisualizer/Program.cs | 49 ----- .../TestDebugVisualizer.csproj | 10 - NrxDebugVisualizer/TestVisualizer.sln | 25 --- .../Vector3DebugVisualizer/README.md | 196 ------------------ .../.vsextension/string-resources.json | 3 - .../Vector3DebuggerVisualizerProvider.cs | 35 ---- .../Vector3/Vector3VisualizerUserControl.cs | 20 -- .../Vector3/Vector3VisualizerUserControl.xaml | 7 - .../Vector3DebugVisualizer.csproj | 25 --- .../Vector3VisualizerExtension.cs | 32 --- .../Vector3DebuggerVisualizerProvider.cs | 33 --- .../Vector3Visualizer.csproj | 25 --- .../Vector3VisualizerSource.csproj | 14 -- 29 files changed, 1380 deletions(-) delete mode 100644 MemoryStreamDebugVisualizer/Directory.Build.props delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamObjectSource.csproj delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamVisualizerObjectSource.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer.slnx delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/ExtensionEntrypoint.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/HexEditorRow.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamData.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamDebuggerVisualizerProvider.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizer.csproj delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.cs delete mode 100644 MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.xaml delete mode 100644 MemoryStreamDebugVisualizer/TestApp/Program.cs delete mode 100644 MemoryStreamDebugVisualizer/TestApp/TestApp.csproj delete mode 100644 NrxDebugVisualizer/Directory.Build.props delete mode 100644 NrxDebugVisualizer/NrxDebugVisualizer.sln delete mode 100644 NrxDebugVisualizer/README.md delete mode 100644 NrxDebugVisualizer/TestDebugVisualizer/Program.cs delete mode 100644 NrxDebugVisualizer/TestDebugVisualizer/TestDebugVisualizer.csproj delete mode 100644 NrxDebugVisualizer/TestVisualizer.sln delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/README.md delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/.vsextension/string-resources.json delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3DebuggerVisualizerProvider.cs delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.cs delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.xaml delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer.csproj delete mode 100644 NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3VisualizerExtension.cs delete mode 100644 Vector3Visualizer/Vector3Visualizer/Vector3DebuggerVisualizerProvider.cs delete mode 100644 Vector3Visualizer/Vector3Visualizer/Vector3Visualizer.csproj delete mode 100644 Vector3Visualizer/Vector3VisualizerSource/Vector3VisualizerSource.csproj diff --git a/MemoryStreamDebugVisualizer/Directory.Build.props b/MemoryStreamDebugVisualizer/Directory.Build.props deleted file mode 100644 index 9a6f2ef..0000000 --- a/MemoryStreamDebugVisualizer/Directory.Build.props +++ /dev/null @@ -1,14 +0,0 @@ - - - Debug - $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)')) - $(RepoRootPath)obj\$(MSBuildProjectName)\ - $(RepoRootPath)bin\$(MSBuildProjectName)\ - false - false - true - false - false - latest - - diff --git a/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamObjectSource.csproj b/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamObjectSource.csproj deleted file mode 100644 index 0350e38..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamObjectSource.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - netstandard2.0 - enable - 12 - - - - - - - - - diff --git a/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamVisualizerObjectSource.cs b/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamVisualizerObjectSource.cs deleted file mode 100644 index 60656a9..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamObjectSource/MemoryStreamVisualizerObjectSource.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace MemoryStreamObjectSource; - -using Microsoft.VisualStudio.DebuggerVisualizers; -using System.IO; - -/// -/// Object source class for the MemoryStreamVisualizer. -/// -public class MemoryStreamVisualizerObjectSource : VisualizerObjectSource -{ - /// - /// How many rows will be transfered, at most, responding to a single request. - /// - public const int RowsCountPerRequest = 1024; - - /// - /// How many bytes will be transfered for each row. - /// - public const int RowLength = 16; - - /// - public override void TransferData(object target, Stream incomingData, Stream outgoingData) - { - if (target is not MemoryStream memoryStream) - { - return; - } - - - using BinaryReader binaryReader = new(incomingData); - var index = binaryReader.ReadInt32(); // The extension will send the offset (Int32) to start reading from - - using BinaryWriter binaryWriter = new(outgoingData); - var backupPosition = memoryStream.Position; - - // Will reply with the current MemoryStream.Position (Int64), - // followed by MemoryStream.Length (Int64), - // followed by up to 16KB of data retrieved from the MemoryStream - binaryWriter.Write(backupPosition); - binaryWriter.Write(memoryStream.Length); - if (index < memoryStream.Length) - { - try - { - var data = new byte[RowsCountPerRequest * RowLength]; - memoryStream.Seek(index, SeekOrigin.Begin); - var count = memoryStream.Read(data, 0, data.Length); - binaryWriter.Write(data, 0, count); - } - finally - { - // Make sure to restore the MemoryStream to its original position - memoryStream.Seek(backupPosition, SeekOrigin.Begin); - } - } - - binaryWriter.Flush(); - - } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer.slnx b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer.slnx deleted file mode 100644 index 2ac69b0..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer.slnx +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/ExtensionEntrypoint.cs b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/ExtensionEntrypoint.cs deleted file mode 100644 index 7119fb1..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/ExtensionEntrypoint.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace MemoryStreamVisualizer; - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.VisualStudio.Extensibility; - -/// -/// Extension entrypoint for the VisualStudio.Extensibility extension. -/// -[VisualStudioContribution] -internal class ExtensionEntrypoint : Extension -{ - /// - public override ExtensionConfiguration ExtensionConfiguration => new() - { - Metadata = new( - id: "MemoryStreamVisualizer.97a0a2fb-f163-4fa3-91f0-48a2d4ad9f57", - version: this.ExtensionAssemblyVersion, - publisherName: "Microsoft", - displayName: "MemoryStream Debugger Visualizer", - description: "A debugger visualizer for MemoryStream"), - }; - - /// - protected override void InitializeServices(IServiceCollection serviceCollection) - { - base.InitializeServices(serviceCollection); - - // You can configure dependency injection here by adding services to the serviceCollection. - } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/HexEditorRow.cs b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/HexEditorRow.cs deleted file mode 100644 index 8d78106..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/HexEditorRow.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace MemoryStreamVisualizer; - -using System.Runtime.Serialization; - -/// -/// ViewModel class representing a row of binary data. -/// -[DataContract] -public class HexEditorRow -{ - /// - /// Initializes a new instance of the class. - /// - /// The index of this row. - /// The bytes making up this row of data, in their hex representation. - /// The bytes making up this row of data, in their Ascii representation. - public HexEditorRow(int index, string data, string ascii) - { - this.Index = index; - this.Data = data; - this.Ascii = ascii; - } - - /// - /// Gets the index of this row. - /// - [DataMember] - public int Index { get; } - - /// - /// Gets the index of this row in hex format. - /// - [DataMember] - public string HexIndex => $"{this.Index:X8}h"; - - /// - /// Gets the bytes making up this row of data, in their hex representation. - /// - [DataMember] - public string Data { get; } - - /// - /// Gets the bytes making up this row of data, in their Ascii representation. - /// - [DataMember] - public string Ascii { get; } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamData.cs b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamData.cs deleted file mode 100644 index fa7d396..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamData.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace MemoryStreamVisualizer; - -using System.IO; -using System.Runtime.Serialization; -using System.Windows; -using Microsoft.VisualStudio.Extensibility.UI; - -/// -/// ViewModel class representing the data contained by a . -/// -[DataContract] -public class MemoryStreamData : NotifyPropertyChangedObject -{ - private long length; - private long position; - private Visibility loadingVisibility = Visibility.Visible; - - /// - /// Gets or sets the length of the . - /// - [DataMember] - public long Length - { - get => this.length; - set - { - if (this.SetProperty(ref this.length, value)) - { - this.RaiseNotifyPropertyChangedEvent(nameof(this.HexLength)); - } - } - } - - /// - /// Gets the length of the in hex format. - /// - [DataMember] - public string HexLength => $"{this.length:X}h"; - - /// - /// Gets or sets the current position of the . - /// - [DataMember] - public long Position - { - get => this.position; - set - { - if (this.SetProperty(ref this.position, value)) - { - this.RaiseNotifyPropertyChangedEvent(nameof(this.HexPosition)); - } - } - } - - /// - /// Gets the current position of the in hex format. - /// - [DataMember] - public string HexPosition => $"{this.position:X}h"; - - /// - /// Gets the data currently contained in the . - /// - [DataMember] - public ObservableList Data { get; } = new(); - - /// - /// Gets or sets whether the loading bar should be visible. - /// - [DataMember] - public Visibility LoadingVisibility - { - get => this.loadingVisibility; - set => this.SetProperty(ref this.loadingVisibility, value); - } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamDebuggerVisualizerProvider.cs b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamDebuggerVisualizerProvider.cs deleted file mode 100644 index 4de5353..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamDebuggerVisualizerProvider.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace MemoryStreamVisualizer; - -using MemoryStreamObjectSource; -using Microsoft.VisualStudio.Extensibility; -using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers; -using Microsoft.VisualStudio.RpcContracts.RemoteUI; -using System.IO; - -using System.Threading; -using System.Threading.Tasks; - -/// -/// Debugger visualizer provider for . -/// -[VisualStudioContribution] -internal class MemoryStreamDebuggerVisualizerProvider : DebuggerVisualizerProvider -{ - /// - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new( - [ - new VisualizerTargetType("%MemoryStreamVisualizer.MemoryStreamDebuggerVisualizerProvider.Name%", typeof(MemoryStream)), - ]) - { - VisualizerObjectSourceType = new VisualizerObjectSourceType(typeof(MemoryStreamVisualizerObjectSource)), - Style = VisualizerStyle.ToolWindow, - }; - - /// - public override Task CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken) - { - return Task.FromResult(new MemoryStreamVisualizerUserControl(visualizerTarget)); - } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizer.csproj b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizer.csproj deleted file mode 100644 index 2024e28..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizer.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - net8.0-windows8.0 - enable - 12 - en-US - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.cs b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.cs deleted file mode 100644 index bdf3e66..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - - -using MemoryStreamObjectSource; -using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers; -using Microsoft.VisualStudio.Extensibility.UI; -using Microsoft.VisualStudio.RpcContracts.DebuggerVisualizers; -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; - -namespace MemoryStreamVisualizer; -/// -/// Remote UI user control for the MemoryStreamVisualizer. -/// -internal class MemoryStreamVisualizerUserControl : RemoteUserControl -{ - private readonly VisualizerTarget visualizerTarget; - private readonly MemoryStreamData dataContext; - - /// - /// Initializes a new instance of the class. - /// - /// The visualizer target to be used to retrieve data from. - public MemoryStreamVisualizerUserControl(VisualizerTarget visualizerTarget) - : base(new MemoryStreamData()) - { - visualizerTarget.Changed += this.VisualizerTargetStateChangedAsync; - - this.dataContext = (MemoryStreamData)this.DataContext!; - this.visualizerTarget = visualizerTarget; - } - - private Task VisualizerTargetStateChangedAsync(VisualizerTargetStateNotification args) - { - if (args == VisualizerTargetStateNotification.Available || args == VisualizerTargetStateNotification.ValueUpdated) - { - this.dataContext.Data.Clear(); - this.dataContext.Position = 0; - this.dataContext.Length = 0; - this.dataContext.LoadingVisibility = Visibility.Visible; - - return this.RetrieveDataAsync(); - } - - return Task.CompletedTask; - } - - private async Task RetrieveDataAsync() - { - ReadOnlySequence data; - do - { - using MemoryStream memoryStream = new(sizeof(int)); - using BinaryWriter binaryWriter = new(memoryStream); - int index = this.dataContext.Data.Count * MemoryStreamVisualizerObjectSource.RowLength; - if (index >= 1024 * 1024) - { - break; // Let's not retrieve more than 1MB of data - } - - binaryWriter.Write(index); - binaryWriter.Flush(); - try - { - data = (await this.visualizerTarget.ObjectSource.RequestDataAsync(new ReadOnlySequence(memoryStream.ToArray()), CancellationToken.None)).Value; - } -#pragma warning disable CA1031 // Do not catch general exception types - catch (Exception) -#pragma warning restore CA1031 // Do not catch general exception types - { - // I can get an exception if the debug session is unpaused, so I need to handle it gracefully - break; - } - } - while (data.Length > 0 && this.Read(data)); - - this.dataContext.LoadingVisibility = Visibility.Hidden; - } - - private bool Read(ReadOnlySequence data) - { - int byteInRowCount = 0; - StringBuilder binaryText = new(); - StringBuilder asciiText = new(); - - SequenceReader reader = new(data); - if (!reader.TryReadLittleEndian(out long position) || !reader.TryReadLittleEndian(out long length)) - { - return false; - } - - this.dataContext.Position = position; - this.dataContext.Length = length; - - if (reader.UnreadSpan.Length == 0) - { - return false; // We always receive data unless we are at the end of the MemoryStream - } - - List rows = new(MemoryStreamVisualizerObjectSource.RowsCountPerRequest); - byte[] tmp = new byte[1]; - while (reader.TryRead(out byte b)) - { - byteInRowCount++; - if (byteInRowCount > 1) - { - binaryText.Append(' '); - } - - binaryText.Append(b.ToString("X2", CultureInfo.InvariantCulture)); - tmp[0] = b; - asciiText.Append(char.IsControl((char)b) || b == 0xAD ? '•' : Encoding.Latin1.GetChars(tmp)[0]); - - if (byteInRowCount == MemoryStreamVisualizerObjectSource.RowLength) - { - CompleteRow(); - } - } - - if (byteInRowCount > 0) - { - CompleteRow(); - this.dataContext.Data.AddRange(rows); - return false; // We only receive partial rows at the end of the MemoryStream - } - - this.dataContext.Data.AddRange(rows); - return true; - - void CompleteRow() - { - rows.Add(new HexEditorRow( - index: (this.dataContext.Data.Count + rows.Count) * MemoryStreamVisualizerObjectSource.RowLength, - data: binaryText.ToString(), - ascii: asciiText.ToString())); - - byteInRowCount = 0; - binaryText.Clear(); - asciiText.Clear(); - } - } -} diff --git a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.xaml b/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.xaml deleted file mode 100644 index 2c6b164..0000000 --- a/MemoryStreamDebugVisualizer/MemoryStreamVisualizer/MemoryStreamVisualizerUserControl.xaml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Hex - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MemoryStreamDebugVisualizer/TestApp/Program.cs b/MemoryStreamDebugVisualizer/TestApp/Program.cs deleted file mode 100644 index d93c1e0..0000000 --- a/MemoryStreamDebugVisualizer/TestApp/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Text; - -// Initialize a MemoryStream to store user input temporarily -using MemoryStream userInputStream = new(); - -// Convert user input string to byte array -string userInput = "Sample user input data"; - -byte[] inputData = Encoding.UTF8.GetBytes(userInput); - -// Write user input data to the MemoryStream -userInputStream.Write(inputData, 0, inputData.Length); -var buffer = new byte[inputData.Length]; -userInputStream.Position = 0; -userInputStream.Read(buffer); -var text = Encoding.UTF8.GetString(buffer, 0, buffer.Length); - -// Perform further processing with the stored user input -Thread.Sleep(1000); \ No newline at end of file diff --git a/MemoryStreamDebugVisualizer/TestApp/TestApp.csproj b/MemoryStreamDebugVisualizer/TestApp/TestApp.csproj deleted file mode 100644 index 489df93..0000000 --- a/MemoryStreamDebugVisualizer/TestApp/TestApp.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - diff --git a/NrxDebugVisualizer/Directory.Build.props b/NrxDebugVisualizer/Directory.Build.props deleted file mode 100644 index a77b037..0000000 --- a/NrxDebugVisualizer/Directory.Build.props +++ /dev/null @@ -1,51 +0,0 @@ - - - Debug - $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\')) - $(RepoRootPath)obj\samples\$(MSBuildProjectName)\ - $(RepoRootPath)bin\samples\$(MSBuildProjectName)\ - false - false - true - $(MSBuildThisFileDirectory)shipping.ruleset - true - true - latest - - - - - true - $(NoWarn);SA1600;SA1602;CS1591 - - - $(NoWarn);SA1010 - - - $(NoWarn);CA1812;CA1303 - - - - - - - - - - diff --git a/NrxDebugVisualizer/NrxDebugVisualizer.sln b/NrxDebugVisualizer/NrxDebugVisualizer.sln deleted file mode 100644 index 7ceb48e..0000000 --- a/NrxDebugVisualizer/NrxDebugVisualizer.sln +++ /dev/null @@ -1,32 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.4.11620.152 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{070F0AEA-C0A0-4B5D-9286-55574A37BE7A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Vector3DebugVisualizer", "Vector3DebugVisualizer", "{8554ABE3-9105-4AF7-9318-81414CC190C6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vector3DebugVisualizer", "Vector3DebugVisualizer\Vector3DebugVisualizer\Vector3DebugVisualizer.csproj", "{D8310D46-26AC-C7D7-1668-BFEBB7072467}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D8310D46-26AC-C7D7-1668-BFEBB7072467}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D8310D46-26AC-C7D7-1668-BFEBB7072467}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D8310D46-26AC-C7D7-1668-BFEBB7072467}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D8310D46-26AC-C7D7-1668-BFEBB7072467}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D8310D46-26AC-C7D7-1668-BFEBB7072467} = {8554ABE3-9105-4AF7-9318-81414CC190C6} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {40A38C8A-61B7-427B-A430-DEB75BE34F22} - EndGlobalSection -EndGlobal diff --git a/NrxDebugVisualizer/README.md b/NrxDebugVisualizer/README.md deleted file mode 100644 index 415ff60..0000000 --- a/NrxDebugVisualizer/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# RegEx Match Debug Visualizer - -This VisualStudio.Extensibility extension adds two new debugger visualizers supporting the .NET [`Match`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.match) and [`MatchCollection`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.matchcollection) classes. - -![RegEx Match visualizer](RegexMatchVisualizer.png "RegEx Match visualizer") - -The extension is composed of two projects: `RegexMatchDebugVisualizer`, the actual extension, and `RegexMatchObjectSource`, the visualizer object source library. - -## Creating the extension - -The extension project is created as described in the [tutorial document](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/get-started/create-your-first-extension). You can also reference the [debugger visualizers guide](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/debugger-visualizer/debugger-visualizers) for additional information. - -## The `Match` visualizer - -The next step is to create a `DebuggerVisualizerProvider` class to visualize instances of [`Match`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.match): - -```csharp -[VisualStudioContribution] -internal class RegexMatchDebuggerVisualizerProvider : DebuggerVisualizerProvider -{ - ... -``` - -If the `Match` type were serializable by Newtonsoft.Json, the visualizer implementation would be extremely simple: - -```csharp -public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => ew("Regex Match visualizer", typeof(Match)); - -public override async Task CreateVisualizerAsync(VisualizerTarget isualizerTarget, CancellationToken cancellationToken) -{ - var regexMatch = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, cancellationToken); - return new RegexMatchVisualizerUserControl(regexMatch); -} -``` - -Unfortunately `Match` is not serializable as-is, so we need a new serializable class [`RegexMatch`](RegexMatchObjectSource/RegexMatch.cs). And we will need to create a visualizer object source library to convert the `Match` into a serializable `RegexMatch`, more about this in [a later paragraph](#the-visualizer-object-source). For now, let's just update the `RequestDataAsync` call to use `RegexMatch`: - -```csharp -var regexMatch = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, cancellationToken); -``` - -### Adding the remote user control - -We now have to create the `RegexMatchVisualizerUserControl` [class](./RegexMatchDebugVisualizer/RegexMatch/RegexMatchVisualizerUserControl.cs) and its associated [XAML file](./RegexMatchDebugVisualizer/RegexMatch/RegexMatchVisualizerUserControl.xaml). This process is described in the [Remote UI documentation](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/inside-the-sdk/remote-ui). - -Every time we create a remote user control like `RegexMatchVisualizerUserControl` we need to configure the corresponding XAML file as embedded resource. In this case, since the XAML file is in a subfolder, we also need to use `LogicalName` to make sure the name of the resource matches the full name of the remote user control class. This is all done in the `.csproj` file: - -```xml - - - - -``` - -## The visualizer object source - -The visualizer object source assembly will be loaded by the debugger into the process being debugged and will take care of converting the `Match` object into a serializable `RegexMatch`. - -I will start creating a `RegexMatchObjectSource` class library targeting `netstandard2.0` and adding a project reference to [Microsoft.VisualStudio.DebuggerVisualizers](https://www.nuget.org/packages/Microsoft.VisualStudio.DebuggerVisualizers) version 17.6 or newer. Targeting `netstandard2.0` will allow the debugger visualizer to easily work with a large variety of .NET versions. - -I will then create a `RegexMatchObjectSource` class extending `VisualizerObjectSource` and will override the `GetData` method to convert the `target` from a `Match` to a `RegexMatch` and use the `VisualizerObjectSource.SerializeAsJson` method to write the value to the `outgoingData` stream. - -```csharp -public class RegexMatchObjectSource : VisualizerObjectSource -{ - public override void GetData(object target, Stream outgoingData) - { - if (target is Match match) - { - RegexMatch result = Convert(match); - SerializeAsJson(outgoingData, result); - } - } - - ... -``` - -The `GetData` method is invoked by the debugger when the `RegexMatchDebuggerVisualizerProvider` calls `RequestDataAsync`. - -`SerializeAsJson` will serialize the `RegexMatch` object using Newtonsoft.Json, which is loaded by the debugger in the process being debugged via reflection. Since my visualizer object source doesn't need to refence Newtonsoft.Json directly, I didn't include a `PackageReference` to it, which is better since we should minimize the dependencies of the visualizer object source assembly. Because this code doesn't reference Newtonsoft.Json, the `RegexMatch` class uses `DataContract` and `DataMember` attributes to control serialization instead of the Newtonsoft.Json-specific types. - -My [`RegexMatchObjectSource`](./RegexMatchObjectSource/RegexMatchObjectSource.cs) implementation contains a small trick: the [`Group.Name`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.group.name) property is read through reflection since it's available on most .NET versions but it is not included in the `netstandard2.0` APIs: - -```csharp -private static readonly Func? GetGroupName = - (Func?)typeof(Group).GetProperty("Name")?.GetGetMethod().CreateDelegate(typeof(Func)); - -... - -Name = $"[{GetGroupName?.Invoke(g) ?? i.ToString()}]" -``` - -### Referencing the visualizer object source from the extension - -First, we need to make sure that the visualizer object source library is packaged as part of the extension. We can do that in the extension's `.csproj` file: - -```xml - - - PreserveNewest - - - - - - -``` - -The `ProjectReference` guarantees that the visualizer object source library is built before the extension and the `Content` item makes sure that the visualizer object source DLL is copied into the `netstandard2.0` extension's subfolder where it will be discoverable by the debugger. - -I have decided to use `ReferenceOutputAssembly="false"` to avoid a dependency of the extension assembly from the visualizer object source one. This allows using conditional compilation (`#if`) to have slightly different definitions of [`RegexCapture`](./RegexMatchObjectSource/RegexCapture.cs) in the two projects. Since I decided to avoid the dependency, I will need to: - -1. link the `RegexMatch.cs` file (and the related `RegexCapture` and `RegexGroup` ones) so that they are available in both projects: - -```xml - - - - - -``` - -2. Reference the `RegexMatchObjectSource` from the `DebuggerVisualizerProviderConfiguration` using its assembly-qualified name: - -```csharp - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Regex Match visualizer", typeof(Match)) - { - VisualizerObjectSourceType = new("Microsoft.VisualStudio.Gladstone.RegexMatchVisualizer.ObjectSource.RegexMatchObjectSource, RegexMatchObjectSource"), - }; -``` - -In most cases, having the extension project depend on the visualizer object source library is simpler: I could have simplified the `DebuggerVisualizerProviderConfiguration` to: - -```csharp - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Regex Match visualizer", typeof(Match)) - { - VisualizerObjectSourceType = new(typeof(RegexMatchObjectSource)), - }; -``` - -## The `MatchCollection` visualizer - -Now that the `Match` visualizer is complete, we can add a second visualizer for the [`MatchCollection`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.matchcollection) class. The process is exactly the same: create a new [`DebuggerVisualizerProvider`](./RegexMatchDebugVisualizer/RegexMatchCollection/RegexMatchCollectionDebuggerVisualizerProvider.cs) and its [remote user control](./RegexMatchDebugVisualizer/RegexMatchCollection/RegexMatchCollectionVisualizerUserControl.cs). Also, add a new [`VisualizerObjectSource`](./RegexMatchObjectSource/RegexMatchCollectionObjectSource.cs) to the visualizer object source library. - -Each call to `RequestDataAsync` is allowed only 5 seconds to complete before throwing a timeout exception. Since the `MatchCollection` could contain many entries, the visualizer object source uses the `TransferData` method instead of `GetData`: `TransferData` accepts a parameter which allows the visualizer to query the collection entries one by one: - -```csharp -public override void TransferData(object target, Stream incomingData, Stream outgoingData) -{ - var index = (int)DeserializeFromJson(incomingData, typeof(int))!; - if (target is MatchCollection matchCollection && index < matchCollection.Count) - { - var result = RegexMatchObjectSource.Convert(matchCollection[index]); - result.Name = $"[{index}]"; - SerializeAsJson(outgoingData, result); - } - else - { - SerializeAsJson(outgoingData, null); - } -} -``` - -Instead of using the `VisualizerTarget` directly, the `DebuggerVisualizerProvider` passes it to the remote user control so that it can asynchronously request the collection entries without delaying the display of the visualizer UI to the user. - -```csharp -public override Task CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken) -{ - return Task.FromResult(new RegexMatchCollectionVisualizerUserControl(visualizerTarget)); -} -``` - -The remote user control uses the `RequestDataAsync` override that takes a `message` parameter, which results in `TransferData` being invoked on the visualizer object source. The remote user control will loop, invoking `RequestDataAsync` for increasing index numbers until the visualizer object source returns `null`, which indicates the end of the collection: - -```csharp -public override Task ControlLoadedAsync(CancellationToken cancellationToken) -{ - _ = Task.Run(async () => - { - for (int i = 0; ; i++) - { - RegexMatch? regexMatch = await this.visualizerTarget.ObjectSource.RequestDataAsync(message: i, jsonSerializer: null, CancellationToken.None); - if (regexMatch is null) - { - break; - } - - this.RegexMatches.Add(regexMatch); - } - }); - - return Task.CompletedTask; -} -``` - -This is a very simple implementation of a debugger visualizer which relies on `RequestDataAsync`. More complex implementations may pass more complex parameters to `RequestDataAsync` in order to retrieve different information from the visualizer object source. You could even invoke `RequestDataAsync` in response to the user's interactions with the remote user control, allowing the user to "explore" the content of, potentially very large, objects. diff --git a/NrxDebugVisualizer/TestDebugVisualizer/Program.cs b/NrxDebugVisualizer/TestDebugVisualizer/Program.cs deleted file mode 100644 index 90bbe7f..0000000 --- a/NrxDebugVisualizer/TestDebugVisualizer/Program.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Text.RegularExpressions; - -class Example -{ - static void Main() - { - string text = "One car red car blue car"; - string pat = @"(\w+)\s+(car)"; - - // Instantiate the regular expression object. - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - - // Match the regular expression pattern against a text string. - Match m = r.Match(text); - int matchCount = 0; - while (m.Success) - { - Console.WriteLine("Match" + (++matchCount)); - for (int i = 1; i <= 2; i++) - { - Group g = m.Groups[i]; - Console.WriteLine("Group" + i + "='" + g + "'"); - CaptureCollection cc = g.Captures; - for (int j = 0; j < cc.Count; j++) - { - Capture c = cc[j]; - System.Console.WriteLine("Capture" + j + "='" + c + "', Position=" + c.Index); - } - } - m = m.NextMatch(); - } - } -} -// This example displays the following output: -// Match1 -// Group1='One' -// Capture0='One', Position=0 -// Group2='car' -// Capture0='car', Position=4 -// Match2 -// Group1='red' -// Capture0='red', Position=8 -// Group2='car' -// Capture0='car', Position=12 -// Match3 -// Group1='blue' -// Capture0='blue', Position=16 -// Group2='car' -// Capture0='car', Position=21 \ No newline at end of file diff --git a/NrxDebugVisualizer/TestDebugVisualizer/TestDebugVisualizer.csproj b/NrxDebugVisualizer/TestDebugVisualizer/TestDebugVisualizer.csproj deleted file mode 100644 index ed9781c..0000000 --- a/NrxDebugVisualizer/TestDebugVisualizer/TestDebugVisualizer.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/NrxDebugVisualizer/TestVisualizer.sln b/NrxDebugVisualizer/TestVisualizer.sln deleted file mode 100644 index d4c293a..0000000 --- a/NrxDebugVisualizer/TestVisualizer.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.4.11620.152 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestDebugVisualizer", "TestDebugVisualizer\TestDebugVisualizer.csproj", "{221A5163-F586-4766-A524-C8097AD06068}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {221A5163-F586-4766-A524-C8097AD06068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {221A5163-F586-4766-A524-C8097AD06068}.Debug|Any CPU.Build.0 = Debug|Any CPU - {221A5163-F586-4766-A524-C8097AD06068}.Release|Any CPU.ActiveCfg = Release|Any CPU - {221A5163-F586-4766-A524-C8097AD06068}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C63DCA03-00AC-476D-B4FE-43DC4F4EBA35} - EndGlobalSection -EndGlobal diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/README.md b/NrxDebugVisualizer/Vector3DebugVisualizer/README.md deleted file mode 100644 index 180c4d6..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# RegEx Vector3 Debug Visualizer - -This VisualStudio.Extensibility extension adds two new debugger visualizers supporting the .NET [`Vector3`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.Vector3) and [`Vector3Collection`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.Vector3collection) classes. - -![RegEx Vector3 visualizer](Vector3Visualizer.png "RegEx Vector3 visualizer") - -The extension is composed of two projects: `Vector3DebugVisualizer`, the actual extension, and `Vector3ObjectSource`, the visualizer object source library. - -## Creating the extension - -The extension project is created as described in the [tutorial document](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/get-started/create-your-first-extension). You can also reference the [debugger visualizers guide](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/debugger-visualizer/debugger-visualizers) for additional information. - -## The `Vector3` visualizer - -The next step is to create a `DebuggerVisualizerProvider` class to visualize instances of [`Vector3`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.Vector3): - -```csharp -[VisualStudioContribution] -internal class Vector3DebuggerVisualizerProvider : DebuggerVisualizerProvider -{ - ... -``` - -If the `Vector3` type were serializable by Newtonsoft.Json, the visualizer implementation would be extremely simple: - -```csharp -public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => ew("Regex Vector3 visualizer", typeof(Vector3)); - -public override async Task CreateVisualizerAsync(VisualizerTarget isualizerTarget, CancellationToken cancellationToken) -{ - var Vector3 = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, cancellationToken); - return new Vector3VisualizerUserControl(Vector3); -} -``` - -Unfortunately `Vector3` is not serializable as-is, so we need a new serializable class [`Vector3`](Vector3ObjectSource/Vector3.cs). And we will need to create a visualizer object source library to convert the `Vector3` into a serializable `Vector3`, more about this in [a later paragraph](#the-visualizer-object-source). For now, let's just update the `RequestDataAsync` call to use `Vector3`: - -```csharp -var Vector3 = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, cancellationToken); -``` - -### Adding the remote user control - -We now have to create the `Vector3VisualizerUserControl` [class](./Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.cs) and its associated [XAML file](./Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.xaml). This process is described in the [Remote UI documentation](https://learn.microsoft.com/visualstudio/extensibility/visualstudio.extensibility/inside-the-sdk/remote-ui). - -Every time we create a remote user control like `Vector3VisualizerUserControl` we need to configure the corresponding XAML file as embedded resource. In this case, since the XAML file is in a subfolder, we also need to use `LogicalName` to make sure the name of the resource Vector3es the full name of the remote user control class. This is all done in the `.csproj` file: - -```xml - - - - -``` - -## The visualizer object source - -The visualizer object source assembly will be loaded by the debugger into the process being debugged and will take care of converting the `Vector3` object into a serializable `Vector3`. - -I will start creating a `Vector3ObjectSource` class library targeting `netstandard2.0` and adding a project reference to [Microsoft.VisualStudio.DebuggerVisualizers](https://www.nuget.org/packages/Microsoft.VisualStudio.DebuggerVisualizers) version 17.6 or newer. Targeting `netstandard2.0` will allow the debugger visualizer to easily work with a large variety of .NET versions. - -I will then create a `Vector3ObjectSource` class extending `VisualizerObjectSource` and will override the `GetData` method to convert the `target` from a `Vector3` to a `Vector3` and use the `VisualizerObjectSource.SerializeAsJson` method to write the value to the `outgoingData` stream. - -```csharp -public class Vector3ObjectSource : VisualizerObjectSource -{ - public override void GetData(object target, Stream outgoingData) - { - if (target is Vector3 Vector3) - { - Vector3 result = Convert(Vector3); - SerializeAsJson(outgoingData, result); - } - } - - ... -``` - -The `GetData` method is invoked by the debugger when the `Vector3DebuggerVisualizerProvider` calls `RequestDataAsync`. - -`SerializeAsJson` will serialize the `Vector3` object using Newtonsoft.Json, which is loaded by the debugger in the process being debugged via reflection. Since my visualizer object source doesn't need to refence Newtonsoft.Json directly, I didn't include a `PackageReference` to it, which is better since we should minimize the dependencies of the visualizer object source assembly. Because this code doesn't reference Newtonsoft.Json, the `Vector3` class uses `DataContract` and `DataMember` attributes to control serialization instead of the Newtonsoft.Json-specific types. - -My [`Vector3ObjectSource`](./Vector3ObjectSource/Vector3ObjectSource.cs) implementation contains a small trick: the [`Group.Name`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.group.name) property is read through reflection since it's available on most .NET versions but it is not included in the `netstandard2.0` APIs: - -```csharp -private static readonly Func? GetGroupName = - (Func?)typeof(Group).GetProperty("Name")?.GetGetMethod().CreateDelegate(typeof(Func)); - -... - -Name = $"[{GetGroupName?.Invoke(g) ?? i.ToString()}]" -``` - -### Referencing the visualizer object source from the extension - -First, we need to make sure that the visualizer object source library is packaged as part of the extension. We can do that in the extension's `.csproj` file: - -```xml - - - PreserveNewest - - - - - - -``` - -The `ProjectReference` guarantees that the visualizer object source library is built before the extension and the `Content` item makes sure that the visualizer object source DLL is copied into the `netstandard2.0` extension's subfolder where it will be discoverable by the debugger. - -I have decided to use `ReferenceOutputAssembly="false"` to avoid a dependency of the extension assembly from the visualizer object source one. This allows using conditional compilation (`#if`) to have slightly different definitions of [`RegexCapture`](./Vector3ObjectSource/RegexCapture.cs) in the two projects. Since I decided to avoid the dependency, I will need to: - -1. link the `Vector3.cs` file (and the related `RegexCapture` and `RegexGroup` ones) so that they are available in both projects: - -```xml - - - - - -``` - -2. Reference the `Vector3ObjectSource` from the `DebuggerVisualizerProviderConfiguration` using its assembly-qualified name: - -```csharp - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Regex Vector3 visualizer", typeof(Vector3)) - { - VisualizerObjectSourceType = new("Microsoft.VisualStudio.Gladstone.Vector3Visualizer.ObjectSource.Vector3ObjectSource, Vector3ObjectSource"), - }; -``` - -In most cases, having the extension project depend on the visualizer object source library is simpler: I could have simplified the `DebuggerVisualizerProviderConfiguration` to: - -```csharp - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Regex Vector3 visualizer", typeof(Vector3)) - { - VisualizerObjectSourceType = new(typeof(Vector3ObjectSource)), - }; -``` - -## The `Vector3Collection` visualizer - -Now that the `Vector3` visualizer is complete, we can add a second visualizer for the [`Vector3Collection`](https://learn.microsoft.com/dotnet/api/system.text.regularexpressions.Vector3collection) class. The process is exactly the same: create a new [`DebuggerVisualizerProvider`](./Vector3DebugVisualizer/Vector3Collection/Vector3CollectionDebuggerVisualizerProvider.cs) and its [remote user control](./Vector3DebugVisualizer/Vector3Collection/Vector3CollectionVisualizerUserControl.cs). Also, add a new [`VisualizerObjectSource`](./Vector3ObjectSource/Vector3CollectionObjectSource.cs) to the visualizer object source library. - -Each call to `RequestDataAsync` is allowed only 5 seconds to complete before throwing a timeout exception. Since the `Vector3Collection` could contain many entries, the visualizer object source uses the `TransferData` method instead of `GetData`: `TransferData` accepts a parameter which allows the visualizer to query the collection entries one by one: - -```csharp -public override void TransferData(object target, Stream incomingData, Stream outgoingData) -{ - var index = (int)DeserializeFromJson(incomingData, typeof(int))!; - if (target is Vector3Collection Vector3Collection && index < Vector3Collection.Count) - { - var result = Vector3ObjectSource.Convert(Vector3Collection[index]); - result.Name = $"[{index}]"; - SerializeAsJson(outgoingData, result); - } - else - { - SerializeAsJson(outgoingData, null); - } -} -``` - -Instead of using the `VisualizerTarget` directly, the `DebuggerVisualizerProvider` passes it to the remote user control so that it can asynchronously request the collection entries without delaying the display of the visualizer UI to the user. - -```csharp -public override Task CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken) -{ - return Task.FromResult(new Vector3CollectionVisualizerUserControl(visualizerTarget)); -} -``` - -The remote user control uses the `RequestDataAsync` override that takes a `message` parameter, which results in `TransferData` being invoked on the visualizer object source. The remote user control will loop, invoking `RequestDataAsync` for increasing index numbers until the visualizer object source returns `null`, which indicates the end of the collection: - -```csharp -public override Task ControlLoadedAsync(CancellationToken cancellationToken) -{ - _ = Task.Run(async () => - { - for (int i = 0; ; i++) - { - Vector3? Vector3 = await this.visualizerTarget.ObjectSource.RequestDataAsync(message: i, jsonSerializer: null, CancellationToken.None); - if (Vector3 is null) - { - break; - } - - this.Vector3es.Add(Vector3); - } - }); - - return Task.CompletedTask; -} -``` - -This is a very simple implementation of a debugger visualizer which relies on `RequestDataAsync`. More complex implementations may pass more complex parameters to `RequestDataAsync` in order to retrieve different information from the visualizer object source. You could even invoke `RequestDataAsync` in response to the user's interactions with the remote user control, allowing the user to "explore" the content of, potentially very large, objects. diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/.vsextension/string-resources.json b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/.vsextension/string-resources.json deleted file mode 100644 index 75bf520..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/.vsextension/string-resources.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Vector3Visualizer.Vector3DebuggerVisualizerProvider.DisplayName": "Vector3 visualizer" -} \ No newline at end of file diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3DebuggerVisualizerProvider.cs b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3DebuggerVisualizerProvider.cs deleted file mode 100644 index 7c6aef3..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3DebuggerVisualizerProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Vector3Visualizer; - -using System.Numerics; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.Extensibility; -using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers; -using Microsoft.VisualStudio.RpcContracts.RemoteUI; - - -/// -/// Debugger visualizer provider class for . -/// -[VisualStudioContribution] -internal sealed class Vector3DebuggerVisualizerProvider : DebuggerVisualizerProvider -{ - /// - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("%Vector3Visualizer.Vector3DebuggerVisualizerProvider.DisplayName%", typeof(Vector3)) - { - VisualizerObjectSourceType = new("Vector3Visualizer.ObjectSource.Vector3ObjectSource, Vector3ObjectSource"), - Style = VisualizerStyle.ToolWindow, - }; - - /// - public override async Task CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken) - { - var Vector3 = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, cancellationToken); - - return new Vector3VisualizerUserControl(Vector3); - } -} diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.cs b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.cs deleted file mode 100644 index 9ede3e8..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Numerics; -using Microsoft.VisualStudio.Extensibility.UI; - -namespace Vector3Visualizer; - - -/// -/// Remote user control to visualize the value. -/// -internal sealed class Vector3VisualizerUserControl : RemoteUserControl -{ - /// - /// Initializes a new instance of the class. - /// - /// Data context of the remote control. - public Vector3VisualizerUserControl(Vector3 dataContext) - : base(dataContext) - { - } -} diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.xaml b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.xaml deleted file mode 100644 index a1ccbb4..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3/Vector3VisualizerUserControl.xaml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer.csproj b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer.csproj deleted file mode 100644 index c1d4836..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net8.0-windows8.0 - enable - latest - Vector3Visualizer - $(DefineConstants);VISUALIZER - - - - - - - - - - - - - - - - - diff --git a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3VisualizerExtension.cs b/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3VisualizerExtension.cs deleted file mode 100644 index d6abc50..0000000 --- a/NrxDebugVisualizer/Vector3DebugVisualizer/Vector3DebugVisualizer/Vector3VisualizerExtension.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Vector3Visualizer; - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.VisualStudio.Extensibility; - -/// -/// Extension entry point for the Vector3Visualizer sample extension. -/// -[VisualStudioContribution] -internal sealed class Vector3VisualizerExtension : Extension -{ - /// - public override ExtensionConfiguration ExtensionConfiguration => new() - { - Metadata = new( - id: "Vector3Visualizer.29d15448-6b97-42e5-97c7-bb12ded13b89", - version: this.ExtensionAssemblyVersion, - publisherName: "Microsoft", - displayName: "Vector3 Debugger Visualizer", - description: "A debugger visualizer for Vector3"), - }; - - /// - protected override void InitializeServices(IServiceCollection serviceCollection) - { - base.InitializeServices(serviceCollection); - - } -} diff --git a/Vector3Visualizer/Vector3Visualizer/Vector3DebuggerVisualizerProvider.cs b/Vector3Visualizer/Vector3Visualizer/Vector3DebuggerVisualizerProvider.cs deleted file mode 100644 index fcbd97b..0000000 --- a/Vector3Visualizer/Vector3Visualizer/Vector3DebuggerVisualizerProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.VisualStudio.Extensibility; -using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers; -using Microsoft.VisualStudio.RpcContracts.RemoteUI; -using System.Collections.Generic; -using System.Numerics; -using System.Threading; -using System.Threading.Tasks; -using Vector3VisualizerSource; -namespace Vector3Visualizer; - -[VisualStudioContribution] -internal class Vector3DebuggerVisualizerProvider : DebuggerVisualizerProvider -{ - [System.Diagnostics.CodeAnalysis.SuppressMessage("ConstantExpressionEvaluator", "CEE0027:String not localized", Justification = "")] - public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new( - [ - new VisualizerTargetType("Vector3 Visualizer", "System.Numerics.Vector3, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"), - new VisualizerTargetType("Vector3[] Visualizer", typeof(Vector3[])), - new VisualizerTargetType("List Visualizer", typeof(List<>)), - new VisualizerTargetType("Quaternion Visualizer", typeof(Quaternion)) - ]) - { - VisualizerObjectSourceType = new VisualizerObjectSourceType(typeof(Vector3ObjectSource)), - Style = VisualizerStyle.ToolWindow, - }; - - public override async Task CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken) - { - Vector3Model? model = await visualizerTarget.ObjectSource.RequestDataAsync(jsonSerializer: null, CancellationToken.None); - return await Task.FromResult(new Vector3VisualizerUserControl(model)); - //return await Task.FromResult(new MyRemoteUserControl(model)); - } -} diff --git a/Vector3Visualizer/Vector3Visualizer/Vector3Visualizer.csproj b/Vector3Visualizer/Vector3Visualizer/Vector3Visualizer.csproj deleted file mode 100644 index 5fa8deb..0000000 --- a/Vector3Visualizer/Vector3Visualizer/Vector3Visualizer.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - net8.0-windows8.0 - enable - 12 - en-US - - - - - - - - - - - - - - - - - - - diff --git a/Vector3Visualizer/Vector3VisualizerSource/Vector3VisualizerSource.csproj b/Vector3Visualizer/Vector3VisualizerSource/Vector3VisualizerSource.csproj deleted file mode 100644 index cdb7014..0000000 --- a/Vector3Visualizer/Vector3VisualizerSource/Vector3VisualizerSource.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - netstandard2.0 - enable - 12 - - - - - - - -