Add OutputElementHintAttribute to control design time IntelliSense for TagHelpers.

- Decided to not have the attribute inheritable since TargetElement is not inheritable.
- Added tests to validate serialization, deserialization and construction of TagHelperDescriptors with OutputElementHints.
- Changed TagHelperUsageDescriptor to TagHelperDesignTimeDescriptor and TagHelperAttributeDesignTImeDescriptor.

#382
This commit is contained in:
N. Taylor Mullen 2015-06-23 11:54:31 -07:00
parent eda9edc41d
commit 85be731e2b
23 changed files with 476 additions and 224 deletions

View File

@ -0,0 +1,31 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
/// <summary>
/// Provides a hint of the <see cref="ITagHelper"/>'s output element.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class OutputElementHintAttribute : Attribute
{
/// <summary>
/// Instantiates a new instance of the <see cref="OutputElementHintAttribute"/> class.
/// </summary>
/// <param name="outputElement">
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </param>
public OutputElementHintAttribute([NotNull] string outputElement)
{
OutputElement = outputElement;
}
/// <summary>
/// The HTML element the <see cref="ITagHelper"/> may output.
/// </summary>
public string OutputElement { get; }
}
}

View File

@ -82,12 +82,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
IEnumerable<TargetElementAttribute> targetElementAttributes, IEnumerable<TargetElementAttribute> targetElementAttributes,
bool designTime) bool designTime)
{ {
TagHelperUsageDescriptor typeUsageDescriptor = null; TagHelperDesignTimeDescriptor typeDesignTimeDescriptor = null;
#if !DNXCORE50 #if !DNXCORE50
if (designTime) if (designTime)
{ {
typeUsageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(typeInfo.GetType()); typeDesignTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(typeInfo.GetType());
} }
#endif #endif
@ -111,7 +111,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName, assemblyName,
attributeDescriptors, attributeDescriptors,
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: typeUsageDescriptor) designTimeDescriptor: typeDesignTimeDescriptor)
}; };
} }
@ -122,7 +122,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName, assemblyName,
attributeDescriptors, attributeDescriptors,
attribute, attribute,
typeUsageDescriptor)); typeDesignTimeDescriptor));
} }
private static TagHelperDescriptor BuildTagHelperDescriptor( private static TagHelperDescriptor BuildTagHelperDescriptor(
@ -130,7 +130,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
string assemblyName, string assemblyName,
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors, IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
TargetElementAttribute targetElementAttribute, TargetElementAttribute targetElementAttribute,
TagHelperUsageDescriptor usageDescriptor) TagHelperDesignTimeDescriptor designTimeDescriptor)
{ {
var requiredAttributes = GetCommaSeparatedValues(targetElementAttribute.Attributes); var requiredAttributes = GetCommaSeparatedValues(targetElementAttribute.Attributes);
@ -140,7 +140,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName, assemblyName,
attributeDescriptors, attributeDescriptors,
requiredAttributes, requiredAttributes,
usageDescriptor); designTimeDescriptor);
} }
private static TagHelperDescriptor BuildTagHelperDescriptor( private static TagHelperDescriptor BuildTagHelperDescriptor(
@ -149,7 +149,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
string assemblyName, string assemblyName,
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors, IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
IEnumerable<string> requiredAttributes, IEnumerable<string> requiredAttributes,
TagHelperUsageDescriptor usageDescriptor) TagHelperDesignTimeDescriptor designTimeDescriptor)
{ {
return new TagHelperDescriptor( return new TagHelperDescriptor(
prefix: string.Empty, prefix: string.Empty,
@ -158,7 +158,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName: assemblyName, assemblyName: assemblyName,
attributes: attributeDescriptors, attributes: attributeDescriptors,
requiredAttributes: requiredAttributes, requiredAttributes: requiredAttributes,
usageDescriptor: usageDescriptor); designTimeDescriptor: designTimeDescriptor);
} }
/// <summary> /// <summary>
@ -462,12 +462,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
bool isIndexer, bool isIndexer,
bool designTime) bool designTime)
{ {
TagHelperUsageDescriptor propertyUsageDescriptor = null; TagHelperAttributeDesignTimeDescriptor propertyDesignTimeDescriptor = null;
#if !DNXCORE50 #if !DNXCORE50
if (designTime) if (designTime)
{ {
propertyUsageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(property); propertyDesignTimeDescriptor =
TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(property);
} }
#endif #endif
@ -476,7 +477,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
property.Name, property.Name,
typeName, typeName,
isIndexer, isIndexer,
propertyUsageDescriptor); propertyDesignTimeDescriptor);
} }
private static bool IsAccessibleProperty(PropertyInfo property) private static bool IsAccessibleProperty(PropertyInfo property)

View File

@ -154,7 +154,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
descriptor.AssemblyName, descriptor.AssemblyName,
descriptor.Attributes, descriptor.Attributes,
descriptor.RequiredAttributes, descriptor.RequiredAttributes,
descriptor.UsageDescriptor)); descriptor.DesignTimeDescriptor));
} }
return descriptors; return descriptors;

View File

