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

Consume EditorBrowsableAttribute on TagHelpers. #448

Merged
merged 1 commit into from
Jul 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class has more than one [TargetElement] but how does "EditorBrowsable" make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hu? It's just the name of the test class.

  • Multi = more than 1 element
  • EditorBrowsable = Has the EditorBrowsableAttribute

{
}

[TargetElement(Attributes = "class*")]
private class AttributeWildcardTargetingTagHelper : TagHelper
{
Expand Down