Enable serialization of `TagHelperDescriptor`s.

- Added ability for TagHelpers to write their own json output.
This commit is contained in:
N. Taylor Mullen 2018-05-22 15:55:54 -07:00
parent de9c5b3909
commit 93d8a93498
2 changed files with 214 additions and 5 deletions

View File

@ -13,8 +13,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Serialization
{
public static readonly TagHelperDescriptorJsonConverter Instance = new TagHelperDescriptorJsonConverter();
public override bool CanWrite => false;
public override bool CanConvert(Type objectType)
{
return typeof(TagHelperDescriptor).IsAssignableFrom(objectType);
@ -81,9 +79,166 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Serialization
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// We should never get here because CanWrite returns false.
// We want the default serializer to handle TagHelperDescriptor serialization.
throw new NotImplementedException();
var tagHelper = (TagHelperDescriptor)value;
writer.WriteStartObject();
writer.WritePropertyName(nameof(TagHelperDescriptor.Kind));
writer.WriteValue(tagHelper.Kind);
writer.WritePropertyName(nameof(TagHelperDescriptor.Name));
writer.WriteValue(tagHelper.Name);
writer.WritePropertyName(nameof(TagHelperDescriptor.AssemblyName));
writer.WriteValue(tagHelper.AssemblyName);
writer.WritePropertyName(nameof(TagHelperDescriptor.Documentation));
writer.WriteValue(tagHelper.Documentation);
writer.WritePropertyName(nameof(TagHelperDescriptor.TagOutputHint));
writer.WriteValue(tagHelper.TagOutputHint);
writer.WritePropertyName(nameof(TagHelperDescriptor.TagMatchingRules));
writer.WriteStartArray();
foreach (var ruleDescriptor in tagHelper.TagMatchingRules)
{
WriteTagMatchingRule(writer, ruleDescriptor, serializer);
}
writer.WriteEndArray();
writer.WritePropertyName(nameof(TagHelperDescriptor.BoundAttributes));
writer.WriteStartArray();
foreach (var boundAttribute in tagHelper.BoundAttributes)
{
WriteBoundAttribute(writer, boundAttribute, serializer);
}
writer.WriteEndArray();
writer.WritePropertyName(nameof(TagHelperDescriptor.AllowedChildTags));
writer.WriteStartArray();
foreach (var allowedChildTag in tagHelper.AllowedChildTags)
{
WriteAllowedChildTags(writer, allowedChildTag, serializer);
}
writer.WriteEndArray();
writer.WritePropertyName(nameof(TagHelperDescriptor.Diagnostics));
serializer.Serialize(writer, tagHelper.Diagnostics);
writer.WritePropertyName(nameof(TagHelperDescriptor.Metadata));
WriteMetadata(writer, tagHelper.Metadata);
writer.WriteEndObject();
}
private void WriteAllowedChildTags(JsonWriter writer, AllowedChildTagDescriptor allowedChildTag, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName(nameof(AllowedChildTagDescriptor.Name));
writer.WriteValue(allowedChildTag.Name);
writer.WritePropertyName(nameof(AllowedChildTagDescriptor.DisplayName));
writer.WriteValue(allowedChildTag.DisplayName);
writer.WritePropertyName(nameof(AllowedChildTagDescriptor.Diagnostics));
serializer.Serialize(writer, allowedChildTag.Diagnostics);
writer.WriteEndObject();
}
private void WriteBoundAttribute(JsonWriter writer, BoundAttributeDescriptor boundAttribute, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Kind));
writer.WriteValue(boundAttribute.Kind);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Name));
writer.WriteValue(boundAttribute.Name);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.TypeName));
writer.WriteValue(boundAttribute.TypeName);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.IsEnum));
writer.WriteValue(boundAttribute.IsEnum);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.IndexerNamePrefix));
writer.WriteValue(boundAttribute.IndexerNamePrefix);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.IndexerTypeName));
writer.WriteValue(boundAttribute.IndexerTypeName);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Documentation));
writer.WriteValue(boundAttribute.Documentation);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Diagnostics));
serializer.Serialize(writer, boundAttribute.Diagnostics);
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Metadata));
WriteMetadata(writer, boundAttribute.Metadata);
writer.WriteEndObject();
}
private static void WriteMetadata(JsonWriter writer, IReadOnlyDictionary<string, string> metadata)
{
writer.WriteStartObject();
foreach (var kvp in metadata)
{
writer.WritePropertyName(kvp.Key);
writer.WriteValue(kvp.Value);
}
writer.WriteEndObject();
}
private void WriteTagMatchingRule(JsonWriter writer, TagMatchingRuleDescriptor ruleDescriptor, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName(nameof(TagMatchingRuleDescriptor.TagName));
writer.WriteValue(ruleDescriptor.TagName);
writer.WritePropertyName(nameof(TagMatchingRuleDescriptor.ParentTag));
writer.WriteValue(ruleDescriptor.ParentTag);
writer.WritePropertyName(nameof(TagMatchingRuleDescriptor.TagStructure));
writer.WriteValue(ruleDescriptor.TagStructure);
writer.WritePropertyName(nameof(TagMatchingRuleDescriptor.Attributes));
writer.WriteStartArray();
foreach (var requiredAttribute in ruleDescriptor.Attributes)
{
WriteRequiredAttribute(writer, requiredAttribute, serializer);
}
writer.WriteEndArray();
writer.WritePropertyName(nameof(TagMatchingRuleDescriptor.Diagnostics));
serializer.Serialize(writer, ruleDescriptor.Diagnostics);
writer.WriteEndObject();
}
private void WriteRequiredAttribute(JsonWriter writer, RequiredAttributeDescriptor requiredAttribute, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.Name));
writer.WriteValue(requiredAttribute.Name);
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.NameComparison));
writer.WriteValue(requiredAttribute.NameComparison);
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.Value));
writer.WriteValue(requiredAttribute.Value);
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.ValueComparison));
writer.WriteValue(requiredAttribute.ValueComparison);
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.Diagnostics));
serializer.Serialize(writer, requiredAttribute.Diagnostics);
writer.WriteEndObject();
}
private void ReadTagMatchingRule(TagMatchingRuleDescriptorBuilder builder, JObject rule, JsonSerializer serializer)

