Add [DebuggerDisplay] to Json types (dotnet/corefx#38275)
authorJeremy Kuhne <jkuhne@microsoft.com>
Thu, 13 Jun 2019 05:58:08 +0000 (22:58 -0700)
committerAhson Khan <ahkha@microsoft.com>
Thu, 13 Jun 2019 05:58:08 +0000 (22:58 -0700)
* Add [DebuggerDisplay] to Json types

Note that there is an issue with turning the TokenType to string in Utf8JsonReader. Probably reflection related? I've been unable to create a more focused repro.

* Add some simple sanity tests

* Address some feedback.

* Use JsonValueType

Commit migrated from https://github.com/dotnet/corefx/commit/b506d4a4ff6ffe1a1877016811e2266eacc2ebbc

src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ArrayEnumerator.cs
src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ObjectEnumerator.cs
src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs
src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs
src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs
src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs
src/libraries/System.Text.Json/tests/DebuggerTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj
src/libraries/System.Text.Json/tests/TestClasses.ClassWithComplexObjects.cs

index 53dda79..2362bdd 100644 (file)
@@ -13,6 +13,7 @@ namespace System.Text.Json
         /// <summary>
         ///   An enumerable and enumerator for the contents of a JSON array.
         /// </summary>
+        [DebuggerDisplay("{Current,nq}")]
         public struct ArrayEnumerator : IEnumerable<JsonElement>, IEnumerator<JsonElement>
         {
             private readonly JsonElement _target;
index 2b6bcbe..2b2b40a 100644 (file)
@@ -13,6 +13,7 @@ namespace System.Text.Json
         /// <summary>
         ///   An enumerable and enumerator for the properties of a JSON object.
         /// </summary>
+        [DebuggerDisplay("{Current,nq}")]
         public struct ObjectEnumerator : IEnumerable<JsonProperty>, IEnumerator<JsonProperty>
         {
             private readonly JsonElement _target;
index e30ce73..fb26d2a 100644 (file)
@@ -2,18 +2,15 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System;
-using System.Buffers;
-using System.Buffers.Text;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Runtime.InteropServices;
 
 namespace System.Text.Json
 {
     /// <summary>
     ///   Represents a specific JSON value within a <see cref="JsonDocument"/>.
     /// </summary>
+    [DebuggerDisplay("{DebuggerDisplay,nq}")]
     public readonly partial struct JsonElement
     {
         private readonly JsonDocument _parent;
@@ -1286,5 +1283,7 @@ namespace System.Text.Json
                 throw new InvalidOperationException();
             }
         }
+
+        private string DebuggerDisplay => $"Type = {Type} : \"{ToString()}\"";
     }
 }
index 41900da..4b999a5 100644 (file)
@@ -3,12 +3,14 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Diagnostics;
 
 namespace System.Text.Json
 {
     /// <summary>
     ///   Represents a single property for a JSON object.
     /// </summary>
+    [DebuggerDisplay("{DebuggerDisplay,nq}")]
     public readonly struct JsonProperty
     {
         /// <summary>
@@ -99,5 +101,8 @@ namespace System.Text.Json
         {
             return Value.GetPropertyRawText();
         }
+
+        private string DebuggerDisplay
+            => Value.Type == JsonValueType.Undefined ? "<Undefined>" : $"\"{ToString()}\"";
     }
 }
index 74811ea..cae8054 100644 (file)
@@ -19,6 +19,7 @@ namespace System.Text.Json
     /// To be able to set max depth while reading OR allow skipping comments, create an instance of 
     /// <see cref="JsonReaderState"/> and pass that in to the reader.
     /// </summary>
+    [DebuggerDisplay("{DebuggerDisplay,nq}")]
     public ref partial struct Utf8JsonReader
     {
         private ReadOnlySpan<byte> _buffer;
@@ -2434,5 +2435,28 @@ namespace System.Text.Json
             _tokenType = JsonTokenType.Comment;
             return true;
         }
+
+        private string DebuggerDisplay => $"TokenType = {DebugTokenType} (TokenStartIndex = {TokenStartIndex}) Consumed = {BytesConsumed}";
+
+        // Using TokenType.ToString() (or {TokenType}) fails to render in the debug window. The
+        // message "The runtime refused to evaluate the expression at this time." is shown. This
+        // is a workaround until we root cause and fix the issue.
+        private string DebugTokenType
+            => TokenType switch
+            {
+                JsonTokenType.Comment => nameof(JsonTokenType.Comment),
+                JsonTokenType.EndArray => nameof(JsonTokenType.EndArray),
+                JsonTokenType.EndObject => nameof(JsonTokenType.EndObject),
+                JsonTokenType.False => nameof(JsonTokenType.False),
+                JsonTokenType.None => nameof(JsonTokenType.None),
+                JsonTokenType.Null => nameof(JsonTokenType.Null),
+                JsonTokenType.Number => nameof(JsonTokenType.Number),
+                JsonTokenType.PropertyName => nameof(JsonTokenType.PropertyName),
+                JsonTokenType.StartArray => nameof(JsonTokenType.StartArray),
+                JsonTokenType.StartObject => nameof(JsonTokenType.StartObject),
+                JsonTokenType.String => nameof(JsonTokenType.String),
+                JsonTokenType.True => nameof(JsonTokenType.True),
+                _ => ((byte)TokenType).ToString()
+            };
     }
 }
