Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Consume EditorBrowsableAttribute on TagHelpers.
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
NTaylorMullen committed Jul 16, 2015
1 parent fe28081 commit b762830
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -52,6 +53,12 @@ public static IEnumerable<TagHelperDescriptor> CreateDescriptors(
[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);

Expand Down Expand Up @@ -264,6 +271,11 @@ private static IEnumerable<TagHelperAttributeDescriptor> GetAttributeDescriptors
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);
Expand Down Expand Up @@ -364,6 +376,18 @@ internal static bool ValidateTagHelperAttributeDescriptor(
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Razor.TagHelpers;
Expand All @@ -15,6 +16,237 @@ public class TagHelperDescriptorFactoryTest
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
Expand Down Expand Up @@ -1564,6 +1796,59 @@ private static TheoryData<string, string[]> GetInvalidNameOrPrefixData(
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
{
Expand Down

0 comments on commit b762830

Please sign in to comment.