@ -14,40 +14,69 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{ {
/// <summary> /// <summary>
/// Factory for providing <see cref="TagHelperUsageDescriptor"/>s from <see cref="Type"/>s and /// Factory for providing <see cref="TagHelperDesignTimeDescriptor"/>s from <see cref="Type"/>s and
/// <see cref="PropertyInfo"/>s. /// <see cref="TagHelperAttributeDesignTimeDescriptor"/>s from <see cref="PropertyInfo"/>s.
/// </summary> /// </summary>
public static class TagHelperUsageDescriptorFactory public static class TagHelperDesignTimeDescriptorFactory
{ {
/// <summary> /// <summary>
/// Creates a <see cref="TagHelperUsageDescriptor"/> from the given <paramref name="type"/>. /// Creates a <see cref="TagHelperDesignTimeDescriptor"/> from the given <paramref name="type"/>.
/// </summary> /// </summary>
/// <param name="type">The <see cref="Type"/> to create a <see cref="TagHelperUsageDescriptor"/> from.</param> /// <param name="type">
/// <returns>A <see cref="TagHelperUsageDescriptor"/> that describes the summary and remarks XML documentation /// The <see cref="Type"/> to create a <see cref="TagHelperDesignTimeDescriptor"/> from.
/// </param>
/// <returns>A <see cref="TagHelperDesignTimeDescriptor"/> that describes design time specific information
/// for the given <paramref name="type"/>.</returns> /// for the given <paramref name="type"/>.</returns>
public static TagHelperUsageDescriptor CreateDescriptor([NotNull] Type type) public static TagHelperDesignTimeDescriptor CreateDescriptor([NotNull] Type type)
{ {
var id = XmlDocumentationProvider.GetId(type); var id = XmlDocumentationProvider.GetId(type);
var documentationDescriptor = CreateDocumentationDescriptor(type.Assembly, id);
return CreateDescriptorCore(type.Assembly, id); // Purposefully not using the TypeInfo.GetCustomAttributes method here to make it easier to mock the Type.
var outputElementHintAttribute = type
.GetCustomAttributes(inherit: false)
?.OfType<OutputElementHintAttribute>()
.FirstOrDefault();
var outputElementHint = outputElementHintAttribute?.OutputElement;
if (documentationDescriptor != null || outputElementHint != null)
{
return new TagHelperDesignTimeDescriptor(
documentationDescriptor?.Summary,
documentationDescriptor?.Remarks,
outputElementHint);
}
return null;
} }
/// <summary> /// <summary>
/// Creates a <see cref="TagHelperUsageDescriptor"/> from the given <paramref name="propertyInfo"/>. /// Creates a <see cref="TagHelperAttributeDesignTimeDescriptor"/> from the given
/// <paramref name="propertyInfo"/>.
/// </summary> /// </summary>
/// <param name="propertyInfo">The <see cref="PropertyInfo"/> to create a /// <param name="propertyInfo">
/// <see cref="TagHelperUsageDescriptor"/> from.</param> /// The <see cref="PropertyInfo"/> to create a <see cref="TagHelperAttributeDesignTimeDescriptor"/> from.
/// <returns>A <see cref="TagHelperUsageDescriptor"/> that describes the summary and remarks XML documentation /// </param>
/// for the given <paramref name="propertyInfo"/>.</returns> /// <returns>A <see cref="TagHelperAttributeDesignTimeDescriptor"/> that describes design time specific
public static TagHelperUsageDescriptor CreateDescriptor([NotNull] PropertyInfo propertyInfo) /// information for the given <paramref name="propertyInfo"/>.</returns>
public static TagHelperAttributeDesignTimeDescriptor CreateAttributeDescriptor(
[NotNull] PropertyInfo propertyInfo)
{ {
var id = XmlDocumentationProvider.GetId(propertyInfo); var id = XmlDocumentationProvider.GetId(propertyInfo);
var declaringAssembly = propertyInfo.DeclaringType.Assembly; var declaringAssembly = propertyInfo.DeclaringType.Assembly;
var documentationDescriptor = CreateDocumentationDescriptor(declaringAssembly, id);
return CreateDescriptorCore(declaringAssembly, id); if (documentationDescriptor != null)
{
return new TagHelperAttributeDesignTimeDescriptor(
documentationDescriptor.Summary,
documentationDescriptor.Remarks);
}
return null;
} }
private static TagHelperUsageDescriptor CreateDescriptorCore(Assembly assembly, string id) private static DocumentationDescriptor CreateDocumentationDescriptor(Assembly assembly, string id)
{ {
var assemblyLocation = assembly.Location; var assemblyLocation = assembly.Location;
@ -77,7 +106,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
if (!string.IsNullOrEmpty(summary) || !string.IsNullOrEmpty(remarks)) if (!string.IsNullOrEmpty(summary) || !string.IsNullOrEmpty(remarks))
{ {
return new TagHelperUsageDescriptor(summary, remarks); return new DocumentationDescriptor
{
Summary = summary,
Remarks = remarks
};
} }
} }
@ -157,6 +190,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return xmlDocumentationFile; return xmlDocumentationFile;
} }
private class DocumentationDescriptor
{
public string Summary { get; set; }
public string Remarks { get; set; }
}
} }
} }
#endif #endif

View File

@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyInfo.PropertyType.FullName, propertyInfo.PropertyType.FullName,
isIndexer: false, isIndexer: false,
isStringProperty: propertyInfo.PropertyType == typeof(string), isStringProperty: propertyInfo.PropertyType == typeof(string),
usageDescriptor: null) designTimeDescriptor: null)
{ {
} }
@ -40,8 +40,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
/// If <c>true</c> this <see cref="TagHelperAttributeDescriptor"/> is used for dictionary indexer assignments. /// If <c>true</c> this <see cref="TagHelperAttributeDescriptor"/> is used for dictionary indexer assignments.
/// Otherwise this <see cref="TagHelperAttributeDescriptor"/> is used for property assignment. /// Otherwise this <see cref="TagHelperAttributeDescriptor"/> is used for property assignment.
/// </param> /// </param>
/// <param name="usageDescriptor">The <see cref="TagHelperUsageDescriptor"/> that contains information about /// <param name="designTimeDescriptor">The <see cref="TagHelperAttributeDesignTimeDescriptor"/> that contains
/// use of this attribute.</param> /// design time information about this attribute.</param>
/// <remarks> /// <remarks>
/// HTML attribute names are matched case-insensitively, regardless of <paramref name="isIndexer"/>. /// HTML attribute names are matched case-insensitively, regardless of <paramref name="isIndexer"/>.
/// </remarks> /// </remarks>
@ -50,14 +50,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
[NotNull] string propertyName, [NotNull] string propertyName,
[NotNull] string typeName, [NotNull] string typeName,
bool isIndexer, bool isIndexer,
TagHelperUsageDescriptor usageDescriptor) TagHelperAttributeDesignTimeDescriptor designTimeDescriptor)
: this( : this(
name, name,
propertyName, propertyName,
typeName, typeName,
isIndexer, isIndexer,
isStringProperty: string.Equals(typeName, typeof(string).FullName, StringComparison.Ordinal), isStringProperty: string.Equals(typeName, typeof(string).FullName, StringComparison.Ordinal),
usageDescriptor: usageDescriptor) designTimeDescriptor: designTimeDescriptor)
{ {
} }
@ -68,14 +68,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
[NotNull] string typeName, [NotNull] string typeName,
bool isIndexer, bool isIndexer,
bool isStringProperty, bool isStringProperty,
TagHelperUsageDescriptor usageDescriptor) TagHelperAttributeDesignTimeDescriptor designTimeDescriptor)
{ {
Name = name; Name = name;
PropertyName = propertyName; PropertyName = propertyName;
TypeName = typeName; TypeName = typeName;
IsIndexer = isIndexer; IsIndexer = isIndexer;
IsStringProperty = isStringProperty; IsStringProperty = isStringProperty;
UsageDescriptor = usageDescriptor; DesignTimeDescriptor = designTimeDescriptor;
} }
/// <summary> /// <summary>
@ -119,9 +119,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public string TypeName { get; } public string TypeName { get; }
/// <summary> /// <summary>
/// The <see cref="TagHelperUsageDescriptor"/> that contains information about use of this attribute. /// The <see cref="TagHelperAttributeDesignTimeDescriptor"/> that contains design time information about
/// this attribute.
/// </summary> /// </summary>
public TagHelperUsageDescriptor UsageDescriptor { get; } public TagHelperAttributeDesignTimeDescriptor DesignTimeDescriptor { get; }
/// <summary> /// <summary>
/// Determines whether HTML attribute <paramref name="name"/> matches this /// Determines whether HTML attribute <paramref name="name"/> matches this

View File

