Consume `EditorBrowsableAttribute` on `TagHelper`s.
- Changed `TagHelperDescriptorFactory` to not create individual descriptors when `EditorBrowsableAttribute` is present and set to `EditorBrowsableState.Never`. - Added tests to validate the `TagHelperDescriptorFactory` creates the attribute correctly. - Did not look down the inheritance chain for `EditorBrowsableAttribute` because `TargetElement` is not inherited. #447
This commit is contained in:
parent
fe28081c34
commit
b762830a43
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
|
@ -52,6 +53,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
[NotNull] ErrorSink errorSink)
|
||||
{
|
||||
var typeInfo = type.GetTypeInfo();
|
||||
|
||||
if (ShouldSkipDescriptorCreation(designTime, typeInfo))
|
||||
{
|
||||
return Enumerable.Empty<TagHelperDescriptor>();
|
||||
}
|
||||
|
||||
var attributeDescriptors = GetAttributeDescriptors(type, designTime, errorSink);
|
||||
var targetElementAttributes = GetValidTargetElementAttributes(typeInfo, errorSink);
|
||||
|
||||
|
|
@ -264,6 +271,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
var accessibleProperties = type.GetRuntimeProperties().Where(IsAccessibleProperty);
|
||||
foreach (var property in accessibleProperties)
|
||||
{
|
||||
if (ShouldSkipDescriptorCreation(designTime, property))
|
||||
{
|
||||
return Enumerable.Empty<TagHelperAttributeDescriptor>();
|
||||
}
|
||||
|
||||
var attributeNameAttribute = property.GetCustomAttribute<HtmlAttributeNameAttribute>(inherit: false);
|
||||
var hasExplicitName =
|
||||
attributeNameAttribute != null && !string.IsNullOrEmpty(attributeNameAttribute.Name);
|
||||
|
|
@ -364,6 +376,18 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
nameOrPrefix);
|
||||
}
|
||||
|
||||
private static bool ShouldSkipDescriptorCreation(bool designTime, MemberInfo memberInfo)
|
||||
{
|
||||
if (designTime)
|
||||
{
|
||||
var editorBrowsableAttribute = memberInfo.GetCustomAttribute<EditorBrowsableAttribute>(inherit: false);
|
||||
|
||||
return editorBrowsableAttribute != null && editorBrowsableAttribute.State == EditorBrowsableState.Never;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ValidateTagHelperAttributeNameOrPrefix(
|
||||
string attributeNameOrPrefix,
|
||||
Type parentType,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
|
|
@ -15,6 +16,237 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
private static readonly string AssemblyName =
|
||||
typeof(TagHelperDescriptorFactoryTest).GetTypeInfo().Assembly.GetName().Name;
|
||||
|
||||
public static TheoryData EditorBrowsableData
|
||||
{
|
||||
get
|
||||
{
|
||||
// tagHelperType, designTime, expectedDescriptors
|
||||
return new TheoryData<Type, bool, TagHelperDescriptor[]>
|
||||
{
|
||||
{
|
||||
typeof(InheritedEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "inherited-editor-browsable",
|
||||
typeName: typeof(InheritedEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(InheritedEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{ typeof(EditorBrowsableTagHelper), true, new TagHelperDescriptor[0] },
|
||||
{
|
||||
typeof(EditorBrowsableTagHelper),
|
||||
false,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "editor-browsable",
|
||||
typeName: typeof(EditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(EditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(HiddenPropertyEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "hidden-property-editor-browsable",
|
||||
typeName: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new TagHelperAttributeDescriptor[0])
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(HiddenPropertyEditorBrowsableTagHelper),
|
||||
false,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "hidden-property-editor-browsable",
|
||||
typeName: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(HiddenPropertyEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(OverriddenEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "overridden-editor-browsable",
|
||||
typeName: typeof(OverriddenEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(OverriddenEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(MultiPropertyEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "multi-property-editor-browsable",
|
||||
typeName: typeof(MultiPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property2",
|
||||
propertyName: nameof(MultiPropertyEditorBrowsableTagHelper.Property2),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(MultiPropertyEditorBrowsableTagHelper),
|
||||
false,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "multi-property-editor-browsable",
|
||||
typeName: typeof(MultiPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(MultiPropertyEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property2",
|
||||
propertyName: nameof(MultiPropertyEditorBrowsableTagHelper.Property2),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(OverriddenPropertyEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "overridden-property-editor-browsable",
|
||||
typeName: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new TagHelperAttributeDescriptor[0])
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(OverriddenPropertyEditorBrowsableTagHelper),
|
||||
false,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "overridden-property-editor-browsable",
|
||||
typeName: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(OverriddenPropertyEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null),
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property2",
|
||||
propertyName: nameof(OverriddenPropertyEditorBrowsableTagHelper.Property2),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(DefaultEditorBrowsableTagHelper),
|
||||
true,
|
||||
new[]
|
||||
{
|
||||
new TagHelperDescriptor(
|
||||
tagName: "default-editor-browsable",
|
||||
typeName: typeof(DefaultEditorBrowsableTagHelper).FullName,
|
||||
assemblyName: AssemblyName,
|
||||
attributes: new[]
|
||||
{
|
||||
new TagHelperAttributeDescriptor(
|
||||
name: "property",
|
||||
propertyName: nameof(DefaultEditorBrowsableTagHelper.Property),
|
||||
typeName: typeof(int).FullName,
|
||||
isIndexer: false,
|
||||
designTimeDescriptor: null)
|
||||
})
|
||||
}
|
||||
},
|
||||
{ typeof(MultiEditorBrowsableTagHelper), true, new TagHelperDescriptor[0] }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(EditorBrowsableData))]
|
||||
public void CreateDescriptors_UnderstandsEditorBrowsableAttribute(
|
||||
Type tagHelperType,
|
||||
bool designTime,
|
||||
TagHelperDescriptor[] expectedDescriptors)
|
||||
{
|
||||
// Arrange
|
||||
var errorSink = new ErrorSink();
|
||||
|
||||
// Act
|
||||
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
|
||||
AssemblyName,
|
||||
tagHelperType,
|
||||
designTime,
|
||||
errorSink);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(errorSink.Errors);
|
||||
Assert.Equal(expectedDescriptors, descriptors, TagHelperDescriptorComparer.Default);
|
||||
}
|
||||
|
||||
public static TheoryData AttributeTargetData
|
||||
{
|
||||
get
|
||||
|
|
@ -1564,6 +1796,59 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
return data;
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Always)]
|
||||
private class DefaultEditorBrowsableTagHelper : TagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Always)]
|
||||
public int Property { get; set; }
|
||||
}
|
||||
|
||||
private class HiddenPropertyEditorBrowsableTagHelper : TagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public int Property { get; set; }
|
||||
}
|
||||
|
||||
private class MultiPropertyEditorBrowsableTagHelper : TagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public int Property { get; set; }
|
||||
|
||||
public virtual int Property2 { get; set; }
|
||||
}
|
||||
|
||||
private class OverriddenPropertyEditorBrowsableTagHelper : MultiPropertyEditorBrowsableTagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override int Property2 { get; set; }
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
private class EditorBrowsableTagHelper : TagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public virtual int Property { get; set; }
|
||||
}
|
||||
|
||||
private class InheritedEditorBrowsableTagHelper : EditorBrowsableTagHelper
|
||||
{
|
||||
public override int Property { get; set; }
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
private class OverriddenEditorBrowsableTagHelper : EditorBrowsableTagHelper
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
public override int Property { get; set; }
|
||||
}
|
||||
|
||||
[TargetElement("p")]
|
||||
[TargetElement("div")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
private class MultiEditorBrowsableTagHelper : TagHelper
|
||||
{
|
||||
}
|
||||
|
||||
[TargetElement(Attributes = "class*")]
|
||||
private class AttributeWildcardTargetingTagHelper : TagHelper
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue