Remove magic string keys from TH builders.
- Replaced the magic strings with extension methods that produce the same behavior as the string keys did. - Added tests to validate new extension methods. #1307
This commit is contained in:
parent
315221c758
commit
5aababce6e
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
{
|
{
|
||||||
GenerateVCTHClass(visitor.Class, tagHelper.Value);
|
GenerateVCTHClass(visitor.Class, tagHelper.Value);
|
||||||
|
|
||||||
var tagHelperTypeName = tagHelper.Value.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var tagHelperTypeName = tagHelper.Value.GetTypeName();
|
||||||
if (visitor.Fields.UsedTagHelperTypeNames.Remove(tagHelperTypeName))
|
if (visitor.Fields.UsedTagHelperTypeNames.Remove(tagHelperTypeName))
|
||||||
{
|
{
|
||||||
visitor.Fields.UsedTagHelperTypeNames.Add(GetVCTHFullName(visitor.Namespace, visitor.Class, tagHelper.Value));
|
visitor.Fields.UsedTagHelperTypeNames.Add(GetVCTHFullName(visitor.Namespace, visitor.Class, tagHelper.Value));
|
||||||
|
|
@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
foreach (var attribute in descriptor.BoundAttributes)
|
foreach (var attribute in descriptor.BoundAttributes)
|
||||||
{
|
{
|
||||||
writer.WriteAutoPropertyDeclaration(
|
writer.WriteAutoPropertyDeclaration(
|
||||||
"public", attribute.TypeName, attribute.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]);
|
"public", attribute.TypeName, attribute.GetPropertyName());
|
||||||
|
|
||||||
if (attribute.IndexerTypeName != null)
|
if (attribute.IndexerTypeName != null)
|
||||||
{
|
{
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
private string[] GetMethodParameters(TagHelperDescriptor descriptor)
|
private string[] GetMethodParameters(TagHelperDescriptor descriptor)
|
||||||
{
|
{
|
||||||
var propertyNames = descriptor.BoundAttributes.Select(
|
var propertyNames = descriptor.BoundAttributes.Select(
|
||||||
attribute => attribute.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]);
|
attribute => attribute.GetPropertyName());
|
||||||
var joinedPropertyNames = string.Join(", ", propertyNames);
|
var joinedPropertyNames = string.Join(", ", propertyNames);
|
||||||
var parametersString = $"new {{ { joinedPropertyNames } }}";
|
var parametersString = $"new {{ { joinedPropertyNames } }}";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public static class BoundAttributeDescriptorExtensions
|
||||||
|
{
|
||||||
|
public static string GetPropertyName(this BoundAttributeDescriptor descriptor)
|
||||||
|
{
|
||||||
|
descriptor.Metadata.TryGetValue(TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey, out var propertyName);
|
||||||
|
|
||||||
|
return propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsDefaultKind(this BoundAttributeDescriptor descriptor)
|
||||||
|
=> string.Equals(descriptor.Kind, TagHelperBoundAttributeDescriptorBuilder.DescriptorKind, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -196,7 +196,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
string attributeName,
|
string attributeName,
|
||||||
BoundAttributeDescriptor descriptor)
|
BoundAttributeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]}";
|
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.GetPropertyName()}";
|
||||||
|
|
||||||
if (isIndexerNameMatch)
|
if (isIndexerNameMatch)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
string attributeName,
|
string attributeName,
|
||||||
BoundAttributeDescriptor descriptor)
|
BoundAttributeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]}";
|
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.GetPropertyName()}";
|
||||||
|
|
||||||
if (isIndexerNameMatch)
|
if (isIndexerNameMatch)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||||
var tagHelperRenderingContext = context.TagHelperRenderingContext;
|
var tagHelperRenderingContext = context.TagHelperRenderingContext;
|
||||||
var propertyName = node.Descriptor.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey];
|
var propertyName = node.Descriptor.GetPropertyName();
|
||||||
|
|
||||||
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
||||||
if (node.IsIndexerNameMatch &&
|
if (node.IsIndexerNameMatch &&
|
||||||
|
|
@ -453,7 +453,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
string attributeName,
|
string attributeName,
|
||||||
BoundAttributeDescriptor descriptor)
|
BoundAttributeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey]}";
|
var propertyAccessor = $"{tagHelperVariableName}.{descriptor.GetPropertyName()}";
|
||||||
|
|
||||||
if (isIndexerNameMatch)
|
if (isIndexerNameMatch)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -533,7 +533,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
foreach (var descriptor in block.Binding.Descriptors)
|
foreach (var descriptor in block.Binding.Descriptors)
|
||||||
{
|
{
|
||||||
var typeName = descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var typeName = descriptor.GetTypeName();
|
||||||
_tagHelperFields.UsedTagHelperTypeNames.Add(typeName);
|
_tagHelperFields.UsedTagHelperTypeNames.Add(typeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +543,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
var descriptors = tagHelperBinding.Descriptors;
|
var descriptors = tagHelperBinding.Descriptors;
|
||||||
foreach (var descriptor in descriptors)
|
foreach (var descriptor in descriptors)
|
||||||
{
|
{
|
||||||
var typeName = descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var typeName = descriptor.GetTypeName();
|
||||||
var createTagHelper = new CreateTagHelperIRNode()
|
var createTagHelper = new CreateTagHelperIRNode()
|
||||||
{
|
{
|
||||||
TagHelperTypeName = typeName,
|
TagHelperTypeName = typeName,
|
||||||
|
|
@ -577,8 +577,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
var associatedAttributeDescriptor = associatedDescriptor.BoundAttributes.First(
|
var associatedAttributeDescriptor = associatedDescriptor.BoundAttributes.First(
|
||||||
attributeDescriptor => TagHelperMatchingConventions.CanSatisfyBoundAttribute(attribute.Name, attributeDescriptor));
|
attributeDescriptor => TagHelperMatchingConventions.CanSatisfyBoundAttribute(attribute.Name, attributeDescriptor));
|
||||||
var tagHelperTypeName = associatedDescriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var tagHelperTypeName = associatedDescriptor.GetTypeName();
|
||||||
var attributePropertyName = associatedAttributeDescriptor.Metadata[TagHelperBoundAttributeDescriptorBuilder.PropertyNameKey];
|
var attributePropertyName = associatedAttributeDescriptor.GetPropertyName();
|
||||||
|
|
||||||
var setTagHelperProperty = new SetTagHelperPropertyIRNode()
|
var setTagHelperProperty = new SetTagHelperPropertyIRNode()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -267,13 +267,13 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.Kind != TagHelperDescriptorBuilder.DescriptorKind)
|
if (!descriptor.IsDefaultKind())
|
||||||
{
|
{
|
||||||
// We only understand TagHelperDescriptors generated from ITagHelpers.
|
// We only understand default TagHelperDescriptors.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptorTypeName = descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var descriptorTypeName = descriptor.GetTypeName();
|
||||||
|
|
||||||
if (lookupInfo.TypePattern.EndsWith("*", StringComparison.Ordinal))
|
if (lookupInfo.TypePattern.EndsWith("*", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
if (invalidRule != null)
|
if (invalidRule != null)
|
||||||
{
|
{
|
||||||
var typeName = descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var typeName = descriptor.GetTypeName();
|
||||||
|
|
||||||
// End tag TagHelper that states it shouldn't have an end tag.
|
// End tag TagHelper that states it shouldn't have an end tag.
|
||||||
errorSink.OnError(
|
errorSink.OnError(
|
||||||
|
|
@ -564,8 +564,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
// Can't have a set of TagHelpers that expect different structures.
|
// Can't have a set of TagHelpers that expect different structures.
|
||||||
if (baseStructure.HasValue && baseStructure != rule.TagStructure)
|
if (baseStructure.HasValue && baseStructure != rule.TagStructure)
|
||||||
{
|
{
|
||||||
var baseDescriptorTypeName = baseDescriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var baseDescriptorTypeName = baseDescriptor.GetTypeName();
|
||||||
var descriptorTypeName = descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
var descriptorTypeName = descriptor.GetTypeName();
|
||||||
errorSink.OnError(
|
errorSink.OnError(
|
||||||
tagBlock.Start,
|
tagBlock.Start,
|
||||||
LegacyResources.FormatTagHelperParseTreeRewriter_InconsistentTagStructure(
|
LegacyResources.FormatTagHelperParseTreeRewriter_InconsistentTagStructure(
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
public sealed class TagHelperBoundAttributeDescriptorBuilder
|
public sealed class TagHelperBoundAttributeDescriptorBuilder
|
||||||
{
|
{
|
||||||
public static readonly string DescriptorKind = "ITagHelper";
|
internal const string DescriptorKind = "ITagHelper";
|
||||||
public static readonly string PropertyNameKey = "ITagHelper.PropertyName";
|
internal const string PropertyNameKey = "ITagHelper.PropertyName";
|
||||||
|
|
||||||
private static readonly IReadOnlyDictionary<string, string> PrimitiveDisplayTypeNameLookups = new Dictionary<string, string>(StringComparer.Ordinal)
|
private static readonly IReadOnlyDictionary<string, string> PrimitiveDisplayTypeNameLookups = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
public sealed class TagHelperDescriptorBuilder
|
public sealed class TagHelperDescriptorBuilder
|
||||||
{
|
{
|
||||||
public static readonly string DescriptorKind = "ITagHelper";
|
internal const string DescriptorKind = "ITagHelper";
|
||||||
public static readonly string TypeNameKey = "ITagHelper.TypeName";
|
internal const string TypeNameKey = "ITagHelper.TypeName";
|
||||||
|
|
||||||
private static ICollection<char> InvalidNonWhitespaceAllowedChildCharacters { get; } = new HashSet<char>(
|
private static ICollection<char> InvalidNonWhitespaceAllowedChildCharacters { get; } = new HashSet<char>(
|
||||||
new[] { '@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*' });
|
new[] { '@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*' });
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public static class TagHelperDescriptorExtensions
|
||||||
|
{
|
||||||
|
public static string GetTypeName(this TagHelperDescriptor descriptor)
|
||||||
|
{
|
||||||
|
descriptor.Metadata.TryGetValue(TagHelperDescriptorBuilder.TypeNameKey, out var typeName);
|
||||||
|
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsDefaultKind(this TagHelperDescriptor descriptor)
|
||||||
|
=> string.Equals(descriptor.Kind, TagHelperDescriptorBuilder.DescriptorKind, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public class BoundAttributeDescriptorExtensionsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetPropertyName_ReturnsPropertyName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedPropertyName = "IntProperty";
|
||||||
|
var descriptor = TagHelperBoundAttributeDescriptorBuilder.Create("TestTagHelper")
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName(expectedPropertyName)
|
||||||
|
.TypeName(typeof(int).FullName)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var propertyName = descriptor.GetPropertyName();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedPropertyName, propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetPropertyName_ReturnsNullIfNoPropertyName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = TagHelperBoundAttributeDescriptorBuilder.Create("TestTagHelper")
|
||||||
|
.Name("test")
|
||||||
|
.TypeName(typeof(int).FullName)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var propertyName = descriptor.GetPropertyName();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsDefaultKind_ReturnsTrueIfFromDefaultBuilder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = TagHelperBoundAttributeDescriptorBuilder.Create("TestTagHelper")
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("IntProperty")
|
||||||
|
.TypeName(typeof(int).FullName)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var isDefault = descriptor.IsDefaultKind();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(isDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsDefaultKind_ReturnsFalseIfFromCustomBuilder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = new CustomBoundAttributeDescriptor();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var isDefault = descriptor.IsDefaultKind();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(isDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CustomBoundAttributeDescriptor : BoundAttributeDescriptor
|
||||||
|
{
|
||||||
|
public CustomBoundAttributeDescriptor() : base("custom")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public class TagHelperDescriptorExtensionsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetTypeName_ReturnsTypeName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedTypeName = "TestTagHelper";
|
||||||
|
var descriptor = TagHelperDescriptorBuilder.Create(expectedTypeName, "TestAssembly").Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var typeName = descriptor.GetTypeName();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedTypeName, typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTypeName_ReturnsNullIfNoTypeName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = new CustomTagHelperDescriptor();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var typeName = descriptor.GetTypeName();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsDefaultKind_ReturnsTrueIfFromDefaultBuilder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var isDefault = descriptor.IsDefaultKind();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(isDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsDefaultKind_ReturnsFalseIfFromCustomBuilder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var descriptor = new CustomTagHelperDescriptor();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var isDefault = descriptor.IsDefaultKind();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(isDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CustomTagHelperDescriptor : TagHelperDescriptor
|
||||||
|
{
|
||||||
|
public CustomTagHelperDescriptor() : base("custom")
|
||||||
|
{
|
||||||
|
Metadata = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.VisualStudio.RazorExtension.RazorInfo
|
||||||
|
|
||||||
public string TargetElement => string.Join(", ", _descriptor.TagMatchingRules.Select(rule => rule.TagName));
|
public string TargetElement => string.Join(", ", _descriptor.TagMatchingRules.Select(rule => rule.TagName));
|
||||||
|
|
||||||
public string TypeName => _descriptor.Metadata[TagHelperDescriptorBuilder.TypeNameKey];
|
public string TypeName => _descriptor.GetTypeName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Loading…
Reference in New Issue