@ -6,14 +6,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
/// <summary> /// <summary>
/// A metadata class containing information about tag helper use. /// A metadata class containing information about tag helper use.
/// </summary> /// </summary>
public class TagHelperUsageDescriptor public class TagHelperAttributeDesignTimeDescriptor
{ {
/// <summary> /// <summary>
/// Instantiates a new instance of <see cref="TagHelperUsageDescriptor"/>. /// Instantiates a new instance of <see cref="TagHelperDesignTimeDescriptor"/>.
/// </summary> /// </summary>
/// <param name="summary">A summary on how to use a tag helper.</param> /// <param name="summary">A summary on how to use a tag helper.</param>
/// <param name="remarks">Remarks on how to use a tag helper.</param> /// <param name="remarks">Remarks on how to use a tag helper.</param>
public TagHelperUsageDescriptor(string summary, string remarks) public TagHelperAttributeDesignTimeDescriptor(string summary, string remarks)
{ {
Summary = summary; Summary = summary;
Remarks = remarks; Remarks = remarks;

View File

@ -60,7 +60,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
assemblyName: assemblyName, assemblyName: assemblyName,
attributes: attributes, attributes: attributes,
requiredAttributes: requiredAttributes, requiredAttributes: requiredAttributes,
usageDescriptor: null) designTimeDescriptor: null)
{ {
} }
@ -82,8 +82,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
/// <param name="requiredAttributes"> /// <param name="requiredAttributes">
/// The attribute names required for the tag helper to target the HTML tag. /// The attribute names required for the tag helper to target the HTML tag.
/// </param> /// </param>
/// <param name="usageDescriptor">The <see cref="TagHelperUsageDescriptor"/> that contains information about /// <param name="designTimeDescriptor">The <see cref="TagHelperDesignTimeDescriptor"/> that contains design
/// how to use the tag helper at design time.</param> /// time information about the tag helper.</param>
public TagHelperDescriptor( public TagHelperDescriptor(
string prefix, string prefix,
[NotNull] string tagName, [NotNull] string tagName,
@ -91,7 +91,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
[NotNull] string assemblyName, [NotNull] string assemblyName,
[NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes, [NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes,
[NotNull] IEnumerable<string> requiredAttributes, [NotNull] IEnumerable<string> requiredAttributes,
TagHelperUsageDescriptor usageDescriptor) TagHelperDesignTimeDescriptor designTimeDescriptor)
{ {
Prefix = prefix ?? string.Empty; Prefix = prefix ?? string.Empty;
TagName = tagName; TagName = tagName;
@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
AssemblyName = assemblyName; AssemblyName = assemblyName;
Attributes = new List<TagHelperAttributeDescriptor>(attributes); Attributes = new List<TagHelperAttributeDescriptor>(attributes);
RequiredAttributes = new List<string>(requiredAttributes); RequiredAttributes = new List<string>(requiredAttributes);
UsageDescriptor = usageDescriptor; DesignTimeDescriptor = designTimeDescriptor;
} }
/// <summary> /// <summary>
@ -144,9 +144,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public IReadOnlyList<string> RequiredAttributes { get; } public IReadOnlyList<string> RequiredAttributes { get; }
/// <summary> /// <summary>
/// The <see cref="TagHelperUsageDescriptor"/> that contains information about how to use the tag helper at /// The <see cref="TagHelperDesignTimeDescriptor"/> that contains design time information about this
/// design time. /// tag helper.
/// </summary> /// </summary>
public TagHelperUsageDescriptor UsageDescriptor { get; } public TagHelperDesignTimeDescriptor DesignTimeDescriptor { get; }
} }
} }

View File

@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
/// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>, /// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>,
/// <see cref="TagHelperDescriptor.AssemblyName"/>, <see cref="TagHelperDescriptor.TagName"/>, /// <see cref="TagHelperDescriptor.AssemblyName"/>, <see cref="TagHelperDescriptor.TagName"/>,
/// and <see cref="TagHelperDescriptor.RequiredAttributes"/>. Ignores /// and <see cref="TagHelperDescriptor.RequiredAttributes"/>. Ignores
/// <see cref="TagHelperDescriptor.UsageDescriptor"/> because it can be inferred directly from /// <see cref="TagHelperDescriptor.DesignTimeDescriptor"/> because it can be inferred directly from
/// <see cref="TagHelperDescriptor.TypeName"/> and <see cref="TagHelperDescriptor.AssemblyName"/>. /// <see cref="TagHelperDescriptor.TypeName"/> and <see cref="TagHelperDescriptor.AssemblyName"/>.
/// </remarks> /// </remarks>
public virtual bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY) public virtual bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)

View File

@ -0,0 +1,42 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Razor.TagHelpers
{
/// <summary>
/// A metadata class containing design time information about a tag helper.
/// </summary>
public class TagHelperDesignTimeDescriptor
{
/// <summary>
/// Instantiates a new instance of <see cref="TagHelperDesignTimeDescriptor"/>.
/// </summary>
/// <param name="summary">A summary on how to use a tag helper.</param>
/// <param name="remarks">Remarks on how to use a tag helper.</param>
/// <param name="outputElementHint">The HTML element a tag helper may output.</param>
public TagHelperDesignTimeDescriptor(string summary, string remarks, string outputElementHint)
{
Summary = summary;
Remarks = remarks;
OutputElementHint = outputElementHint;
}
/// <summary>
/// A summary of how to use a tag helper.
/// </summary>
public string Summary { get; }
/// <summary>
/// Remarks about how to use a tag helper.
/// </summary>
public string Remarks { get; }
/// <summary>
/// The HTML element a tag helper may output.
/// </summary>
/// <remarks>
/// In IDEs supporting IntelliSense, may override the HTML information provided at design time.
/// </remarks>
public string OutputElementHint { get; }
}
}

View File

@ -36,7 +36,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
StringComparer.Ordinal) && StringComparer.Ordinal) &&
descriptorX.Attributes.SequenceEqual( descriptorX.Attributes.SequenceEqual(
descriptorY.Attributes, descriptorY.Attributes,
TagHelperAttributeDescriptorComparer.Default); TagHelperAttributeDescriptorComparer.Default) &&
TagHelperDesignTimeDescriptorComparer.Default.Equals(
descriptorX.DesignTimeDescriptor,
descriptorY.DesignTimeDescriptor);
} }
public override int GetHashCode(TagHelperDescriptor descriptor) public override int GetHashCode(TagHelperDescriptor descriptor)
@ -44,7 +47,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var hashCodeCombiner = HashCodeCombiner.Start() var hashCodeCombiner = HashCodeCombiner.Start()
.Add(base.GetHashCode(descriptor)) .Add(base.GetHashCode(descriptor))
.Add(descriptor.TagName, StringComparer.Ordinal) .Add(descriptor.TagName, StringComparer.Ordinal)
.Add(descriptor.Prefix); .Add(descriptor.Prefix, StringComparer.Ordinal);
if (descriptor.DesignTimeDescriptor != null)
{
hashCodeCombiner.Add(
TagHelperDesignTimeDescriptorComparer.Default.GetHashCode(descriptor.DesignTimeDescriptor));
}
foreach (var requiredAttribute in descriptor.RequiredAttributes) foreach (var requiredAttribute in descriptor.RequiredAttributes)
{ {

View File

@ -41,6 +41,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <remarks> /// <remarks>
/// Inherits from <see cref="TagHelper"/>. /// Inherits from <see cref="TagHelper"/>.
/// </remarks> /// </remarks>
[OutputElementHint("p")]
public class DocumentedTagHelper : TagHelper public class DocumentedTagHelper : TagHelper
{ {
/// <summary> /// <summary>

View File

@ -30,9 +30,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) && string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) &&
string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) && string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) &&
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) && string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
TagHelperUsageDescriptorComparer.Default.Equals( TagHelperAttributeDesignTimeDescriptorComparer.Default.Equals(
descriptorX.UsageDescriptor, descriptorX.DesignTimeDescriptor,
descriptorY.UsageDescriptor); descriptorY.DesignTimeDescriptor);
} }
public int GetHashCode(TagHelperAttributeDescriptor descriptor) public int GetHashCode(TagHelperAttributeDescriptor descriptor)
@ -44,7 +44,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
.Add(descriptor.Name, StringComparer.Ordinal) .Add(descriptor.Name, StringComparer.Ordinal)
.Add(descriptor.PropertyName, StringComparer.Ordinal) .Add(descriptor.PropertyName, StringComparer.Ordinal)
.Add(descriptor.TypeName, StringComparer.Ordinal) .Add(descriptor.TypeName, StringComparer.Ordinal)
.Add(TagHelperUsageDescriptorComparer.Default.GetHashCode(descriptor.UsageDescriptor)) .Add(TagHelperAttributeDesignTimeDescriptorComparer.Default.GetHashCode(
descriptor.DesignTimeDescriptor))
.CombinedHash; .CombinedHash;
} }
} }