View File

@ -7,12 +7,66 @@ using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Xunit;
namespace Microsoft.VisualStudio.LanguageServices.Razor
{
public class TagHelperDescriptorSerializationTest
{
[Fact]
public void TagHelperDescriptor_CanReadCamelCasedData()
{
// Arrange
var expectedDescriptor = CreateTagHelperDescriptor(
kind: TagHelperConventions.DefaultKind,
tagName: "tag-name",
typeName: "type name",
assemblyName: "assembly name",
attributes: new Action<BoundAttributeDescriptorBuilder>[]
{
builder => builder
.Name("test-attribute")
.PropertyName("TestAttribute")
.TypeName("string"),
},
ruleBuilders: new Action<TagMatchingRuleDescriptorBuilder>[]
{
builder => builder
.RequireAttributeDescriptor(attribute => attribute
.Name("required-attribute-one")
.NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.PrefixMatch))
.RequireAttributeDescriptor(attribute => attribute
.Name("required-attribute-two")
.NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)
.Value("something")
.ValueComparisonMode(RequiredAttributeDescriptor.ValueComparisonMode.PrefixMatch))
.RequireParentTag("parent-name")
.RequireTagStructure(TagStructure.WithoutEndTag),
},
configureAction: builder =>
{
builder.AllowChildTag("allowed-child-one");
builder.AddMetadata("foo", "bar");
});
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter>
{
TagHelperDescriptorJsonConverter.Instance,
RazorDiagnosticJsonConverter.Instance,
}
};
var serializedDescriptor = JsonConvert.SerializeObject(expectedDescriptor, serializerSettings);
// Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor, TagHelperDescriptorJsonConverter.Instance, RazorDiagnosticJsonConverter.Instance);
// Assert
Assert.Equal(expectedDescriptor, descriptor, TagHelperDescriptorComparer.Default);
}
[Fact]
public void TagHelperDescriptor_RoundTripsProperly()
{