From 2fa8996994e39f649124a32b2fdb29345ee86272 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Fri, 3 Feb 2023 17:33:12 -0800 Subject: [PATCH] remove old object table formatters, clean up --- ...eView.cs => HtmlFormatterTests.Objects.cs} | 7 +- .../HtmlFormatterTests.Objects_TableView.cs | 299 ------------------ .../HtmlFormatter.cs | 9 - .../HtmlFormatter{T}.cs | 98 +----- 4 files changed, 8 insertions(+), 405 deletions(-) rename src/Microsoft.DotNet.Interactive.Formatting.Tests/{HtmlFormatterTests.Objects_TreeView.cs => HtmlFormatterTests.Objects.cs} (98%) delete mode 100644 src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TableView.cs diff --git a/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TreeView.cs b/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects.cs similarity index 98% rename from src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TreeView.cs rename to src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects.cs index 9f8c66859e..2de6887f35 100644 --- a/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TreeView.cs +++ b/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects.cs @@ -16,13 +16,8 @@ namespace Microsoft.DotNet.Interactive.Formatting.Tests; public partial class HtmlFormatterTests { - public class Objects_TreeView : FormatterTestBase + public class Objects : FormatterTestBase { - public Objects_TreeView() - { - HtmlFormatter.UseTreeView = true; - } - [Fact] public void Formatters_are_generated_on_the_fly_for_anonymous_types() { diff --git a/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TableView.cs b/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TableView.cs deleted file mode 100644 index b1bc7b3997..0000000000 --- a/src/Microsoft.DotNet.Interactive.Formatting.Tests/HtmlFormatterTests.Objects_TableView.cs +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Dynamic; -using System.IO; -using System.Linq; -using FluentAssertions; -using FluentAssertions.Extensions; -using Microsoft.DotNet.Interactive.Formatting.Tests.Utility; -using Xunit; - -namespace Microsoft.DotNet.Interactive.Formatting.Tests; - -public partial class HtmlFormatterTests -{ - public class Objects_TableView : FormatterTestBase - { - // FIX: (Objects_TableView) delete? - [Fact] - public void Formatters_are_generated_on_the_fly_when_HTML_mime_type_is_requested() - { - var output = new { a = 123 }.ToDisplayString(HtmlFormatter.MimeType); - - output - .RemoveStyleElement() - .Should() - .Be($"
a
{Tags.PlainTextBegin}123{Tags.PlainTextEnd}
"); - } - - [Fact] - public void Null_references_are_indicated() - { - string value = null; - - value.ToDisplayString(HtmlFormatter.MimeType).RemoveStyleElement() - .Should() - .Be($"{Tags.PlainTextBegin}<null>{Tags.PlainTextEnd}"); - } - - [Fact] - public void Formatter_puts_div_with_class_around_string() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(); - - var s = "hello".ToDisplayString(formatter).RemoveStyleElement(); - - s.Should().Be($"{Tags.PlainTextBegin}hello{Tags.PlainTextEnd}"); - } - - [Fact] - public void Formatter_expands_properties_of_ExpandoObjects() - { - dynamic expando = new ExpandoObject(); - expando.Name = "socks"; - expando.Count = 2; - - var formatter = HtmlFormatter.GetPreferredFormatterFor(); - - var output = ((object) expando).ToDisplayString(formatter).RemoveStyleElement(); - - output.Should().BeEquivalentHtmlTo($@" - - - - - - -
CountName
{Tags.PlainTextBegin}2{Tags.PlainTextEnd}socks
"); - } - - [Fact] - public void It_formats_objects_as_tables_having_properties_on_the_y_axis() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(EntityId)); - - var writer = new StringWriter(); - - var instance = new EntityId("TheEntity", "123"); - - formatter.Format(instance, writer); - - var html = writer.ToString().RemoveStyleElement(); - - html - .Should() - .BeEquivalentHtmlTo($@" - - - - - -
TypeNameId
{Tags.PlainTextBegin}TheEntity{Tags.PlainTextEnd}{Tags.PlainTextBegin}123{Tags.PlainTextEnd}
"); - } - - [Fact] - public void Formatted_objects_include_custom_styles() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(FileInfo)); - - var writer = new StringWriter(); - - var instance = new FileInfo("a.txt"); - - formatter.Format(instance, writer); - - var html = writer.ToString(); - - html.Should().Contain(Tags.DefaultStyles); - } - - [Fact] - public void It_formats_anonymous_types_as_tables_having_properties_on_the_y_axis() - { - var writer = new StringWriter(); - - var instance = new - { - PropertyA = 123, - PropertyB = "hello" - }; - - var formatter = HtmlFormatter.GetPreferredFormatterFor(instance.GetType()); - - formatter.Format(instance, writer); - - writer.ToString().RemoveStyleElement() - .Should() - .BeEquivalentHtmlTo($@" - - - -
PropertyAPropertyB
{Tags.PlainTextBegin}123{Tags.PlainTextEnd}{Tags.PlainTextBegin}hello{Tags.PlainTextEnd}
"); - } - - [Fact] - public void It_formats_tuples_as_tables_having_properties_on_the_y_axis() - { - var writer = new StringWriter(); - - var instance = (123, "hello"); - - var formatter = HtmlFormatter.GetPreferredFormatterFor(instance.GetType()); - - formatter.Format(instance, writer); - - writer.ToString().RemoveStyleElement() - .Should() - .BeEquivalentHtmlTo($@" -
Item1Item2
{Tags.PlainTextBegin}123{Tags.PlainTextEnd}{Tags.PlainTextBegin}hello{Tags.PlainTextEnd}
"); - } - - [Fact] - public void Object_properties_are_formatted_using_plain_text_formatter() - { - var writer = new StringWriter(); - - var instance = new - { - A = 123, - B = new { BA = 456 } - }; - - var formatter = HtmlFormatter.GetPreferredFormatterFor(instance.GetType()); - - formatter.Format(instance, writer); - - writer.ToString().RemoveStyleElement() - .Should() - .Match($"
AB
{Tags.PlainTextBegin}123{Tags.PlainTextEnd}{Tags.PlainTextBegin}<>f__AnonymousType*<Int32>{Environment.NewLine} BA: 456{Tags.PlainTextEnd}
"); - } - - [Fact] - public void Sequence_properties_are_formatted_using_plain_text_formatter() - { - var writer = new StringWriter(); - - var instance = new - { - PropertyA = 123, - PropertyB = Enumerable.Range(1, 3) - }; - - var formatter = HtmlFormatter.GetPreferredFormatterFor(instance.GetType()); - - formatter.Format(instance, writer); - - writer.ToString() - .Should() - .Contain($"
PropertyAPropertyB
{Tags.PlainTextBegin}123{Tags.PlainTextEnd}{Tags.PlainTextBegin}[ 1, 2, 3 ]{Tags.PlainTextEnd}
"); - } - - [Fact] - public void Collection_properties_are_formatted_using_plain_text_formatting() - { - var writer = new StringWriter(); - - var instance = new - { - PropertyA = Enumerable.Range(1, 3) - }; - - var formatter = HtmlFormatter.GetPreferredFormatterFor(instance.GetType()); - - formatter.Format(instance, writer); - - writer.ToString() - .Should() - .Contain("[ 1, 2, 3 ]"); - } - - [Fact] - public void It_displays_exceptions_thrown_by_properties_in_the_property_value_cell() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(SomePropertyThrows)); - - var writer = new StringWriter(); - - var widget = new SomePropertyThrows(); - - formatter.Format(widget, writer); - - writer.ToString() - .Should() - .Contain($"{Tags.PlainTextBegin}System.Exception"); - } - - [Fact] - public void Type_instances_do_not_have_properties_expanded() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(Type)); - - var writer = new StringWriter(); - - formatter.Format(typeof(Dummy.ClassNotInSystemNamespace), writer); - - writer.ToString() - .Should() - .Be("Dummy.ClassNotInSystemNamespace"); - } - - [Fact] - public void Type_instances_have_link_added_for_System_namespace_type() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(Type)); - - var writer = new StringWriter(); - - formatter.Format(typeof(string), writer); - - writer.ToString() - .Should() - .Be("System.String"); - } - - - [Fact] - public void Type_instances_have_link_added_for_Microsoft_namespace_type() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(Type)); - - var writer = new StringWriter(); - - formatter.Format(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException), writer); - - writer.ToString() - .Should() - .Be("Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"); - } - - - [Fact] - public void Enums_are_formatted_using_their_names() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(FileAccess)); - - var writer = new StringWriter(); - - formatter.Format(FileAccess.ReadWrite, writer); - - writer.ToString().Should().Contain("ReadWrite"); - } - - [Fact] - public void TimeSpan_is_not_destructured() - { - var formatter = HtmlFormatter.GetPreferredFormatterFor(typeof(TimeSpan)); - - var writer = new StringWriter(); - - var timespan = 25.Milliseconds(); - - formatter.Format(timespan, writer); - - writer.ToString().Should().Contain(timespan.ToString()); - } - - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter.cs b/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter.cs index 11f2c3b350..31af513ea1 100644 --- a/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter.cs +++ b/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter.cs @@ -24,17 +24,10 @@ static HtmlFormatter() void Initialize() { -#if (false) // FIX: delete - FormattersForAnyObject = new FormatterMapByType(typeof(HtmlFormatter<>), nameof(HtmlFormatter.CreateTableFormatterForAnyObject)); -#else FormattersForAnyObject = new FormatterMapByType(typeof(HtmlFormatter<>), nameof(HtmlFormatter.CreateTreeViewFormatterForAnyObject)); -#endif } } - // FIX: (HtmlFormatter.UseTreeView) delete this - public static bool UseTreeView { get; set; } - // FIX: (HtmlFormatter) this can return a formatter with the wrong MIME type public static ITypeFormatter GetPreferredFormatterFor(Type type) => Formatter.GetPreferredFormatterFor(type, MimeType); @@ -56,8 +49,6 @@ internal static void FormatAndStyleAsPlainText( { context.RequireDefaultStyles(); - // FIX: (FormatAndStyleAsPlainText) can this be refactored out to a reusable instance? - PocketView tag = div(pre(value.ToDisplayString(PlainTextFormatter.MimeType))); tag.HtmlAttributes["class"] = "dni-plaintext"; tag.WriteTo(context); diff --git a/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter{T}.cs b/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter{T}.cs index 3402250a22..7f9b0f59e3 100644 --- a/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter{T}.cs +++ b/src/Microsoft.DotNet.Interactive.Formatting/HtmlFormatter{T}.cs @@ -54,50 +54,7 @@ public override bool Format( } public override string MimeType => HtmlFormatter.MimeType; - - internal static HtmlFormatter CreateTableFormatterForAnyObject() - { - var members = typeof(T).GetMembersToFormat() - .GetMemberAccessors(); - - return new HtmlFormatter((instance, context) => BuildTable(instance, context, members)); - - static bool BuildTable(T instance, FormatContext context, MemberAccessor[] memberAccessors) - { - if (memberAccessors.Length == 0) - { - // This formatter refuses to format objects without members, and - // refused to produce nested tables, or if no members are selected - return false; - } - else - { - // Note, embeds the keys and values as arbitrary objects into the HTML content, - List headers = - memberAccessors.Select(m => (IHtmlContent)th(m.Member.Name)) - .ToList(); - - // FIX: (CreateTableFormatterForAnyObject) should this use a tree view? - IEnumerable values = - memberAccessors.Select(m => m.GetValueOrException(instance)) - .Select(v => td(div[@class: "dni-plaintext"](pre(v.ToDisplayString(PlainTextFormatter.MimeType))))); - - PocketView t = - table( - thead( - tr( - headers)), - tbody( - tr( - values))); - - t.WriteTo(context); - - return true; - } - } - } - + internal static HtmlFormatter CreateTableFormatterForAnyEnumerable() { Func getKeys = null; @@ -151,32 +108,11 @@ bool BuildTable(T source, FormatContext context, bool summarize) } var valuesByHeader = new Dictionary>(); - var headerToSortIndex = new Dictionary(); var typesAreDifferent = false; var types = new Dictionary(); foreach (var (value, index) in rowData) { - IDictionary keysAndValues; - - // FIX: (CreateTableFormatterForAnyEnumerable) -#if false - if (value is { } && - Formatter.GetPreferredFormatterFor(value.GetType(), HtmlFormatter.MimeType) is { } formatter && - formatter.Type == typeof(object)) - { - var destructurer = Destructurer.GetOrCreate(value?.GetType()); - - keysAndValues = destructurer.Destructure(value); - } - else - { - keysAndValues = NonDestructurer.Instance.Destructure(value); - } -#else - keysAndValues = NonDestructurer.Instance.Destructure(value); -#endif - if (value is not null) { var type = value.GetType(); @@ -188,22 +124,9 @@ bool BuildTable(T source, FormatContext context, bool summarize) typesAreDifferent = types.Count > 1; } - var typeIndex = value is null ? 0 : types[value.GetType()]; - - var pairIndex = 0; - - foreach (var pair in keysAndValues) - { - if (!headerToSortIndex.ContainsKey(pair.Key)) - { - headerToSortIndex.Add(pair.Key, (typeIndex, pairIndex)); - } - - valuesByHeader - .GetOrAdd(pair.Key, _ => new Dictionary()) - .Add(index, pair.Value); - pairIndex++; - } + valuesByHeader + .GetOrAdd("value", _ => new Dictionary()) + .Add(index, value); } var headers = new List(); @@ -231,15 +154,10 @@ bool BuildTable(T source, FormatContext context, bool summarize) headers.Insert(1, th(i("type"))); } - // Order the columns first by the *first* type to exhibit the - // property, then by the destructuring order within that type. - var valueKeys = - valuesByHeader.Keys - .OrderBy(x => headerToSortIndex[x]) - .ToArray(); + var valueKeys = valuesByHeader.Keys.ToArray(); headers.AddRange(valueKeys.Select(k => (IHtmlContent)th(k))); - + var rows = new List(); for (var rowIndex = 0; rowIndex < rowData.Count; rowIndex++) @@ -310,8 +228,6 @@ static bool BuildTreeView(T source, FormatContext context, MemberAccessor[] m return true; } - PocketView view = null; - HtmlTag code = new HtmlTag("code", c => { var formatter = PlainTextSummaryFormatter.GetPreferredFormatterFor(source?.GetType()); @@ -328,7 +244,7 @@ static bool BuildTreeView(T source, FormatContext context, MemberAccessor[] m attributes.AddCssClass("dni-treeview"); - view = details[attributes]( + PocketView view = details[attributes]( summary( span[@class: "dni-code-hint"](code)), div(