View File

@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class TagHelperAttributeDesignTimeDescriptorComparer :
IEqualityComparer<TagHelperAttributeDesignTimeDescriptor>
{
public static readonly TagHelperAttributeDesignTimeDescriptorComparer Default =
new TagHelperAttributeDesignTimeDescriptorComparer();
private TagHelperAttributeDesignTimeDescriptorComparer()
{
}
public bool Equals(
TagHelperAttributeDesignTimeDescriptor descriptorX,
TagHelperAttributeDesignTimeDescriptor descriptorY)
{
if (descriptorX == descriptorY)
{
return true;
}
return descriptorX != null &&
descriptorY != null &&
string.Equals(descriptorX.Summary, descriptorY.Summary, StringComparison.Ordinal) &&
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
}
public int GetHashCode(TagHelperAttributeDesignTimeDescriptor descriptor)
{
return HashCodeCombiner
.Start()
.Add(descriptor.Summary, StringComparer.Ordinal)
.Add(descriptor.Remarks, StringComparer.Ordinal)
.CombinedHash;
}
}
}

View File

@ -412,7 +412,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(int).FullName, typeof(int).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null) designTimeDescriptor: null)
}); });
// Act // Act
@ -533,7 +533,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(object).FullName, typeof(object).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null) designTimeDescriptor: null)
}); });
// Act // Act
@ -588,7 +588,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null) designTimeDescriptor: null)
}), }),
new TagHelperDescriptor( new TagHelperDescriptor(
"p", "p",
@ -602,7 +602,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null) designTimeDescriptor: null)
}) })
}; };
@ -935,14 +935,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeName: typeof(IDictionary<string, string>).FullName, typeName: typeof(IDictionary<string, string>).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "dictionary-property-", name: "dictionary-property-",
propertyName: nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty), propertyName: nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null), designTimeDescriptor: null),
}, },
new string[0] new string[0]
}, },
@ -956,14 +956,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeName: typeof(IDictionary<string, string>).FullName, typeName: typeof(IDictionary<string, string>).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix", name: "valid-prefix",
propertyName: nameof(SingleValidHtmlAttributePrefix.DictionaryProperty), propertyName: nameof(SingleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null), designTimeDescriptor: null),
}, },
new string[0] new string[0]
}, },
@ -977,77 +977,77 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeName: typeof(Dictionary<string, object>).FullName, typeName: typeof(Dictionary<string, object>).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-name2", name: "valid-name2",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
typeName: typeof(DictionarySubclass).FullName, typeName: typeof(DictionarySubclass).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-name3", name: "valid-name3",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
typeName: typeof(DictionaryWithoutParameterlessConstructor).FullName, typeName: typeof(DictionaryWithoutParameterlessConstructor).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-name4", name: "valid-name4",
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
typeName: typeof(GenericDictionarySubclass<object>).FullName, typeName: typeof(GenericDictionarySubclass<object>).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-name5", name: "valid-name5",
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
typeName: typeof(SortedDictionary<string, int>).FullName, typeName: typeof(SortedDictionary<string, int>).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-name6", name: "valid-name6",
propertyName: nameof(MultipleValidHtmlAttributePrefix.StringProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.StringProperty),
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix1-", name: "valid-prefix1-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(object).FullName, typeName: typeof(object).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix2-", name: "valid-prefix2-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix3-", name: "valid-prefix3-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: true, isStringProperty: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix4-", name: "valid-prefix4-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
typeName: typeof(object).FullName, typeName: typeof(object).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "valid-prefix5-", name: "valid-prefix5-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty), propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
typeName: typeof(int).FullName, typeName: typeof(int).FullName,
isIndexer: true, isIndexer: true,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
new string[0] new string[0]
}, },
@ -1071,7 +1071,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeName: typeof(long).FullName, typeName: typeof(long).FullName,
isIndexer: false, isIndexer: false,
isStringProperty: false, isStringProperty: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
new[] new[]
{ {
@ -1156,7 +1156,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: "ValidProperty", propertyName: "ValidProperty",
typeName: "PropertyType", typeName: "PropertyType",
isIndexer: false, isIndexer: false,
usageDescriptor: null); designTimeDescriptor: null);
var errorSink = new ErrorSink(); var errorSink = new ErrorSink();
// Act // Act
@ -1180,7 +1180,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: "ValidProperty", propertyName: "ValidProperty",
typeName: "PropertyType", typeName: "PropertyType",
isIndexer: true, isIndexer: true,
usageDescriptor: null); designTimeDescriptor: null);
var errorSink = new ErrorSink(); var errorSink = new ErrorSink();
// Act // Act
@ -1226,7 +1226,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: "InvalidProperty", propertyName: "InvalidProperty",
typeName: "PropertyType", typeName: "PropertyType",
isIndexer: false, isIndexer: false,
usageDescriptor: null); designTimeDescriptor: null);
var errorSink = new ErrorSink(); var errorSink = new ErrorSink();
// Act // Act
@ -1280,7 +1280,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: "InvalidProperty", propertyName: "InvalidProperty",
typeName: "ValuesType", typeName: "ValuesType",
isIndexer: true, isIndexer: true,
usageDescriptor: null); designTimeDescriptor: null);
var errorSink = new ErrorSink(); var errorSink = new ErrorSink();
// Act // Act

View File

@ -1369,7 +1369,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName, assemblyName,
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
} }
private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix) private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix)

View File

