Enable serialization of `TagHelperDescriptor`s.
- Added ability for TagHelpers to write their own json output.
This commit is contained in:
parent
de9c5b3909
commit
93d8a93498
|
|
@ -13,8 +13,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Serialization
|
||||||
{
|
{
|
||||||
public static readonly TagHelperDescriptorJsonConverter Instance = new TagHelperDescriptorJsonConverter();
|
public static readonly TagHelperDescriptorJsonConverter Instance = new TagHelperDescriptorJsonConverter();
|
||||||
|
|
||||||
public override bool CanWrite => false;
|
|
||||||
|
|
||||||
public override bool CanConvert(Type objectType)
|
public override bool CanConvert(Type objectType)
|
||||||
{
|
{
|
||||||
return typeof(TagHelperDescriptor).IsAssignableFrom(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)
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
// We should never get here because CanWrite returns false.
|
var tagHelper = (TagHelperDescriptor)value;
|
||||||
// We want the default serializer to handle TagHelperDescriptor serialization.
|
|
||||||
throw new NotImplementedException();
|
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)
|
private void ReadTagMatchingRule(TagMatchingRuleDescriptorBuilder builder, JObject rule, JsonSerializer serializer)
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,66 @@ using Microsoft.AspNetCore.Mvc.Razor.Extensions;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.VisualStudio.LanguageServices.Razor
|
namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
{
|
{
|
||||||
public class TagHelperDescriptorSerializationTest
|
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]
|
[Fact]
|
||||||
public void TagHelperDescriptor_RoundTripsProperly()
|
public void TagHelperDescriptor_RoundTripsProperly()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue