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:
parent
eda9edc41d
commit
85be731e2b
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -82,12 +82,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
IEnumerable<TargetElementAttribute> targetElementAttributes,
|
||||
bool designTime)
|
||||
{
|
||||
TagHelperUsageDescriptor typeUsageDescriptor = null;
|
||||
TagHelperDesignTimeDescriptor typeDesignTimeDescriptor = null;
|
||||
|
||||
#if !DNXCORE50
|
||||
if (designTime)
|
||||
{
|
||||
typeUsageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(typeInfo.GetType());
|
||||
typeDesignTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(typeInfo.GetType());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
assemblyName,
|
||||
attributeDescriptors,
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: typeUsageDescriptor)
|
||||
designTimeDescriptor: typeDesignTimeDescriptor)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
assemblyName,
|
||||
attributeDescriptors,
|
||||
attribute,
|
||||
typeUsageDescriptor));
|
||||
typeDesignTimeDescriptor));
|
||||
}
|
||||
|
||||
private static TagHelperDescriptor BuildTagHelperDescriptor(
|
||||
|
|
@ -130,7 +130,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
string assemblyName,
|
||||
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
|
||||
TargetElementAttribute targetElementAttribute,
|
||||
TagHelperUsageDescriptor usageDescriptor)
|
||||
TagHelperDesignTimeDescriptor designTimeDescriptor)
|
||||
{
|
||||
var requiredAttributes = GetCommaSeparatedValues(targetElementAttribute.Attributes);
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
assemblyName,
|
||||
attributeDescriptors,
|
||||
requiredAttributes,
|
||||
usageDescriptor);
|
||||
designTimeDescriptor);
|
||||
}
|
||||
|
||||
private static TagHelperDescriptor BuildTagHelperDescriptor(
|
||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
string assemblyName,
|
||||
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
|
||||
IEnumerable<string> requiredAttributes,
|
||||
TagHelperUsageDescriptor usageDescriptor)
|
||||
TagHelperDesignTimeDescriptor designTimeDescriptor)
|
||||
{
|
||||
return new TagHelperDescriptor(
|
||||
prefix: string.Empty,
|
||||
|
|
@ -158,7 +158,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
assemblyName: assemblyName,
|
||||
attributes: attributeDescriptors,
|
||||
requiredAttributes: requiredAttributes,
|
||||
usageDescriptor: usageDescriptor);
|
||||
designTimeDescriptor: designTimeDescriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -462,12 +462,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
bool isIndexer,
|
||||
bool designTime)
|
||||
{
|
||||
TagHelperUsageDescriptor propertyUsageDescriptor = null;
|
||||
TagHelperAttributeDesignTimeDescriptor propertyDesignTimeDescriptor = null;
|
||||
|
||||
#if !DNXCORE50
|
||||
if (designTime)
|
||||
{
|
||||
propertyUsageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(property);
|
||||
propertyDesignTimeDescriptor =
|
||||
TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(property);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -476,7 +477,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
property.Name,
|
||||
typeName,
|
||||
isIndexer,
|
||||
propertyUsageDescriptor);
|
||||
propertyDesignTimeDescriptor);
|
||||
}
|
||||
|
||||
private static bool IsAccessibleProperty(PropertyInfo property)
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
descriptor.AssemblyName,
|
||||
descriptor.Attributes,
|
||||
descriptor.RequiredAttributes,
|
||||
descriptor.UsageDescriptor));
|
||||
descriptor.DesignTimeDescriptor));
|
||||
}
|
||||
|
||||
return descriptors;
|
||||
|
|
|
|||
|
|
@ -14,40 +14,69 @@ using Microsoft.Framework.Internal;
|
|||
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for providing <see cref="TagHelperUsageDescriptor"/>s from <see cref="Type"/>s and
|
||||
/// <see cref="PropertyInfo"/>s.
|
||||
/// Factory for providing <see cref="TagHelperDesignTimeDescriptor"/>s from <see cref="Type"/>s and
|
||||
/// <see cref="TagHelperAttributeDesignTimeDescriptor"/>s from <see cref="PropertyInfo"/>s.
|
||||
/// </summary>
|
||||
public static class TagHelperUsageDescriptorFactory
|
||||
public static class TagHelperDesignTimeDescriptorFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="TagHelperUsageDescriptor"/> from the given <paramref name="type"/>.
|
||||
/// Creates a <see cref="TagHelperDesignTimeDescriptor"/> from the given <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The <see cref="Type"/> to create a <see cref="TagHelperUsageDescriptor"/> from.</param>
|
||||
/// <returns>A <see cref="TagHelperUsageDescriptor"/> that describes the summary and remarks XML documentation
|
||||
/// <param name="type">
|
||||
/// 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>
|
||||
public static TagHelperUsageDescriptor CreateDescriptor([NotNull] Type type)
|
||||
public static TagHelperDesignTimeDescriptor CreateDescriptor([NotNull] Type 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>
|
||||
/// Creates a <see cref="TagHelperUsageDescriptor"/> from the given <paramref name="propertyInfo"/>.
|
||||
/// Creates a <see cref="TagHelperAttributeDesignTimeDescriptor"/> from the given
|
||||
/// <paramref name="propertyInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The <see cref="PropertyInfo"/> to create a
|
||||
/// <see cref="TagHelperUsageDescriptor"/> from.</param>
|
||||
/// <returns>A <see cref="TagHelperUsageDescriptor"/> that describes the summary and remarks XML documentation
|
||||
/// for the given <paramref name="propertyInfo"/>.</returns>
|
||||
public static TagHelperUsageDescriptor CreateDescriptor([NotNull] PropertyInfo propertyInfo)
|
||||
/// <param name="propertyInfo">
|
||||
/// The <see cref="PropertyInfo"/> to create a <see cref="TagHelperAttributeDesignTimeDescriptor"/> from.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="TagHelperAttributeDesignTimeDescriptor"/> that describes design time specific
|
||||
/// information for the given <paramref name="propertyInfo"/>.</returns>
|
||||
public static TagHelperAttributeDesignTimeDescriptor CreateAttributeDescriptor(
|
||||
[NotNull] PropertyInfo propertyInfo)
|
||||
{
|
||||
var id = XmlDocumentationProvider.GetId(propertyInfo);
|
||||
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;
|
||||
|
||||
|
|
@ -77,7 +106,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
private class DocumentationDescriptor
|
||||
{
|
||||
public string Summary { get; set; }
|
||||
public string Remarks { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyInfo.PropertyType.FullName,
|
||||
isIndexer: false,
|
||||
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.
|
||||
/// Otherwise this <see cref="TagHelperAttributeDescriptor"/> is used for property assignment.
|
||||
/// </param>
|
||||
/// <param name="usageDescriptor">The <see cref="TagHelperUsageDescriptor"/> that contains information about
|
||||
/// use of this attribute.</param>
|
||||
/// <param name="designTimeDescriptor">The <see cref="TagHelperAttributeDesignTimeDescriptor"/> that contains
|
||||
/// design time information about this attribute.</param>
|
||||
/// <remarks>
|
||||
/// HTML attribute names are matched case-insensitively, regardless of <paramref name="isIndexer"/>.
|
||||
/// </remarks>
|
||||
|
|
@ -50,14 +50,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
[NotNull] string propertyName,
|
||||
[NotNull] string typeName,
|
||||
bool isIndexer,
|
||||
TagHelperUsageDescriptor usageDescriptor)
|
||||
TagHelperAttributeDesignTimeDescriptor designTimeDescriptor)
|
||||
: this(
|
||||
name,
|
||||
propertyName,
|
||||
typeName,
|
||||
isIndexer,
|
||||
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,
|
||||
bool isIndexer,
|
||||
bool isStringProperty,
|
||||
TagHelperUsageDescriptor usageDescriptor)
|
||||
TagHelperAttributeDesignTimeDescriptor designTimeDescriptor)
|
||||
{
|
||||
Name = name;
|
||||
PropertyName = propertyName;
|
||||
TypeName = typeName;
|
||||
IsIndexer = isIndexer;
|
||||
IsStringProperty = isStringProperty;
|
||||
UsageDescriptor = usageDescriptor;
|
||||
DesignTimeDescriptor = designTimeDescriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -119,9 +119,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
public string TypeName { get; }
|
||||
|
||||
/// <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>
|
||||
public TagHelperUsageDescriptor UsageDescriptor { get; }
|
||||
public TagHelperAttributeDesignTimeDescriptor DesignTimeDescriptor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether HTML attribute <paramref name="name"/> matches this
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// <summary>
|
||||
/// A metadata class containing information about tag helper use.
|
||||
/// </summary>
|
||||
public class TagHelperUsageDescriptor
|
||||
public class TagHelperAttributeDesignTimeDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of <see cref="TagHelperUsageDescriptor"/>.
|
||||
/// 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>
|
||||
public TagHelperUsageDescriptor(string summary, string remarks)
|
||||
public TagHelperAttributeDesignTimeDescriptor(string summary, string remarks)
|
||||
{
|
||||
Summary = summary;
|
||||
Remarks = remarks;
|
||||
|
|
@ -60,7 +60,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
assemblyName: assemblyName,
|
||||
attributes: attributes,
|
||||
requiredAttributes: requiredAttributes,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -82,8 +82,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// <param name="requiredAttributes">
|
||||
/// The attribute names required for the tag helper to target the HTML tag.
|
||||
/// </param>
|
||||
/// <param name="usageDescriptor">The <see cref="TagHelperUsageDescriptor"/> that contains information about
|
||||
/// how to use the tag helper at design time.</param>
|
||||
/// <param name="designTimeDescriptor">The <see cref="TagHelperDesignTimeDescriptor"/> that contains design
|
||||
/// time information about the tag helper.</param>
|
||||
public TagHelperDescriptor(
|
||||
string prefix,
|
||||
[NotNull] string tagName,
|
||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
[NotNull] string assemblyName,
|
||||
[NotNull] IEnumerable<TagHelperAttributeDescriptor> attributes,
|
||||
[NotNull] IEnumerable<string> requiredAttributes,
|
||||
TagHelperUsageDescriptor usageDescriptor)
|
||||
TagHelperDesignTimeDescriptor designTimeDescriptor)
|
||||
{
|
||||
Prefix = prefix ?? string.Empty;
|
||||
TagName = tagName;
|
||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
AssemblyName = assemblyName;
|
||||
Attributes = new List<TagHelperAttributeDescriptor>(attributes);
|
||||
RequiredAttributes = new List<string>(requiredAttributes);
|
||||
UsageDescriptor = usageDescriptor;
|
||||
DesignTimeDescriptor = designTimeDescriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -144,9 +144,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
public IReadOnlyList<string> RequiredAttributes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TagHelperUsageDescriptor"/> that contains information about how to use the tag helper at
|
||||
/// design time.
|
||||
/// The <see cref="TagHelperDesignTimeDescriptor"/> that contains design time information about this
|
||||
/// tag helper.
|
||||
/// </summary>
|
||||
public TagHelperUsageDescriptor UsageDescriptor { get; }
|
||||
public TagHelperDesignTimeDescriptor DesignTimeDescriptor { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
/// Determines equality based on <see cref="TagHelperDescriptor.TypeName"/>,
|
||||
/// <see cref="TagHelperDescriptor.AssemblyName"/>, <see cref="TagHelperDescriptor.TagName"/>,
|
||||
/// 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"/>.
|
||||
/// </remarks>
|
||||
public virtual bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
StringComparer.Ordinal) &&
|
||||
descriptorX.Attributes.SequenceEqual(
|
||||
descriptorY.Attributes,
|
||||
TagHelperAttributeDescriptorComparer.Default);
|
||||
TagHelperAttributeDescriptorComparer.Default) &&
|
||||
TagHelperDesignTimeDescriptorComparer.Default.Equals(
|
||||
descriptorX.DesignTimeDescriptor,
|
||||
descriptorY.DesignTimeDescriptor);
|
||||
}
|
||||
|
||||
public override int GetHashCode(TagHelperDescriptor descriptor)
|
||||
|
|
@ -44,7 +47,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var hashCodeCombiner = HashCodeCombiner.Start()
|
||||
.Add(base.GetHashCode(descriptor))
|
||||
.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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
/// <remarks>
|
||||
/// Inherits from <see cref="TagHelper"/>.
|
||||
/// </remarks>
|
||||
[OutputElementHint("p")]
|
||||
public class DocumentedTagHelper : TagHelper
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) &&
|
||||
string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) &&
|
||||
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
|
||||
TagHelperUsageDescriptorComparer.Default.Equals(
|
||||
descriptorX.UsageDescriptor,
|
||||
descriptorY.UsageDescriptor);
|
||||
TagHelperAttributeDesignTimeDescriptorComparer.Default.Equals(
|
||||
descriptorX.DesignTimeDescriptor,
|
||||
descriptorY.DesignTimeDescriptor);
|
||||
}
|
||||
|
||||
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
|
||||
|
|
@ -44,7 +44,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
.Add(descriptor.Name, StringComparer.Ordinal)
|
||||
.Add(descriptor.PropertyName, StringComparer.Ordinal)
|
||||
.Add(descriptor.TypeName, StringComparer.Ordinal)
|
||||
.Add(TagHelperUsageDescriptorComparer.Default.GetHashCode(descriptor.UsageDescriptor))
|
||||
.Add(TagHelperAttributeDesignTimeDescriptorComparer.Default.GetHashCode(
|
||||
descriptor.DesignTimeDescriptor))
|
||||
.CombinedHash;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -412,7 +412,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -533,7 +533,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeof(object).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -588,7 +588,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
}),
|
||||
new TagHelperDescriptor(
|
||||
"p",
|
||||
|
|
@ -602,7 +602,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -935,14 +935,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeName: typeof(IDictionary<string, string>).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "dictionary-property-",
|
||||
propertyName: nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty),
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
new string[0]
|
||||
},
|
||||
|
|
@ -956,14 +956,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeName: typeof(IDictionary<string, string>).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix",
|
||||
propertyName: nameof(SingleValidHtmlAttributePrefix.DictionaryProperty),
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
new string[0]
|
||||
},
|
||||
|
|
@ -977,77 +977,77 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeName: typeof(Dictionary<string, object>).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-name2",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
|
||||
typeName: typeof(DictionarySubclass).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-name3",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
|
||||
typeName: typeof(DictionaryWithoutParameterlessConstructor).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-name4",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
|
||||
typeName: typeof(GenericDictionarySubclass<object>).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-name5",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
|
||||
typeName: typeof(SortedDictionary<string, int>).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-name6",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.StringProperty),
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix1-",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty),
|
||||
typeName: typeof(object).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix2-",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix3-",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix4-",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
|
||||
typeName: typeof(object).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "valid-prefix5-",
|
||||
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: true,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
new string[0]
|
||||
},
|
||||
|
|
@ -1071,7 +1071,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
typeName: typeof(long).FullName,
|
||||
isIndexer: false,
|
||||
isStringProperty: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
new[]
|
||||
{
|
||||
|
|
@ -1156,7 +1156,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName: "ValidProperty",
|
||||
typeName: "PropertyType",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var errorSink = new ErrorSink();
|
||||
|
||||
// Act
|
||||
|
|
@ -1180,7 +1180,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName: "ValidProperty",
|
||||
typeName: "PropertyType",
|
||||
isIndexer: true,
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var errorSink = new ErrorSink();
|
||||
|
||||
// Act
|
||||
|
|
@ -1226,7 +1226,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName: "InvalidProperty",
|
||||
typeName: "PropertyType",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var errorSink = new ErrorSink();
|
||||
|
||||
// Act
|
||||
|
|
@ -1280,7 +1280,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
propertyName: "InvalidProperty",
|
||||
typeName: "ValuesType",
|
||||
isIndexer: true,
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var errorSink = new ErrorSink();
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -1369,7 +1369,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
assemblyName,
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
}
|
||||
|
||||
private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix)
|
||||
|
|
|
|||
|
|
@ -8,15 +8,16 @@ using Microsoft.Internal.Web.Utils;
|
|||
|
||||
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)
|
||||
{
|
||||
|
|
@ -29,7 +30,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(TagHelperUsageDescriptor descriptor)
|
||||
public int GetHashCode(TagHelperDesignTimeDescriptor descriptor)
|
||||
{
|
||||
return HashCodeCombiner
|
||||
.Start()
|
||||
|
|
@ -12,7 +12,7 @@ using Xunit;
|
|||
|
||||
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." +
|
||||
"TagHelpers.DocumentedTagHelper\" />.";
|
||||
|
|
@ -40,6 +40,45 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
"file:" + new string(Path.DirectorySeparatorChar, 3) +
|
||||
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
|
||||
{
|
||||
get
|
||||
|
|
@ -50,28 +89,35 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var nonExistentCodeBase = defaultCodeBase.Replace("TestFiles", "TestFile");
|
||||
var invalidLocation = defaultLocation + '\0';
|
||||
var invalidCodeBase = defaultCodeBase + '\0';
|
||||
var onlyHint = new TagHelperDesignTimeDescriptor(
|
||||
summary: null,
|
||||
remarks: null,
|
||||
outputElementHint: "p");
|
||||
|
||||
// tagHelperType, expectedUsageDescriptor
|
||||
return new TheoryData<Type, TagHelperUsageDescriptor>
|
||||
// tagHelperType, expectedDesignTimeDescriptor
|
||||
return new TheoryData<Type, TagHelperDesignTimeDescriptor>
|
||||
{
|
||||
{ CreateDocumentationTagHelperType(location: null, codeBase: null), null },
|
||||
{ CreateDocumentationTagHelperType(location: null, codeBase: null), onlyHint },
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
TypeSummary,
|
||||
TypeRemarks,
|
||||
outputElementHint: "p")
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
|
||||
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
|
||||
new TagHelperDesignTimeDescriptor(TypeSummary, TypeRemarks, outputElementHint: "p")
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
|
||||
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
|
||||
new TagHelperDesignTimeDescriptor(TypeSummary, TypeRemarks, outputElementHint: "p")
|
||||
},
|
||||
{ CreateType<SingleAttributeTagHelper>(defaultLocation, defaultCodeBase), null },
|
||||
{ CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null), null },
|
||||
{ CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase), null },
|
||||
{ CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null), onlyHint },
|
||||
{ CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase), onlyHint },
|
||||
{ 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))]
|
||||
public void CreateDescriptor_WithType_ReturnsExpectedDescriptors(
|
||||
Type tagHelperType,
|
||||
TagHelperUsageDescriptor expectedUsageDescriptor)
|
||||
TagHelperDesignTimeDescriptor expectedDesignTimeDescriptor)
|
||||
{
|
||||
// Act
|
||||
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType);
|
||||
var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
|
||||
Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
public static TheoryData CreateDescriptor_LocalizedTypeDocumentationData
|
||||
{
|
||||
get
|
||||
{
|
||||
// tagHelperType, expectedUsageDescriptor, culture
|
||||
return new TheoryData<Type, TagHelperUsageDescriptor, string>
|
||||
// tagHelperType, expectedDesignTimeDescriptor, culture
|
||||
return new TheoryData<Type, TagHelperDesignTimeDescriptor, string>
|
||||
{
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
summary: "en-GB: " + TypeSummary,
|
||||
remarks: "en-GB: " + TypeRemarks),
|
||||
remarks: "en-GB: " + TypeRemarks,
|
||||
outputElementHint: "p"),
|
||||
"en-GB"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
summary: "en: " + TypeSummary,
|
||||
remarks: "en: " + TypeRemarks),
|
||||
remarks: "en: " + TypeRemarks,
|
||||
outputElementHint: "p"),
|
||||
"en-US"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
summary: "fr-FR: " + TypeSummary,
|
||||
remarks: "fr-FR: " + TypeRemarks),
|
||||
remarks: "fr-FR: " + TypeRemarks,
|
||||
outputElementHint: "p"),
|
||||
"fr-FR"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
summary: "fr: " + TypeSummary,
|
||||
remarks: "fr: " + TypeRemarks),
|
||||
remarks: "fr: " + TypeRemarks,
|
||||
outputElementHint: "p"),
|
||||
"fr-BE"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperDesignTimeDescriptor(
|
||||
summary: "nl-BE: " + TypeSummary,
|
||||
remarks: "nl-BE: " + TypeRemarks),
|
||||
remarks: "nl-BE: " + TypeRemarks,
|
||||
outputElementHint: "p"),
|
||||
"nl-BE"
|
||||
}
|
||||
};
|
||||
|
|
@ -139,23 +190,23 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
[MemberData(nameof(CreateDescriptor_LocalizedTypeDocumentationData))]
|
||||
public void CreateDescriptor_WithLocalizedType_ReturnsExpectedDescriptors(
|
||||
Type tagHelperType,
|
||||
TagHelperUsageDescriptor expectedUsageDescriptor,
|
||||
TagHelperDesignTimeDescriptor expectedDesignTimeDescriptor,
|
||||
string culture)
|
||||
{
|
||||
// Arrange
|
||||
TagHelperUsageDescriptor usageDescriptor;
|
||||
TagHelperDesignTimeDescriptor designTimeDescriptor;
|
||||
|
||||
// Act
|
||||
using (new CultureReplacer(culture))
|
||||
{
|
||||
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType);
|
||||
designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
|
||||
Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
public static TheoryData CreateDescriptor_PropertyDocumentationData
|
||||
public static TheoryData CreateAttributeDescriptor_PropertyDocumentationData
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -166,8 +217,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var invalidLocation = defaultLocation + '\0';
|
||||
var invalidCodeBase = defaultCodeBase + '\0';
|
||||
|
||||
// tagHelperType, propertyName, expectedUsageDescriptor
|
||||
return new TheoryData<Type, string, TagHelperUsageDescriptor>
|
||||
// tagHelperType, propertyName, expectedDesignTimeDescriptor
|
||||
return new TheoryData<Type, string, TagHelperAttributeDesignTimeDescriptor>
|
||||
{
|
||||
{
|
||||
CreateDocumentationTagHelperType(location: null, codeBase: null),
|
||||
|
|
@ -192,51 +243,51 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
|
||||
nameof(DocumentedTagHelper.SummaryProperty),
|
||||
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
|
||||
new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
|
||||
nameof(DocumentedTagHelper.RemarksProperty),
|
||||
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
|
||||
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
PropertyWithSummaryAndRemarks_Summary,
|
||||
PropertyWithSummaryAndRemarks_Remarks)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.SummaryProperty),
|
||||
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
|
||||
new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.RemarksProperty),
|
||||
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
PropertyWithSummaryAndRemarks_Summary,
|
||||
PropertyWithSummaryAndRemarks_Remarks)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.SummaryProperty),
|
||||
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
|
||||
new TagHelperAttributeDesignTimeDescriptor(PropertySummary, remarks: null)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.RemarksProperty),
|
||||
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
new TagHelperAttributeDesignTimeDescriptor(summary: null, remarks: PropertyRemarks)
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
|
||||
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
PropertyWithSummaryAndRemarks_Summary,
|
||||
PropertyWithSummaryAndRemarks_Remarks)
|
||||
},
|
||||
|
|
@ -265,11 +316,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(CreateDescriptor_PropertyDocumentationData))]
|
||||
public void CreateDescriptor_WithProperty_ReturnsExpectedDescriptors(
|
||||
[MemberData(nameof(CreateAttributeDescriptor_PropertyDocumentationData))]
|
||||
public void CreateAttributeDescriptor_ReturnsExpectedDescriptors(
|
||||
Type tagHelperType,
|
||||
string propertyName,
|
||||
TagHelperUsageDescriptor expectedUsageDescriptor)
|
||||
TagHelperAttributeDesignTimeDescriptor expectedDesignTimeDescriptor)
|
||||
{
|
||||
// Arrange
|
||||
var mockPropertyInfo = new Mock<PropertyInfo>();
|
||||
|
|
@ -277,50 +328,54 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
mockPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns(propertyName);
|
||||
|
||||
// Act
|
||||
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object);
|
||||
var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
|
||||
mockPropertyInfo.Object);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
|
||||
Assert.Equal(
|
||||
expectedDesignTimeDescriptor,
|
||||
designTimeDescriptor,
|
||||
TagHelperAttributeDesignTimeDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
public static TheoryData CreateDescriptor_LocalizedPropertyData
|
||||
public static TheoryData CreateAttributeDescriptor_LocalizedPropertyData
|
||||
{
|
||||
get
|
||||
{
|
||||
// tagHelperType, expectedUsageDescriptor, culture
|
||||
return new TheoryData<Type, TagHelperUsageDescriptor, string>
|
||||
// tagHelperType, expectedDesignTimeDescriptor, culture
|
||||
return new TheoryData<Type, TagHelperAttributeDesignTimeDescriptor, string>
|
||||
{
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
summary: "en-GB: " + PropertyWithSummaryAndRemarks_Summary,
|
||||
remarks: "en-GB: " + PropertyWithSummaryAndRemarks_Remarks),
|
||||
"en-GB"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
summary: "en: " + PropertyWithSummaryAndRemarks_Summary,
|
||||
remarks: "en: " + PropertyWithSummaryAndRemarks_Remarks),
|
||||
"en-US"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
summary: "fr-FR: " + PropertyWithSummaryAndRemarks_Summary,
|
||||
remarks: "fr-FR: " + PropertyWithSummaryAndRemarks_Remarks),
|
||||
"fr-FR"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
summary: "fr: " + PropertyWithSummaryAndRemarks_Summary,
|
||||
remarks: "fr: " + PropertyWithSummaryAndRemarks_Remarks),
|
||||
"fr-BE"
|
||||
},
|
||||
{
|
||||
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
|
||||
new TagHelperUsageDescriptor(
|
||||
new TagHelperAttributeDesignTimeDescriptor(
|
||||
summary: "nl-BE: " + PropertyWithSummaryAndRemarks_Summary,
|
||||
remarks: "nl-BE: " + PropertyWithSummaryAndRemarks_Remarks),
|
||||
"nl-BE"
|
||||
|
|
@ -330,10 +385,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(CreateDescriptor_LocalizedPropertyData))]
|
||||
public void CreateDescriptor_WithLocalizedProperty_ReturnsExpectedDescriptors(
|
||||
[MemberData(nameof(CreateAttributeDescriptor_LocalizedPropertyData))]
|
||||
public void CreateAttributeDescriptor_WithLocalizedProperty_ReturnsExpectedDescriptors(
|
||||
Type tagHelperType,
|
||||
TagHelperUsageDescriptor expectedUsageDescriptor,
|
||||
TagHelperAttributeDesignTimeDescriptor expectedDesignTimeDescriptor,
|
||||
string culture)
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -342,16 +397,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
mockPropertyInfo
|
||||
.Setup(propertyInfo => propertyInfo.Name)
|
||||
.Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
|
||||
TagHelperUsageDescriptor usageDescriptor;
|
||||
TagHelperAttributeDesignTimeDescriptor designTimeDescriptor;
|
||||
|
||||
// Act
|
||||
using (new CultureReplacer(culture))
|
||||
{
|
||||
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object);
|
||||
designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
|
||||
mockPropertyInfo.Object);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
|
||||
Assert.Equal(
|
||||
expectedDesignTimeDescriptor,
|
||||
designTimeDescriptor,
|
||||
TagHelperAttributeDesignTimeDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
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.FullName).Returns(wrappedType.FullName);
|
||||
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;
|
||||
}
|
||||
|
|
@ -383,6 +447,20 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
public override string CodeBase { get; }
|
||||
}
|
||||
|
||||
[OutputElementHint("hinted-value")]
|
||||
private class OutputElementHintTagHelper : TagHelper
|
||||
{
|
||||
}
|
||||
|
||||
private class InheritedOutputElementHintTagHelper : OutputElementHintTagHelper
|
||||
{
|
||||
}
|
||||
|
||||
[OutputElementHint("overridden")]
|
||||
private class OverriddenOutputElementHintTagHelper : OutputElementHintTagHelper
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
"BoundRequiredString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: new[] { "catchall-unbound-required" }),
|
||||
new TagHelperDescriptor(
|
||||
|
|
@ -50,13 +50,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
"BoundRequiredString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
"input-bound-string",
|
||||
"BoundString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
},
|
||||
requiredAttributes: new[] { "input-bound-required-string", "input-unbound-required" }),
|
||||
};
|
||||
|
|
@ -175,37 +175,37 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
propertyName: "IntProperty",
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "int-dictionary",
|
||||
propertyName: "IntDictionaryProperty",
|
||||
typeName: typeof(IDictionary<string, int>).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "string-dictionary",
|
||||
propertyName: "StringDictionaryProperty",
|
||||
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "string-prefix-grabber",
|
||||
propertyName: "StringProperty",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "int-prefix-",
|
||||
propertyName: "IntDictionaryProperty",
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "string-prefix-",
|
||||
propertyName: "StringDictionaryProperty",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
}),
|
||||
new TagHelperDescriptor(
|
||||
tagName: "input",
|
||||
|
|
@ -218,25 +218,25 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
propertyName: "IntDictionaryProperty",
|
||||
typeName: typeof(IDictionary<string, int>).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "string-dictionary",
|
||||
propertyName: "StringDictionaryProperty",
|
||||
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "int-prefix-",
|
||||
propertyName: "IntDictionaryProperty",
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "string-prefix-",
|
||||
propertyName: "StringDictionaryProperty",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
@ -1065,7 +1065,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperDescriptor(
|
||||
prefix,
|
||||
tagName: "input",
|
||||
|
|
@ -1076,7 +1076,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperDescriptor(
|
||||
prefix,
|
||||
tagName: "input",
|
||||
|
|
@ -1088,7 +1088,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -771,19 +771,19 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "Age",
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "birthday",
|
||||
propertyName: "BirthDay",
|
||||
typeName: typeof(DateTime).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "name",
|
||||
propertyName: "Name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
})
|
||||
};
|
||||
var providerContext = new TagHelperDescriptorProvider(descriptors);
|
||||
|
|
@ -1784,13 +1784,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "Bound",
|
||||
typeName: typeof(bool).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "name",
|
||||
propertyName: "Name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
};
|
||||
var descriptorProvider = new TagHelperDescriptorProvider(descriptors);
|
||||
|
|
@ -3280,7 +3280,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
"BoundRequiredString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
},
|
||||
requiredAttributes: new[] { "unbound-required" }),
|
||||
new TagHelperDescriptor(
|
||||
|
|
@ -3294,7 +3294,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
"BoundRequiredString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
},
|
||||
requiredAttributes: new[] { "bound-required-string" }),
|
||||
new TagHelperDescriptor(
|
||||
|
|
@ -3308,7 +3308,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
"BoundRequiredInt",
|
||||
typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
},
|
||||
requiredAttributes: new[] { "bound-required-int" }),
|
||||
new TagHelperDescriptor(
|
||||
|
|
@ -3322,25 +3322,25 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
"DictionaryOfIntProperty",
|
||||
typeof(IDictionary<string, int>).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
"string-dictionary",
|
||||
"DictionaryOfStringProperty",
|
||||
typeof(IDictionary<string, string>).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
"int-prefix-",
|
||||
"DictionaryOfIntProperty",
|
||||
typeof(int).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
"string-prefix-",
|
||||
"DictionaryOfStringProperty",
|
||||
typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>()),
|
||||
new TagHelperDescriptor(
|
||||
|
|
@ -3354,13 +3354,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
"BoundRequiredString",
|
||||
typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
"bound-int",
|
||||
"BoundRequiredString",
|
||||
typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>()),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
assemblyName: "SomeAssembly",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
assemblyName: "assembly name",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
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 =
|
||||
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
|
||||
|
|
@ -32,9 +32,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{ nameof(TagHelperDescriptor.Attributes) }\":[]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":" +
|
||||
"[\"required attribute one\",\"required attribute two\"]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{"+
|
||||
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," +
|
||||
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":{{"+
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.Summary) }\":\"usage summary\"," +
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.Remarks) }\":\"usage remarks\"," +
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.OutputElementHint) }\":\"some-tag\"}}}}";
|
||||
|
||||
// Act
|
||||
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
|
||||
|
|
@ -59,16 +60,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "property name",
|
||||
typeName: "property type name",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "attribute two",
|
||||
propertyName: "property name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var expectedSerializedDescriptor =
|
||||
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
|
||||
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
|
||||
|
|
@ -81,15 +82,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
|
||||
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
|
||||
|
||||
// Act
|
||||
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
|
||||
|
|
@ -114,16 +115,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "property name",
|
||||
typeName: "property type name",
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "attribute two",
|
||||
propertyName: "property name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
var expectedSerializedDescriptor =
|
||||
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
|
||||
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
|
||||
|
|
@ -136,15 +137,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
|
||||
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
|
||||
|
||||
// Act
|
||||
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
|
||||
|
|
@ -166,9 +167,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{nameof(TagHelperDescriptor.Attributes)}\":[]," +
|
||||
$"\"{nameof(TagHelperDescriptor.RequiredAttributes)}\":" +
|
||||
"[\"required attribute one\",\"required attribute two\"]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{" +
|
||||
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," +
|
||||
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":{{" +
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.Summary) }\":\"usage summary\"," +
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.Remarks) }\":\"usage remarks\"," +
|
||||
$"\"{ nameof(TagHelperDesignTimeDescriptor.OutputElementHint) }\":\"some-tag\"}}}}";
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
prefix: "prefix:",
|
||||
tagName: "tag name",
|
||||
|
|
@ -176,7 +178,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
assemblyName: "assembly name",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
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
|
||||
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
|
||||
|
|
@ -191,9 +193,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
Assert.Empty(descriptor.Attributes);
|
||||
Assert.Equal(expectedDescriptor.RequiredAttributes, descriptor.RequiredAttributes, StringComparer.Ordinal);
|
||||
Assert.Equal(
|
||||
expectedDescriptor.UsageDescriptor,
|
||||
descriptor.UsageDescriptor,
|
||||
TagHelperUsageDescriptorComparer.Default);
|
||||
expectedDescriptor.DesignTimeDescriptor,
|
||||
descriptor.DesignTimeDescriptor,
|
||||
TagHelperDesignTimeDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -212,15 +214,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
|
||||
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
prefix: "prefix:",
|
||||
tagName: "tag name",
|
||||
|
|
@ -233,16 +235,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "property name",
|
||||
typeName: "property type name",
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "attribute two",
|
||||
propertyName: "property name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
|
||||
// Act
|
||||
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
|
||||
|
|
@ -299,15 +301,15 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
|
||||
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
|
||||
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
|
||||
$"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
|
||||
var expectedDescriptor = new TagHelperDescriptor(
|
||||
prefix: "prefix:",
|
||||
tagName: "tag name",
|
||||
|
|
@ -320,16 +322,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
propertyName: "property name",
|
||||
typeName: "property type name",
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "attribute two",
|
||||
propertyName: "property name",
|
||||
typeName: typeof(string).FullName,
|
||||
isIndexer: true,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null);
|
||||
designTimeDescriptor: null);
|
||||
|
||||
// Act
|
||||
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ using Microsoft.Internal.Web.Utils;
|
|||
|
||||
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)
|
||||
{
|
||||
|
|
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode(TagHelperUsageDescriptor descriptor)
|
||||
public int GetHashCode(TagHelperDesignTimeDescriptor descriptor)
|
||||
{
|
||||
return HashCodeCombiner
|
||||
.Start()
|
||||
|
|
@ -911,7 +911,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
assemblyName: "SomeAssembly",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperDescriptor(
|
||||
prefix: "th:",
|
||||
tagName: "myth2",
|
||||
|
|
@ -924,10 +924,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
propertyName: "Bound",
|
||||
typeName: typeof(bool).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
};
|
||||
var availableDescriptorsText = new TagHelperDescriptor[]
|
||||
{
|
||||
|
|
@ -938,7 +938,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
assemblyName: "SomeAssembly",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperDescriptor(
|
||||
prefix: "PREFIX",
|
||||
tagName: "myth2",
|
||||
|
|
@ -951,10 +951,10 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
propertyName: "Bound",
|
||||
typeName: typeof(bool).FullName,
|
||||
isIndexer: false,
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
},
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null)
|
||||
designTimeDescriptor: null)
|
||||
};
|
||||
var availableDescriptorsCatchAll = new TagHelperDescriptor[]
|
||||
{
|
||||
|
|
@ -965,7 +965,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
|||
assemblyName: "SomeAssembly",
|
||||
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
|
||||
requiredAttributes: Enumerable.Empty<string>(),
|
||||
usageDescriptor: null),
|
||||
designTimeDescriptor: null),
|
||||
};
|
||||
|
||||
// documentContent, expectedOutput, availableDescriptors
|
||||
|
|
|
|||
Loading…
Reference in New Issue