@ -8,15 +8,16 @@ using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{ {
public class TagHelperUsageDescriptorComparer : IEqualityComparer<TagHelperUsageDescriptor> public class TagHelperDesignTimeDescriptorComparer : IEqualityComparer<TagHelperDesignTimeDescriptor>
{ {
public static readonly TagHelperUsageDescriptorComparer Default = new TagHelperUsageDescriptorComparer(); public static readonly TagHelperDesignTimeDescriptorComparer Default =
new TagHelperDesignTimeDescriptorComparer();
private TagHelperUsageDescriptorComparer() private TagHelperDesignTimeDescriptorComparer()
{ {
} }
public bool Equals(TagHelperUsageDescriptor descriptorX, TagHelperUsageDescriptor descriptorY) public bool Equals(TagHelperDesignTimeDescriptor descriptorX, TagHelperDesignTimeDescriptor descriptorY)
{ {
if (descriptorX == descriptorY) if (descriptorX == descriptorY)
{ {
@ -29,7 +30,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal); string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
} }
public int GetHashCode(TagHelperUsageDescriptor descriptor) public int GetHashCode(TagHelperDesignTimeDescriptor descriptor)
{ {
return HashCodeCombiner return HashCodeCombiner
.Start() .Start()

View File

@ -12,7 +12,7 @@ using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{ {
public class TagHelperUsageDescriptorFactoryTest public class TagHelperDesignTimeDescriptorFactoryTest
{ {
private const string TypeSummary = "The summary for <see cref=\"T:Microsoft.AspNet.Razor.Runtime." + private const string TypeSummary = "The summary for <see cref=\"T:Microsoft.AspNet.Razor.Runtime." +
"TagHelpers.DocumentedTagHelper\" />."; "TagHelpers.DocumentedTagHelper\" />.";
@ -40,6 +40,45 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
"file:" + new string(Path.DirectorySeparatorChar, 3) + "file:" + new string(Path.DirectorySeparatorChar, 3) +
DocumentedAssemblyLocation.TrimStart(Path.DirectorySeparatorChar); DocumentedAssemblyLocation.TrimStart(Path.DirectorySeparatorChar);
public static TheoryData OutputElementHintData
{
get
{
// tagHelperType, expectedDescriptor
return new TheoryData<Type, TagHelperDesignTimeDescriptor>
{
{ typeof(InheritedOutputElementHintTagHelper), null },
{
typeof(OutputElementHintTagHelper),
new TagHelperDesignTimeDescriptor(
summary: null,
remarks: null,
outputElementHint: "hinted-value")
},
{
typeof(OverriddenOutputElementHintTagHelper),
new TagHelperDesignTimeDescriptor(
summary: null,
remarks: null,
outputElementHint: "overridden")
},
};
}
}
[Theory]
[MemberData(nameof(OutputElementHintData))]
public void CreateDescriptor_CapturesOutputElementHint(
Type tagHelperType,
TagHelperDesignTimeDescriptor expectedDescriptor)
{
// Act
var descriptors = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
// Assert
Assert.Equal(expectedDescriptor, descriptors, TagHelperDesignTimeDescriptorComparer.Default);
}
public static TheoryData CreateDescriptor_TypeDocumentationData public static TheoryData CreateDescriptor_TypeDocumentationData
{ {
get get
@ -50,28 +89,35 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var nonExistentCodeBase = defaultCodeBase.Replace("TestFiles", "TestFile"); var nonExistentCodeBase = defaultCodeBase.Replace("TestFiles", "TestFile");
var invalidLocation = defaultLocation + '\0'; var invalidLocation = defaultLocation + '\0';
var invalidCodeBase = defaultCodeBase + '\0'; var invalidCodeBase = defaultCodeBase + '\0';
var onlyHint = new TagHelperDesignTimeDescriptor(
summary: null,
remarks: null,
outputElementHint: "p");
// tagHelperType, expectedUsageDescriptor // tagHelperType, expectedDesignTimeDescriptor
return new TheoryData<Type, TagHelperUsageDescriptor> return new TheoryData<Type, TagHelperDesignTimeDescriptor>
{ {
{ CreateDocumentationTagHelperType(location: null, codeBase: null), null }, { CreateDocumentationTagHelperType(location: null, codeBase: null), onlyHint },
{ {
CreateDocumentationTagHelperType(defaultLocation, codeBase: null), CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks) new TagHelperDesignTimeDescriptor(
TypeSummary,
TypeRemarks,
outputElementHint: "p")
}, },
{ {
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase), CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks) new TagHelperDesignTimeDescriptor(TypeSummary, TypeRemarks, outputElementHint: "p")
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase), CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks) new TagHelperDesignTimeDescriptor(TypeSummary, TypeRemarks, outputElementHint: "p")
}, },
{ CreateType<SingleAttributeTagHelper>(defaultLocation, defaultCodeBase), null }, { CreateType<SingleAttributeTagHelper>(defaultLocation, defaultCodeBase), null },
{ CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null), null }, { CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null), onlyHint },
{ CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase), null }, { CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase), onlyHint },
{ CreateType<SingleAttributeTagHelper>(invalidLocation, codeBase: null), null }, { CreateType<SingleAttributeTagHelper>(invalidLocation, codeBase: null), null },
{ CreateDocumentationTagHelperType(location: null, codeBase: invalidCodeBase), null }, { CreateDocumentationTagHelperType(location: null, codeBase: invalidCodeBase), onlyHint },
}; };
} }
} }
@ -80,55 +126,60 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
[MemberData(nameof(CreateDescriptor_TypeDocumentationData))] [MemberData(nameof(CreateDescriptor_TypeDocumentationData))]
public void CreateDescriptor_WithType_ReturnsExpectedDescriptors( public void CreateDescriptor_WithType_ReturnsExpectedDescriptors(
Type tagHelperType, Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor) TagHelperDesignTimeDescriptor expectedDesignTimeDescriptor)
{ {
// Act // Act
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType); var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
// Assert // Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default); Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
} }
public static TheoryData CreateDescriptor_LocalizedTypeDocumentationData public static TheoryData CreateDescriptor_LocalizedTypeDocumentationData
{ {
get get
{ {
// tagHelperType, expectedUsageDescriptor, culture // tagHelperType, expectedDesignTimeDescriptor, culture
return new TheoryData<Type, TagHelperUsageDescriptor, string> return new TheoryData<Type, TagHelperDesignTimeDescriptor, string>
{ {
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperDesignTimeDescriptor(
summary: "en-GB: " + TypeSummary, summary: "en-GB: " + TypeSummary,
remarks: "en-GB: " + TypeRemarks), remarks: "en-GB: " + TypeRemarks,
outputElementHint: "p"),
"en-GB" "en-GB"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperDesignTimeDescriptor(
summary: "en: " + TypeSummary, summary: "en: " + TypeSummary,
remarks: "en: " + TypeRemarks), remarks: "en: " + TypeRemarks,
outputElementHint: "p"),
"en-US" "en-US"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperDesignTimeDescriptor(
summary: "fr-FR: " + TypeSummary, summary: "fr-FR: " + TypeSummary,
remarks: "fr-FR: " + TypeRemarks), remarks: "fr-FR: " + TypeRemarks,
outputElementHint: "p"),
"fr-FR" "fr-FR"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperDesignTimeDescriptor(
summary: "fr: " + TypeSummary, summary: "fr: " + TypeSummary,
remarks: "fr: " + TypeRemarks), remarks: "fr: " + TypeRemarks,
outputElementHint: "p"),
"fr-BE" "fr-BE"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperDesignTimeDescriptor(
summary: "nl-BE: " + TypeSummary, summary: "nl-BE: " + TypeSummary,
remarks: "nl-BE: " + TypeRemarks), remarks: "nl-BE: " + TypeRemarks,
outputElementHint: "p"),
"nl-BE" "nl-BE"
} }
}; };
@ -139,23 +190,23 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
[MemberData(nameof(CreateDescriptor_LocalizedTypeDocumentationData))] [MemberData(nameof(CreateDescriptor_LocalizedTypeDocumentationData))]
public void CreateDescriptor_WithLocalizedType_ReturnsExpectedDescriptors( public void CreateDescriptor_WithLocalizedType_ReturnsExpectedDescriptors(
Type tagHelperType, Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor, TagHelperDesignTimeDescriptor expectedDesignTimeDescriptor,
string culture) string culture)
{ {
// Arrange // Arrange
TagHelperUsageDescriptor usageDescriptor; TagHelperDesignTimeDescriptor designTimeDescriptor;
// Act // Act
using (new CultureReplacer(culture)) using (new CultureReplacer(culture))
{ {
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType); designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
} }
// Assert // Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default); Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
} }
public static TheoryData CreateDescriptor_PropertyDocumentationData public static TheoryData CreateAttributeDescriptor_PropertyDocumentationData
{ {
get get
{ {
@ -166,8 +217,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var invalidLocation = defaultLocation + '\0'; var invalidLocation = defaultLocation + '\0';
var invalidCodeBase = defaultCodeBase + '\0'; var invalidCodeBase = defaultCodeBase + '\0';
// tagHelperType, propertyName, expectedUsageDescriptor // tagHelperType, propertyName, expectedDesignTimeDescriptor
return new TheoryData<Type, string, TagHelperUsageDescriptor> return new TheoryData<Type, string, TagHelperAttributeDesignTimeDescriptor>
{ {
{ {
CreateDocumentationTagHelperType(location: null, codeBase: null), CreateDocumentationTagHelperType(location: null, codeBase: null),
@ -192,51 +243,51 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{ {
CreateDocumentationTagHelperType(defaultLocation, codeBase: null), CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.SummaryProperty), nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null) new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, codeBase: null), CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksProperty), nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks) new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, codeBase: null), CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty), nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
PropertyWithSummaryAndRemarks_Summary, PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks) PropertyWithSummaryAndRemarks_Remarks)
}, },
{ {
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase), CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.SummaryProperty), nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null) new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
}, },
{ {
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase), CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.RemarksProperty), nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks) new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
}, },
{ {
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase), CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty), nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
PropertyWithSummaryAndRemarks_Summary, PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks) PropertyWithSummaryAndRemarks_Remarks)
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase), CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.SummaryProperty), nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null) new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase), CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.RemarksProperty), nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks) new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
}, },
{ {
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase), CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty), nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
PropertyWithSummaryAndRemarks_Summary, PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks) PropertyWithSummaryAndRemarks_Remarks)
}, },
@ -265,11 +316,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
} }
[Theory] [Theory]
[MemberData(nameof(CreateDescriptor_PropertyDocumentationData))] [MemberData(nameof(CreateAttributeDescriptor_PropertyDocumentationData))]
public void CreateDescriptor_WithProperty_ReturnsExpectedDescriptors( public void CreateAttributeDescriptor_ReturnsExpectedDescriptors(
Type tagHelperType, Type tagHelperType,
string propertyName, string propertyName,
TagHelperUsageDescriptor expectedUsageDescriptor) TagHelperAttributeDesignTimeDescriptor expectedDesignTimeDescriptor)
{ {
// Arrange // Arrange
var mockPropertyInfo = new Mock<PropertyInfo>(); var mockPropertyInfo = new Mock<PropertyInfo>();
@ -277,50 +328,54 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
mockPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns(propertyName); mockPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns(propertyName);
// Act // Act
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object); var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
mockPropertyInfo.Object);
// Assert // Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default); Assert.Equal(
expectedDesignTimeDescriptor,
designTimeDescriptor,
TagHelperAttributeDesignTimeDescriptorComparer.Default);
} }
public static TheoryData CreateDescriptor_LocalizedPropertyData public static TheoryData CreateAttributeDescriptor_LocalizedPropertyData
{ {
get get
{ {
// tagHelperType, expectedUsageDescriptor, culture // tagHelperType, expectedDesignTimeDescriptor, culture
return new TheoryData<Type, TagHelperUsageDescriptor, string> return new TheoryData<Type, TagHelperAttributeDesignTimeDescriptor, string>
{ {
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
summary: "en-GB: " + PropertyWithSummaryAndRemarks_Summary, summary: "en-GB: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "en-GB: " + PropertyWithSummaryAndRemarks_Remarks), remarks: "en-GB: " + PropertyWithSummaryAndRemarks_Remarks),
"en-GB" "en-GB"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
summary: "en: " + PropertyWithSummaryAndRemarks_Summary, summary: "en: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "en: " + PropertyWithSummaryAndRemarks_Remarks), remarks: "en: " + PropertyWithSummaryAndRemarks_Remarks),
"en-US" "en-US"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
summary: "fr-FR: " + PropertyWithSummaryAndRemarks_Summary, summary: "fr-FR: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "fr-FR: " + PropertyWithSummaryAndRemarks_Remarks), remarks: "fr-FR: " + PropertyWithSummaryAndRemarks_Remarks),
"fr-FR" "fr-FR"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
summary: "fr: " + PropertyWithSummaryAndRemarks_Summary, summary: "fr: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "fr: " + PropertyWithSummaryAndRemarks_Remarks), remarks: "fr: " + PropertyWithSummaryAndRemarks_Remarks),
"fr-BE" "fr-BE"
}, },
{ {
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null), CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor( new TagHelperAttributeDesignTimeDescriptor(
summary: "nl-BE: " + PropertyWithSummaryAndRemarks_Summary, summary: "nl-BE: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "nl-BE: " + PropertyWithSummaryAndRemarks_Remarks), remarks: "nl-BE: " + PropertyWithSummaryAndRemarks_Remarks),
"nl-BE" "nl-BE"
@ -330,10 +385,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
} }
[Theory] [Theory]
[MemberData(nameof(CreateDescriptor_LocalizedPropertyData))] [MemberData(nameof(CreateAttributeDescriptor_LocalizedPropertyData))]
public void CreateDescriptor_WithLocalizedProperty_ReturnsExpectedDescriptors( public void CreateAttributeDescriptor_WithLocalizedProperty_ReturnsExpectedDescriptors(
Type tagHelperType, Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor, TagHelperAttributeDesignTimeDescriptor expectedDesignTimeDescriptor,
string culture) string culture)
{ {
// Arrange // Arrange
@ -342,16 +397,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
mockPropertyInfo mockPropertyInfo
.Setup(propertyInfo => propertyInfo.Name) .Setup(propertyInfo => propertyInfo.Name)
.Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty)); .Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
TagHelperUsageDescriptor usageDescriptor; TagHelperAttributeDesignTimeDescriptor designTimeDescriptor;
// Act // Act
using (new CultureReplacer(culture)) using (new CultureReplacer(culture))
{ {
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object); designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
mockPropertyInfo.Object);
} }
// Assert // Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default); Assert.Equal(
expectedDesignTimeDescriptor,
designTimeDescriptor,
TagHelperAttributeDesignTimeDescriptorComparer.Default);
} }
private static Type CreateDocumentationTagHelperType(string location, string codeBase) private static Type CreateDocumentationTagHelperType(string location, string codeBase)
@ -367,6 +426,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
mockType.Setup(type => type.Assembly).Returns(testAssembly); mockType.Setup(type => type.Assembly).Returns(testAssembly);
mockType.Setup(type => type.FullName).Returns(wrappedType.FullName); mockType.Setup(type => type.FullName).Returns(wrappedType.FullName);
mockType.Setup(type => type.DeclaringType).Returns(wrappedType.DeclaringType); mockType.Setup(type => type.DeclaringType).Returns(wrappedType.DeclaringType);
mockType
.Setup(type => type.GetCustomAttributes(false))
.Returns(wrappedType == typeof(DocumentedTagHelper) ?
new[] { new OutputElementHintAttribute("p") } :
null);
return mockType.Object; return mockType.Object;
} }
@ -383,6 +447,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
public override string CodeBase { get; } public override string CodeBase { get; }
} }
[OutputElementHint("hinted-value")]
private class OutputElementHintTagHelper : TagHelper
{
}
private class InheritedOutputElementHintTagHelper : OutputElementHintTagHelper
{
}
[OutputElementHint("overridden")]
private class OverriddenOutputElementHintTagHelper : OutputElementHintTagHelper
{
}
} }
} }
#endif #endif

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
"BoundRequiredString", "BoundRequiredString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: new[] { "catchall-unbound-required" }), requiredAttributes: new[] { "catchall-unbound-required" }),
new TagHelperDescriptor( new TagHelperDescriptor(
@ -50,13 +50,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
"BoundRequiredString", "BoundRequiredString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
"input-bound-string", "input-bound-string",
"BoundString", "BoundString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}, },
requiredAttributes: new[] { "input-bound-required-string", "input-unbound-required" }), requiredAttributes: new[] { "input-bound-required-string", "input-unbound-required" }),
}; };
@ -175,37 +175,37 @@ namespace Microsoft.AspNet.Razor.Test.Generator
propertyName: "IntProperty", propertyName: "IntProperty",
typeName: typeof(int).FullName, typeName: typeof(int).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "int-dictionary", name: "int-dictionary",
propertyName: "IntDictionaryProperty", propertyName: "IntDictionaryProperty",
typeName: typeof(IDictionary<string, int>).FullName, typeName: typeof(IDictionary<string, int>).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "string-dictionary", name: "string-dictionary",
propertyName: "StringDictionaryProperty", propertyName: "StringDictionaryProperty",
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>", typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "string-prefix-grabber", name: "string-prefix-grabber",
propertyName: "StringProperty", propertyName: "StringProperty",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "int-prefix-", name: "int-prefix-",
propertyName: "IntDictionaryProperty", propertyName: "IntDictionaryProperty",
typeName: typeof(int).FullName, typeName: typeof(int).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "string-prefix-", name: "string-prefix-",
propertyName: "StringDictionaryProperty", propertyName: "StringDictionaryProperty",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
}), }),
new TagHelperDescriptor( new TagHelperDescriptor(
tagName: "input", tagName: "input",
@ -218,25 +218,25 @@ namespace Microsoft.AspNet.Razor.Test.Generator
propertyName: "IntDictionaryProperty", propertyName: "IntDictionaryProperty",
typeName: typeof(IDictionary<string, int>).FullName, typeName: typeof(IDictionary<string, int>).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "string-dictionary", name: "string-dictionary",
propertyName: "StringDictionaryProperty", propertyName: "StringDictionaryProperty",
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>", typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "int-prefix-", name: "int-prefix-",
propertyName: "IntDictionaryProperty", propertyName: "IntDictionaryProperty",
typeName: typeof(int).FullName, typeName: typeof(int).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "string-prefix-", name: "string-prefix-",
propertyName: "StringDictionaryProperty", propertyName: "StringDictionaryProperty",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
}), }),
}; };
} }
@ -1065,7 +1065,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
new TagHelperAttributeDescriptor("age", pAgePropertyInfo) new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperDescriptor( new TagHelperDescriptor(
prefix, prefix,
tagName: "input", tagName: "input",
@ -1076,7 +1076,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo) new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperDescriptor( new TagHelperDescriptor(
prefix, prefix,
tagName: "input", tagName: "input",
@ -1088,7 +1088,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo) new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null) designTimeDescriptor: null)
}; };
} }

View File

@ -771,19 +771,19 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "Age", propertyName: "Age",
typeName: typeof(int).FullName, typeName: typeof(int).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "birthday", name: "birthday",
propertyName: "BirthDay", propertyName: "BirthDay",
typeName: typeof(DateTime).FullName, typeName: typeof(DateTime).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "name", name: "name",
propertyName: "Name", propertyName: "Name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}) })
}; };
var providerContext = new TagHelperDescriptorProvider(descriptors); var providerContext = new TagHelperDescriptorProvider(descriptors);
@ -1784,13 +1784,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "Bound", propertyName: "Bound",
typeName: typeof(bool).FullName, typeName: typeof(bool).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "name", name: "name",
propertyName: "Name", propertyName: "Name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}) })
}; };
var descriptorProvider = new TagHelperDescriptorProvider(descriptors); var descriptorProvider = new TagHelperDescriptorProvider(descriptors);
@ -3280,7 +3280,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"BoundRequiredString", "BoundRequiredString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}, },
requiredAttributes: new[] { "unbound-required" }), requiredAttributes: new[] { "unbound-required" }),
new TagHelperDescriptor( new TagHelperDescriptor(
@ -3294,7 +3294,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"BoundRequiredString", "BoundRequiredString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}, },
requiredAttributes: new[] { "bound-required-string" }), requiredAttributes: new[] { "bound-required-string" }),
new TagHelperDescriptor( new TagHelperDescriptor(
@ -3308,7 +3308,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"BoundRequiredInt", "BoundRequiredInt",
typeof(int).FullName, typeof(int).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}, },
requiredAttributes: new[] { "bound-required-int" }), requiredAttributes: new[] { "bound-required-int" }),
new TagHelperDescriptor( new TagHelperDescriptor(
@ -3322,25 +3322,25 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"DictionaryOfIntProperty", "DictionaryOfIntProperty",
typeof(IDictionary<string, int>).FullName, typeof(IDictionary<string, int>).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
"string-dictionary", "string-dictionary",
"DictionaryOfStringProperty", "DictionaryOfStringProperty",
typeof(IDictionary<string, string>).FullName, typeof(IDictionary<string, string>).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
"int-prefix-", "int-prefix-",
"DictionaryOfIntProperty", "DictionaryOfIntProperty",
typeof(int).FullName, typeof(int).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
"string-prefix-", "string-prefix-",
"DictionaryOfStringProperty", "DictionaryOfStringProperty",
typeof(string).FullName, typeof(string).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>()), requiredAttributes: Enumerable.Empty<string>()),
new TagHelperDescriptor( new TagHelperDescriptor(
@ -3354,13 +3354,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"BoundRequiredString", "BoundRequiredString",
typeof(string).FullName, typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
"bound-int", "bound-int",
"BoundRequiredString", "BoundRequiredString",
typeof(int).FullName, typeof(int).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null) designTimeDescriptor: null)
}, },
requiredAttributes: Enumerable.Empty<string>()), requiredAttributes: Enumerable.Empty<string>()),
}; };