index 41101c7..9ac6d57 100644 (file)
@@ -30,6 +30,7 @@ namespace System.Text.Json
     /// To be able to format the output with indentation and whitespace OR to skip validation, create an instance of 
     /// <see cref="JsonWriterOptions"/> and pass that in to the writer.
     /// </remarks>
+    [DebuggerDisplay("{DebuggerDisplay,nq}")]
     public sealed partial class Utf8JsonWriter : IDisposable
 #if BUILDING_INBOX_LIBRARY
         , IAsyncDisposable
@@ -1091,5 +1092,7 @@ namespace System.Text.Json
         {
             _currentDepth |= 1 << 31;
         }
+
+        private string DebuggerDisplay => $"BytesCommitted = {BytesCommitted} BytesPending = {BytesPending} CurrentDepth = {CurrentDepth}";
     }
 }
diff --git a/src/libraries/System.Text.Json/tests/DebuggerTests.cs b/src/libraries/System.Text.Json/tests/DebuggerTests.cs
new file mode 100644 (file)
index 0000000..13a50ca
--- /dev/null
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using System.Reflection;
+using Xunit;
+
+namespace System.Text.Json.Tests
+{
+    public class DebuggerTests
+    {
+        [Fact]
+        public void DefaultJsonElement()
+        {
+            // Validating that we don't throw on default
+            JsonElement element = default;
+            GetDebuggerDisplayProperty(element);
+        }
+
+        [Fact]
+        public void DefaultJsonProperty()
+        {
+            // Validating that we don't throw on default
+            JsonProperty property = default;
+            GetDebuggerDisplayProperty(property);
+        }
+
+        [Fact]
+        public void DefaultUtf8JsonWriter()
+        {
+            // Validating that we don't throw on new object
+            Utf8JsonWriter writer = new Utf8JsonWriter(new MemoryStream());
+            GetDebuggerDisplayProperty(writer);
+        }
+
+        private static string GetDebuggerDisplayProperty<T>(T value)
+        {
+            return (string)typeof(T).GetProperty("DebuggerDisplay", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(value);
+        }
+    }
+}
index 6795834..a5388f1 100644 (file)
@@ -11,6 +11,7 @@
     <Compile Include="BitStackTests.cs" />
     <Compile Include="BufferFactory.cs" />
     <Compile Include="BufferSegment.cs" />
+    <Compile Include="DebuggerTests.cs" />
     <Compile Include="FixedSizedBufferWriter.cs" />
     <Compile Include="InvalidBufferWriter.cs" />
     <Compile Include="JsonDateTimeTestData.cs" />
index da8cc66..502905d 100644 (file)
@@ -51,7 +51,8 @@ namespace System.Text.Json.Serialization.Tests
             Assert.IsType<JsonElement>(Object);
             JsonElement jsonObject = (JsonElement)Object;
             Assert.Equal(JsonValueType.Object, jsonObject.Type);
-            JsonProperty property = jsonObject.EnumerateObject().First();
+            JsonElement.ObjectEnumerator enumerator = jsonObject.EnumerateObject();
+            JsonProperty property = enumerator.First();
             Assert.Equal("NestedArray", property.Name);
             Assert.True(property.NameEquals("NestedArray"));
             ValidateArray(property.Value);