From 22ecf85f8882e22564da2679678ec19765266c44 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 26 Oct 2015 17:26:01 -0700 Subject: [PATCH] Added `TagHelper` support for `enum`s. - If a `TagHelper` attribute is an `enum` then you no longer need to provide the `enum` name. To override this functionality you can add the `@` symbol. - Added code generation tests. - Added `TagHelperDescriptorFactoryTest`s that double for Precompilation tests. #196 --- .../CodeAnalysisSymbolBasedTypeInfo.cs | 3 + .../Runtime/TagHelpers/ITypeInfo.cs | 5 + .../Runtime/TagHelpers/RuntimeTypeInfo.cs | 3 + .../TagHelpers/TagHelperDescriptorFactory.cs | 1 + .../TagHelperAttributeDescriptorComparer.cs | 2 + .../CSharpTagHelperCodeRenderer.cs | 12 +- .../TagHelperAttributeDescriptor.cs | 6 + .../TagHelperDescriptorFactoryTest.cs | 87 ++++++++++ .../TagHelperDescriptorFactoryTagHelpers.cs | 19 ++ .../TagHelpers/TestTagHelpers/TestTypeInfo.cs | 8 + .../CSharpTagHelperRenderingTest.cs | 126 ++++++++++++++ .../TagHelpers/TagHelperDescriptorTest.cs | 23 ++- .../Output/EnumTagHelpers.DesignTime.cs | 88 ++++++++++ .../CodeGenerator/Output/EnumTagHelpers.cs | 163 ++++++++++++++++++ .../Source/EnumTagHelpers.cshtml | 11 ++ 15 files changed, 550 insertions(+), 7 deletions(-) create mode 100644 test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.DesignTime.cs create mode 100644 test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.cs create mode 100644 test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Source/EnumTagHelpers.cshtml diff --git a/src/Microsoft.AspNet.Razor.Runtime.Precompilation/CodeAnalysisSymbolBasedTypeInfo.cs b/src/Microsoft.AspNet.Razor.Runtime.Precompilation/CodeAnalysisSymbolBasedTypeInfo.cs index 61293d87a6..4251b32beb 100644 --- a/src/Microsoft.AspNet.Razor.Runtime.Precompilation/CodeAnalysisSymbolBasedTypeInfo.cs +++ b/src/Microsoft.AspNet.Razor.Runtime.Precompilation/CodeAnalysisSymbolBasedTypeInfo.cs @@ -60,6 +60,9 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation /// public ITypeSymbol TypeSymbol => _type; + /// + public bool IsEnum => _type.TypeKind == TypeKind.Enum; + /// public bool IsAbstract => _type.IsAbstract; diff --git a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/ITypeInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/ITypeInfo.cs index 00b670925f..dd2ded0af5 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/ITypeInfo.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/ITypeInfo.cs @@ -33,6 +33,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// IEnumerable Properties { get; } + /// + /// Gets a value indicating whether the type is an . + /// + bool IsEnum { get; } + /// /// Gets a value indicating whether the type is public. /// diff --git a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/RuntimeTypeInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/RuntimeTypeInfo.cs index eed802bf01..b05f2cbcd1 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/RuntimeTypeInfo.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/RuntimeTypeInfo.cs @@ -50,6 +50,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// public string FullName => TypeInfo.FullName; + /// + public bool IsEnum => TypeInfo.IsEnum; + /// public bool IsAbstract => TypeInfo.IsAbstract; diff --git a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/TagHelperDescriptorFactory.cs b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/TagHelperDescriptorFactory.cs index def04994f4..c3504800a5 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/TagHelperDescriptorFactory.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/Runtime/TagHelpers/TagHelperDescriptorFactory.cs @@ -719,6 +719,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { Name = attributeName, PropertyName = property.Name, + IsEnum = property.PropertyType.IsEnum, TypeName = typeName, IsStringProperty = isStringProperty, IsIndexer = isIndexer, diff --git a/src/Microsoft.AspNet.Razor.Test.Sources/TagHelperAttributeDescriptorComparer.cs b/src/Microsoft.AspNet.Razor.Test.Sources/TagHelperAttributeDescriptorComparer.cs index 40756fa623..da2a4ab9c3 100644 --- a/src/Microsoft.AspNet.Razor.Test.Sources/TagHelperAttributeDescriptorComparer.cs +++ b/src/Microsoft.AspNet.Razor.Test.Sources/TagHelperAttributeDescriptorComparer.cs @@ -31,6 +31,7 @@ namespace Microsoft.AspNet.Razor.Test.Internal Assert.Equal(descriptorX.Name, descriptorY.Name, StringComparer.Ordinal); Assert.Equal(descriptorX.PropertyName, descriptorY.PropertyName, StringComparer.Ordinal); Assert.Equal(descriptorX.TypeName, descriptorY.TypeName, StringComparer.Ordinal); + Assert.Equal(descriptorX.IsEnum, descriptorY.IsEnum); Assert.Equal(descriptorX.IsStringProperty, descriptorY.IsStringProperty); return TagHelperAttributeDesignTimeDescriptorComparer.Default.Equals( @@ -45,6 +46,7 @@ namespace Microsoft.AspNet.Razor.Test.Internal hashCodeCombiner.Add(descriptor.Name, StringComparer.Ordinal); hashCodeCombiner.Add(descriptor.PropertyName, StringComparer.Ordinal); hashCodeCombiner.Add(descriptor.TypeName, StringComparer.Ordinal); + hashCodeCombiner.Add(descriptor.IsEnum); hashCodeCombiner.Add(descriptor.IsStringProperty); hashCodeCombiner.Add(TagHelperAttributeDesignTimeDescriptorComparer.Default.GetHashCode( descriptor.DesignTimeDescriptor)); diff --git a/src/Microsoft.AspNet.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs b/src/Microsoft.AspNet.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs index dbd26e3a2c..a53b5c0c98 100644 --- a/src/Microsoft.AspNet.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs +++ b/src/Microsoft.AspNet.Razor/CodeGenerators/CSharpTagHelperCodeRenderer.cs @@ -413,9 +413,9 @@ namespace Microsoft.AspNet.Razor.CodeGenerators _writer.WriteStartAssignment(valueAccessor); lineMapper.MarkLineMappingStart(); - // Write out bare expression for this attribute value. Property is not a string. + // Write out code expression for this attribute value. Property is not a string. // So quoting or buffering are not helpful. - RenderRawAttributeValue(attributeValueChunk, attributeDescriptor, isPlainTextValue); + RenderCodeAttributeValue(attributeValueChunk, attributeDescriptor, isPlainTextValue); // End the assignment to the attribute. lineMapper.MarkLineMappingEnd(); @@ -580,7 +580,7 @@ namespace Microsoft.AspNet.Razor.CodeGenerators complexValue: false); } - private void RenderRawAttributeValue( + private void RenderCodeAttributeValue( Chunk attributeValueChunk, TagHelperAttributeDescriptor attributeDescriptor, bool isPlainTextValue) @@ -589,6 +589,12 @@ namespace Microsoft.AspNet.Razor.CodeGenerators attributeDescriptor, valueRenderer: (writer) => { + if (attributeDescriptor.IsEnum && isPlainTextValue) + { + writer.Write(attributeDescriptor.TypeName) + .Write("."); + } + var visitor = new CSharpTagHelperAttributeValueVisitor(writer, _context, attributeDescriptor.TypeName); visitor.Accept(attributeValueChunk); diff --git a/src/Microsoft.AspNet.Razor/Compilation/TagHelpers/TagHelperAttributeDescriptor.cs b/src/Microsoft.AspNet.Razor/Compilation/TagHelpers/TagHelperAttributeDescriptor.cs index 1634e2d7d1..3b8baa30e0 100644 --- a/src/Microsoft.AspNet.Razor/Compilation/TagHelpers/TagHelperAttributeDescriptor.cs +++ b/src/Microsoft.AspNet.Razor/Compilation/TagHelpers/TagHelperAttributeDescriptor.cs @@ -28,6 +28,7 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers Name = name; PropertyName = propertyInfo.Name; TypeName = propertyInfo.PropertyType.FullName; + IsEnum = propertyInfo.PropertyType.GetTypeInfo().IsEnum; } /// @@ -45,6 +46,11 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers /// public bool IsIndexer { get; set; } + /// + /// Gets or sets an indication whether this property is an . + /// + public bool IsEnum { get; set; } + /// /// Gets or sets an indication whether this property is of type or, if /// is true, whether the indexer's value is of type . diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperDescriptorFactoryTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperDescriptorFactoryTest.cs index 3905b63327..b2df198292 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperDescriptorFactoryTest.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TagHelperDescriptorFactoryTest.cs @@ -19,6 +19,93 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers protected static readonly string AssemblyName = TagHelperDescriptorFactoryTestAssembly.Name; + public static TheoryData IsEnumData + { + get + { + var attributeDescriptors = new[] + { + new TagHelperAttributeDescriptor + { + Name = "non-enum-property", + PropertyName = nameof(EnumTagHelper.NonEnumProperty), + TypeName = typeof(int).FullName + }, + new TagHelperAttributeDescriptor + { + Name = "enum-property", + PropertyName = nameof(EnumTagHelper.EnumProperty), + TypeName = typeof(CustomEnum).FullName, + IsEnum = true + }, + }; + + // tagHelperType, expectedDescriptors + return new TheoryData + { + { + typeof(EnumTagHelper), + new[] + { + new TagHelperDescriptor + { + TagName = "enum", + TypeName = typeof(EnumTagHelper).FullName, + AssemblyName = AssemblyName, + Attributes = attributeDescriptors + } + } + }, + { + typeof(MultiEnumTagHelper), + new[] + { + new TagHelperDescriptor + { + TagName = "input", + TypeName = typeof(MultiEnumTagHelper).FullName, + AssemblyName = AssemblyName, + Attributes = attributeDescriptors + }, + new TagHelperDescriptor + { + TagName = "p", + TypeName = typeof(MultiEnumTagHelper).FullName, + AssemblyName = AssemblyName, + Attributes = attributeDescriptors + } + } + } + }; + } + } + + [Theory] + [MemberData(nameof(IsEnumData))] + public void CreateDescriptors_IsEnumIsSetCorrectly( + Type tagHelperType, + TagHelperDescriptor[] expectedDescriptors) + { + // Arrange + var errorSink = new ErrorSink(); + + // Act + var descriptors = TagHelperDescriptorFactory.CreateDescriptors( + AssemblyName, + GetTypeInfo(tagHelperType), + designTime: false, + errorSink: errorSink); + + // Assert + Assert.Empty(errorSink.Errors); + + // We don't care about order. Mono returns reflected attributes differently so we need to ensure order + // doesn't matter by sorting. + descriptors = descriptors.OrderBy(descriptor => descriptor.TagName); + + Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default); + } + public static TheoryData RequiredParentData { get diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TagHelperDescriptorFactoryTagHelpers.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TagHelperDescriptorFactoryTagHelpers.cs index 78b0c6c73a..a5636b82fc 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TagHelperDescriptorFactoryTagHelpers.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TagHelperDescriptorFactoryTagHelpers.cs @@ -9,6 +9,25 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace Microsoft.AspNet.Razor.TagHelpers { + public enum CustomEnum + { + FirstValue, + SecondValue + } + + public class EnumTagHelper : TagHelper + { + public int NonEnumProperty { get; set; } + + public CustomEnum EnumProperty { get; set; } + } + + [HtmlTargetElement("p")] + [HtmlTargetElement("input")] + public class MultiEnumTagHelper : EnumTagHelper + { + } + [HtmlTargetElement("input", ParentTag = "div")] public class RequiredParentTagHelper : TagHelper { diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TestTypeInfo.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TestTypeInfo.cs index 97e4b90455..212906d204 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TestTypeInfo.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/Runtime/TagHelpers/TestTagHelpers/TestTypeInfo.cs @@ -34,6 +34,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers } } + public bool IsEnum + { + get + { + throw new NotImplementedException(); + } + } + public bool ImplementsInterface(ITypeInfo other) { throw new NotImplementedException(); diff --git a/test/Microsoft.AspNet.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs b/test/Microsoft.AspNet.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs index 96a34aa933..3d15491d9a 100644 --- a/test/Microsoft.AspNet.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/CodeGenerators/CSharpTagHelperRenderingTest.cs @@ -21,6 +21,48 @@ namespace Microsoft.AspNet.Razor.Test.Generator private static IEnumerable PrefixedPAndInputTagHelperDescriptors { get; } = BuildPAndInputTagHelperDescriptors(prefix: "THS"); + private static IEnumerable EnumTagHelperDescriptors + { + get + { + return new[] + { + new TagHelperDescriptor + { + TagName = "*", + TypeName = "CatchAllTagHelper", + AssemblyName = "SomeAssembly", + Attributes = new[] + { + new TagHelperAttributeDescriptor + { + Name = "catch-all", + PropertyName = "CatchAll", + IsEnum = true, + TypeName = typeof(MyEnum).FullName + }, + } + }, + new TagHelperDescriptor + { + TagName = "input", + TypeName = "InputTagHelper", + AssemblyName = "SomeAssembly", + Attributes = new[] + { + new TagHelperAttributeDescriptor + { + Name = "value", + PropertyName = "Value", + IsEnum = true, + TypeName = typeof(MyEnum).FullName + }, + } + }, + }; + } + } + private static IEnumerable SymbolBoundTagHelperDescriptors { get @@ -1588,6 +1630,83 @@ namespace Microsoft.AspNet.Razor.Test.Generator generatedCharacterOffsetIndex: 29, contentLength: 13), } + }, + { + "EnumTagHelpers", + "EnumTagHelpers.DesignTime", + EnumTagHelperDescriptors, + new[] + { + BuildLineMapping( + documentAbsoluteIndex: 14, + documentLineIndex: 0, + generatedAbsoluteIndex: 419, + generatedLineIndex: 14, + characterOffsetIndex: 14, + contentLength: 17), + BuildLineMapping( + documentAbsoluteIndex: 37, + documentLineIndex: 2, + generatedAbsoluteIndex: 892, + generatedLineIndex: 33, + characterOffsetIndex: 2, + contentLength: 39), + BuildLineMapping( + documentAbsoluteIndex: 96, + documentLineIndex: 6, + documentCharacterOffsetIndex: 15, + generatedAbsoluteIndex: 1162, + generatedLineIndex: 42, + generatedCharacterOffsetIndex: 25, + contentLength: 14), + BuildLineMapping( + documentAbsoluteIndex: 131, + documentLineIndex: 7, + generatedAbsoluteIndex: 1398, + generatedLineIndex: 49, + characterOffsetIndex: 15, + contentLength: 20), + BuildLineMapping( + documentAbsoluteIndex: 171, + documentLineIndex: 8, + documentCharacterOffsetIndex: 14, + generatedAbsoluteIndex: 1695, + generatedLineIndex: 56, + generatedCharacterOffsetIndex: 70, + contentLength: 7), + BuildLineMapping( + documentAbsoluteIndex: 198, + documentLineIndex: 9, + documentCharacterOffsetIndex: 14, + generatedAbsoluteIndex: 1980, + generatedLineIndex: 63, + generatedCharacterOffsetIndex: 70, + contentLength: 13), + BuildLineMapping( + documentAbsoluteIndex: 224, + documentLineIndex: 9, + documentCharacterOffsetIndex: 40, + generatedAbsoluteIndex: 2146, + generatedLineIndex: 68, + generatedCharacterOffsetIndex: 85, + contentLength: 7), + BuildLineMapping( + documentAbsoluteIndex: 251, + documentLineIndex: 10, + documentCharacterOffsetIndex: 15, + generatedAbsoluteIndex: 2386, + generatedLineIndex: 75, + generatedCharacterOffsetIndex: 25, + contentLength: 9), + BuildLineMapping( + documentAbsoluteIndex: 274, + documentLineIndex: 10, + documentCharacterOffsetIndex: 38, + generatedAbsoluteIndex: 2500, + generatedLineIndex: 80, + generatedCharacterOffsetIndex: 37, + contentLength: 9), + } } }; } @@ -1640,6 +1759,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator { "TransitionsInTagHelperAttributes", null, DefaultPAndInputTagHelperDescriptors }, { "NestedScriptTagTagHelpers", null, DefaultPAndInputTagHelperDescriptors }, { "SymbolBoundAttributes", null, SymbolBoundTagHelperDescriptors }, + { "EnumTagHelpers", null, EnumTagHelperDescriptors }, }; } } @@ -1793,4 +1913,10 @@ namespace Microsoft.AspNet.Razor.Test.Generator public string BoundProperty { get; set; } } } + + public enum MyEnum + { + MyValue, + MySecondValue + } } diff --git a/test/Microsoft.AspNet.Razor.Test/TagHelpers/TagHelperDescriptorTest.cs b/test/Microsoft.AspNet.Razor.Test/TagHelpers/TagHelperDescriptorTest.cs index 454cb073de..79aff0bc10 100644 --- a/test/Microsoft.AspNet.Razor.Test/TagHelpers/TagHelperDescriptorTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/TagHelpers/TagHelperDescriptorTest.cs @@ -73,7 +73,8 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers { Name = "attribute one", PropertyName = "property name", - TypeName = "property type name" + TypeName = "property type name", + IsEnum = true, }, new TagHelperAttributeDescriptor { @@ -94,12 +95,14 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," + $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + @@ -135,7 +138,8 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers Name = "attribute one", PropertyName = "property name", TypeName = "property type name", - IsIndexer = true + IsIndexer = true, + IsEnum = true, }, new TagHelperAttributeDescriptor { @@ -143,6 +147,7 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers PropertyName = "property name", TypeName = typeof(string).FullName, IsIndexer = true, + IsEnum = false, IsStringProperty = true }, }, @@ -158,12 +163,14 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," + $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + @@ -249,12 +256,14 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," + $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + @@ -277,13 +286,15 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers { Name = "attribute one", PropertyName = "property name", - TypeName = "property type name" + TypeName = "property type name", + IsEnum = true, }, new TagHelperAttributeDescriptor { Name = "attribute two", PropertyName = "property name", TypeName = typeof(string).FullName, + IsEnum = false, IsStringProperty = true }, }, @@ -316,12 +327,14 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," + $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," + $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," + $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," + + $"\"{ nameof(TagHelperAttributeDescriptor.IsEnum) }\":false," + $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," + $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," + $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," + @@ -345,7 +358,8 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers Name = "attribute one", PropertyName = "property name", TypeName = "property type name", - IsIndexer = true + IsIndexer = true, + IsEnum = true, }, new TagHelperAttributeDescriptor { @@ -353,6 +367,7 @@ namespace Microsoft.AspNet.Razor.Compilation.TagHelpers PropertyName = "property name", TypeName = typeof(string).FullName, IsIndexer = true, + IsEnum = false, IsStringProperty = true } }, diff --git a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.DesignTime.cs b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.DesignTime.cs new file mode 100644 index 0000000000..694b259346 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.DesignTime.cs @@ -0,0 +1,88 @@ +namespace TestOutput +{ + using System; + using System.Threading.Tasks; + + public class EnumTagHelpers + { + private static object @__o; + private void @__RazorDesignTimeHelpers__() + { + #pragma warning disable 219 + string __tagHelperDirectiveSyntaxHelper = null; + __tagHelperDirectiveSyntaxHelper = +#line 1 "EnumTagHelpers.cshtml" + "something, nice" + +#line default +#line hidden + ; + #pragma warning restore 219 + } + #line hidden + private InputTagHelper __InputTagHelper = null; + private CatchAllTagHelper __CatchAllTagHelper = null; + #line hidden + public EnumTagHelpers() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { +#line 3 "EnumTagHelpers.cshtml" + + var enumValue = MyEnum.MyValue; + +#line default +#line hidden + + __InputTagHelper = CreateTagHelper(); + __CatchAllTagHelper = CreateTagHelper(); +#line 7 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = MyEnum.MyValue; + +#line default +#line hidden + __InputTagHelper = CreateTagHelper(); + __CatchAllTagHelper = CreateTagHelper(); +#line 8 "EnumTagHelpers.cshtml" + __o = MyEnum.MySecondValue; + +#line default +#line hidden + __InputTagHelper = CreateTagHelper(); + __CatchAllTagHelper = CreateTagHelper(); +#line 9 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MyValue; + +#line default +#line hidden + __InputTagHelper = CreateTagHelper(); + __CatchAllTagHelper = CreateTagHelper(); +#line 10 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MySecondValue; + +#line default +#line hidden +#line 10 "EnumTagHelpers.cshtml" + __CatchAllTagHelper.CatchAll = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MyValue; + +#line default +#line hidden + __InputTagHelper = CreateTagHelper(); + __CatchAllTagHelper = CreateTagHelper(); +#line 11 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = enumValue; + +#line default +#line hidden +#line 11 "EnumTagHelpers.cshtml" + __CatchAllTagHelper.CatchAll = enumValue; + +#line default +#line hidden + } + #pragma warning restore 1998 + } +} diff --git a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.cs b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.cs new file mode 100644 index 0000000000..94b2b37336 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Output/EnumTagHelpers.cs @@ -0,0 +1,163 @@ +#pragma checksum "EnumTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "57102d182f8d5da659bb113653552ea18f42bb76" +namespace TestOutput +{ + using Microsoft.AspNet.Razor.TagHelpers; + using Microsoft.AspNet.Razor.Runtime.TagHelpers; + using System; + using System.Threading.Tasks; + + public class EnumTagHelpers + { + #line hidden + #pragma warning disable 0414 + private TagHelperContent __tagHelperStringValueBuffer = null; + #pragma warning restore 0414 + private TagHelperExecutionContext __tagHelperExecutionContext = null; + private TagHelperRunner __tagHelperRunner = null; + private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager(); + private InputTagHelper __InputTagHelper = null; + private CatchAllTagHelper __CatchAllTagHelper = null; + #line hidden + public EnumTagHelpers() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + __tagHelperRunner = __tagHelperRunner ?? new TagHelperRunner(); + Instrumentation.BeginContext(33, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); +#line 3 "EnumTagHelpers.cshtml" + + var enumValue = MyEnum.MyValue; + +#line default +#line hidden + + Instrumentation.BeginContext(79, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => { + } + , StartTagHelperWritingScope, EndTagHelperWritingScope); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __CatchAllTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__CatchAllTagHelper); +#line 7 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = MyEnum.MyValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("value", __InputTagHelper.Value); + __tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); + Instrumentation.BeginContext(81, 33, false); + await WriteTagHelperAsync(__tagHelperExecutionContext); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(114, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => { + } + , StartTagHelperWritingScope, EndTagHelperWritingScope); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __CatchAllTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__CatchAllTagHelper); + BeginAddHtmlAttributeValues(__tagHelperExecutionContext, "class", 1); +#line 8 "EnumTagHelpers.cshtml" +AddHtmlAttributeValue("", 130, MyEnum.MySecondValue, 130, 21, false); + +#line default +#line hidden + EndAddHtmlAttributeValues(__tagHelperExecutionContext); + __tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); + Instrumentation.BeginContext(116, 39, false); + await WriteTagHelperAsync(__tagHelperExecutionContext); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(155, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => { + } + , StartTagHelperWritingScope, EndTagHelperWritingScope); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __CatchAllTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__CatchAllTagHelper); +#line 9 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MyValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("value", __InputTagHelper.Value); + __tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); + Instrumentation.BeginContext(157, 25, false); + await WriteTagHelperAsync(__tagHelperExecutionContext); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(182, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => { + } + , StartTagHelperWritingScope, EndTagHelperWritingScope); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __CatchAllTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__CatchAllTagHelper); +#line 10 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MySecondValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("value", __InputTagHelper.Value); +#line 10 "EnumTagHelpers.cshtml" + __CatchAllTagHelper.CatchAll = Microsoft.AspNet.Razor.Test.Generator.MyEnum.MyValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("catch-all", __CatchAllTagHelper.CatchAll); + __tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); + Instrumentation.BeginContext(184, 50, false); + await WriteTagHelperAsync(__tagHelperExecutionContext); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(234, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", TagMode.SelfClosing, "test", async() => { + } + , StartTagHelperWritingScope, EndTagHelperWritingScope); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __CatchAllTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__CatchAllTagHelper); +#line 11 "EnumTagHelpers.cshtml" +__InputTagHelper.Value = enumValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("value", __InputTagHelper.Value); +#line 11 "EnumTagHelpers.cshtml" + __CatchAllTagHelper.CatchAll = enumValue; + +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("catch-all", __CatchAllTagHelper.CatchAll); + __tagHelperExecutionContext.Output = await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); + Instrumentation.BeginContext(236, 51, false); + await WriteTagHelperAsync(__tagHelperExecutionContext); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(287, 2, true); + WriteLiteral("\r\n"); + Instrumentation.EndContext(); + } + #pragma warning restore 1998 + } +} diff --git a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Source/EnumTagHelpers.cshtml b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Source/EnumTagHelpers.cshtml new file mode 100644 index 0000000000..42f2e818d9 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/Source/EnumTagHelpers.cshtml @@ -0,0 +1,11 @@ +@addTagHelper "something, nice" + +@{ + var enumValue = MyEnum.MyValue; +} + + + + + +