View File

@ -321,7 +321,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
assemblyName: "SomeAssembly", assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
assemblyName: "assembly name", assemblyName: "assembly name",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: new[] { "required attribute one", "required attribute two" }, requiredAttributes: new[] { "required attribute one", "required attribute two" },
usageDescriptor: new TagHelperUsageDescriptor("usage summary", "usage remarks")); designTimeDescriptor: new TagHelperDesignTimeDescriptor("usage summary", "usage remarks", "some-tag"));
var expectedSerializedDescriptor = var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," + $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
@ -32,9 +32,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperDescriptor.Attributes) }\":[]," + $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":" + $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":" +
"[\"required attribute one\",\"required attribute two\"]," + "[\"required attribute one\",\"required attribute two\"]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{"+ $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":{{"+
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," + $"\"{ nameof(TagHelperDesignTimeDescriptor.Summary) }\":\"usage summary\"," +
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}"; $"\"{ nameof(TagHelperDesignTimeDescriptor.Remarks) }\":\"usage remarks\"," +
$"\"{ nameof(TagHelperDesignTimeDescriptor.OutputElementHint) }\":\"some-tag\"}}}}";
// Act // Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor); var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -59,16 +60,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "property name", propertyName: "property name",
typeName: "property type name", typeName: "property type name",
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "attribute two", name: "attribute two",
propertyName: "property name", propertyName: "property name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
var expectedSerializedDescriptor = var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," + $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," + $"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
@ -81,15 +82,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," + $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}"; $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
// Act // Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor); var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -114,16 +115,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "property name", propertyName: "property name",
typeName: "property type name", typeName: "property type name",
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "attribute two", name: "attribute two",
propertyName: "property name", propertyName: "property name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
var expectedSerializedDescriptor = var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," + $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," + $"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
@ -136,15 +137,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," + $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}"; $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
// Act // Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor); var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -166,9 +167,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{nameof(TagHelperDescriptor.Attributes)}\":[]," + $"\"{nameof(TagHelperDescriptor.Attributes)}\":[]," +
$"\"{nameof(TagHelperDescriptor.RequiredAttributes)}\":" + $"\"{nameof(TagHelperDescriptor.RequiredAttributes)}\":" +
"[\"required attribute one\",\"required attribute two\"]," + "[\"required attribute one\",\"required attribute two\"]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{" + $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":{{" +
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," + $"\"{ nameof(TagHelperDesignTimeDescriptor.Summary) }\":\"usage summary\"," +
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}"; $"\"{ nameof(TagHelperDesignTimeDescriptor.Remarks) }\":\"usage remarks\"," +
$"\"{ nameof(TagHelperDesignTimeDescriptor.OutputElementHint) }\":\"some-tag\"}}}}";
var expectedDescriptor = new TagHelperDescriptor( var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:", prefix: "prefix:",
tagName: "tag name", tagName: "tag name",
@ -176,7 +178,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
assemblyName: "assembly name", assemblyName: "assembly name",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: new[] { "required attribute one", "required attribute two" }, requiredAttributes: new[] { "required attribute one", "required attribute two" },
usageDescriptor: new TagHelperUsageDescriptor("usage summary", "usage remarks")); designTimeDescriptor: new TagHelperDesignTimeDescriptor("usage summary", "usage remarks", "some-tag"));
// Act // Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor); var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
@ -191,9 +193,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
Assert.Empty(descriptor.Attributes); Assert.Empty(descriptor.Attributes);
Assert.Equal(expectedDescriptor.RequiredAttributes, descriptor.RequiredAttributes, StringComparer.Ordinal); Assert.Equal(expectedDescriptor.RequiredAttributes, descriptor.RequiredAttributes, StringComparer.Ordinal);
Assert.Equal( Assert.Equal(
expectedDescriptor.UsageDescriptor, expectedDescriptor.DesignTimeDescriptor,
descriptor.UsageDescriptor, descriptor.DesignTimeDescriptor,
TagHelperUsageDescriptorComparer.Default); TagHelperDesignTimeDescriptorComparer.Default);
} }
[Fact] [Fact]
@ -212,15 +214,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," + $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}"; $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
var expectedDescriptor = new TagHelperDescriptor( var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:", prefix: "prefix:",
tagName: "tag name", tagName: "tag name",
@ -233,16 +235,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "property name", propertyName: "property name",
typeName: "property type name", typeName: "property type name",
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "attribute two", name: "attribute two",
propertyName: "property name", propertyName: "property name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
// Act // Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor); var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
@ -299,15 +301,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," + $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}"; $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
var expectedDescriptor = new TagHelperDescriptor( var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:", prefix: "prefix:",
tagName: "tag name", tagName: "tag name",
@ -320,16 +322,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
propertyName: "property name", propertyName: "property name",
typeName: "property type name", typeName: "property type name",
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperAttributeDescriptor( new TagHelperAttributeDescriptor(
name: "attribute two", name: "attribute two",
propertyName: "property name", propertyName: "property name",
typeName: typeof(string).FullName, typeName: typeof(string).FullName,
isIndexer: true, isIndexer: true,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null); designTimeDescriptor: null);
// Act // Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor); var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);

View File

@ -7,15 +7,16 @@ using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.TagHelpers namespace Microsoft.AspNet.Razor.TagHelpers
{ {
public class TagHelperUsageDescriptorComparer : IEqualityComparer<TagHelperUsageDescriptor> public class TagHelperDesignTimeDescriptorComparer : IEqualityComparer<TagHelperDesignTimeDescriptor>
{ {
public static readonly TagHelperUsageDescriptorComparer Default = new TagHelperUsageDescriptorComparer(); public static readonly TagHelperDesignTimeDescriptorComparer Default =
new TagHelperDesignTimeDescriptorComparer();
private TagHelperUsageDescriptorComparer() private TagHelperDesignTimeDescriptorComparer()
{ {
} }
public bool Equals(TagHelperUsageDescriptor descriptorX, TagHelperUsageDescriptor descriptorY) public bool Equals(TagHelperDesignTimeDescriptor descriptorX, TagHelperDesignTimeDescriptor descriptorY)
{ {
if (descriptorX == descriptorY) if (descriptorX == descriptorY)
{ {
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal); string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
} }
public int GetHashCode(TagHelperUsageDescriptor descriptor) public int GetHashCode(TagHelperDesignTimeDescriptor descriptor)
{ {
return HashCodeCombiner return HashCodeCombiner
.Start() .Start()

View File

@ -911,7 +911,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
assemblyName: "SomeAssembly", assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperDescriptor( new TagHelperDescriptor(
prefix: "th:", prefix: "th:",
tagName: "myth2", tagName: "myth2",
@ -924,10 +924,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
propertyName: "Bound", propertyName: "Bound",
typeName: typeof(bool).FullName, typeName: typeof(bool).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null) designTimeDescriptor: null)
}; };
var availableDescriptorsText = new TagHelperDescriptor[] var availableDescriptorsText = new TagHelperDescriptor[]
{ {
@ -938,7 +938,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
assemblyName: "SomeAssembly", assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null), designTimeDescriptor: null),
new TagHelperDescriptor( new TagHelperDescriptor(
prefix: "PREFIX", prefix: "PREFIX",
tagName: "myth2", tagName: "myth2",
@ -951,10 +951,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
propertyName: "Bound", propertyName: "Bound",
typeName: typeof(bool).FullName, typeName: typeof(bool).FullName,
isIndexer: false, isIndexer: false,
usageDescriptor: null), designTimeDescriptor: null),
}, },
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null) designTimeDescriptor: null)
}; };
var availableDescriptorsCatchAll = new TagHelperDescriptor[] var availableDescriptorsCatchAll = new TagHelperDescriptor[]
{ {
@ -965,7 +965,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
assemblyName: "SomeAssembly", assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(), attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>(), requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null), designTimeDescriptor: null),
}; };
// documentContent, expectedOutput, availableDescriptors // documentContent, expectedOutput, availableDescriptors