Add support for type parameters to class nodes
This change will allow someone extending Razor to use generic type parameters in generated classes. There's no user-level extensibility provided here yet, as in there is no language support for adding type parameters.
This commit is contained in:
parent
ae42d7599d
commit
d1c0ab587c
|
|
@ -60,7 +60,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
// Initialize declaration.
|
// Initialize declaration.
|
||||||
using (context.CodeWriter.BuildClassDeclaration(PublicModifiers, node.ClassName, TagHelperTypeName, interfaces: null))
|
using (context.CodeWriter.BuildClassDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
node.ClassName,
|
||||||
|
TagHelperTypeName,
|
||||||
|
interfaces: null,
|
||||||
|
typeParameters: null))
|
||||||
{
|
{
|
||||||
// Add view component helper.
|
// Add view component helper.
|
||||||
context.CodeWriter.WriteVariableDeclaration(
|
context.CodeWriter.WriteVariableDeclaration(
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
WriteTargetElementString(context.CodeWriter, node.TagHelper);
|
||||||
|
|
||||||
// Initialize declaration.
|
// Initialize declaration.
|
||||||
using (context.CodeWriter.BuildClassDeclaration(PublicModifiers, node.ClassName, TagHelperTypeName, interfaces: null))
|
using (context.CodeWriter.BuildClassDeclaration(
|
||||||
|
PublicModifiers,
|
||||||
|
node.ClassName,
|
||||||
|
TagHelperTypeName,
|
||||||
|
interfaces: null,
|
||||||
|
typeParameters: null))
|
||||||
{
|
{
|
||||||
// Add view component helper.
|
// Add view component helper.
|
||||||
context.CodeWriter.WriteVariableDeclaration(
|
context.CodeWriter.WriteVariableDeclaration(
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
IList<string> modifiers,
|
IList<string> modifiers,
|
||||||
string name,
|
string name,
|
||||||
string baseType,
|
string baseType,
|
||||||
IEnumerable<string> interfaces)
|
IList<string> interfaces,
|
||||||
|
IList<string> typeParameters)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < modifiers.Count; i++)
|
for (var i = 0; i < modifiers.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -385,8 +386,15 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
writer.Write("class ");
|
writer.Write("class ");
|
||||||
writer.Write(name);
|
writer.Write(name);
|
||||||
|
|
||||||
|
if (typeParameters != null && typeParameters.Count > 0)
|
||||||
|
{
|
||||||
|
writer.Write("<");
|
||||||
|
writer.Write(string.Join(", ", typeParameters));
|
||||||
|
writer.Write(">");
|
||||||
|
}
|
||||||
|
|
||||||
var hasBaseType = !string.IsNullOrEmpty(baseType);
|
var hasBaseType = !string.IsNullOrEmpty(baseType);
|
||||||
var hasInterfaces = interfaces != null && interfaces.Count() > 0;
|
var hasInterfaces = interfaces != null && interfaces.Count > 0;
|
||||||
|
|
||||||
if (hasBaseType || hasInterfaces)
|
if (hasBaseType || hasInterfaces)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
{
|
{
|
||||||
algorithmId = "{8829d00f-11b8-4213-878b-770e8597ac16}";
|
algorithmId = "{8829d00f-11b8-4213-878b-770e8597ac16}";
|
||||||
}
|
}
|
||||||
else if (string.Equals(algorithm, HashAlgorithmName.SHA1.Name, StringComparison.Ordinal) ||
|
else if (string.Equals(algorithm, HashAlgorithmName.SHA1.Name, StringComparison.Ordinal) ||
|
||||||
|
|
||||||
// In 2.0, we didn't actually expose the name of the algorithm, so it's possible we could get null here.
|
// In 2.0, we didn't actually expose the name of the algorithm, so it's possible we could get null here.
|
||||||
// If that's the case, we just assume SHA1 since that's the only thing we supported in 2.0.
|
// If that's the case, we just assume SHA1 since that's the only thing we supported in 2.0.
|
||||||
algorithm == null)
|
algorithm == null)
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var supportedAlgorithms = string.Join(" ", new string[]
|
var supportedAlgorithms = string.Join(" ", new string[]
|
||||||
{
|
{
|
||||||
HashAlgorithmName.SHA1.Name,
|
HashAlgorithmName.SHA1.Name,
|
||||||
HashAlgorithmName.SHA256.Name
|
HashAlgorithmName.SHA256.Name
|
||||||
|
|
@ -143,7 +143,12 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
{
|
{
|
||||||
using (Context.CodeWriter.BuildClassDeclaration(node.Modifiers, node.ClassName, node.BaseType, node.Interfaces))
|
using (Context.CodeWriter.BuildClassDeclaration(
|
||||||
|
node.Modifiers,
|
||||||
|
node.ClassName,
|
||||||
|
node.BaseType,
|
||||||
|
node.Interfaces,
|
||||||
|
node.TypeParameters.Select(p => p.ParameterName).ToArray()))
|
||||||
{
|
{
|
||||||
VisitDefault(node);
|
VisitDefault(node);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
public string BaseType { get; set; }
|
public string BaseType { get; set; }
|
||||||
|
|
||||||
public IList<string> Interfaces { get; set; }
|
public IList<string> Interfaces { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
public IList<TypeParameter> TypeParameters { get; set; } = new List<TypeParameter>();
|
||||||
|
|
||||||
public override void Accept(IntermediateNodeVisitor visitor)
|
public override void Accept(IntermediateNodeVisitor visitor)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
{
|
||||||
|
public sealed class TypeParameter
|
||||||
|
{
|
||||||
|
public string ParameterName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -218,6 +218,11 @@ namespace TestNamespace
|
||||||
},
|
},
|
||||||
BaseType = "TestBase",
|
BaseType = "TestBase",
|
||||||
Interfaces = new List<string> { "IFoo", "IBar", },
|
Interfaces = new List<string> { "IFoo", "IBar", },
|
||||||
|
TypeParameters = new List<TypeParameter>
|
||||||
|
{
|
||||||
|
new TypeParameter() { ParameterName = "TKey", },
|
||||||
|
new TypeParameter() { ParameterName = "TValue", },
|
||||||
|
},
|
||||||
ClassName = "TestClass",
|
ClassName = "TestClass",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -236,7 +241,7 @@ namespace TestNamespace
|
||||||
@"#pragma checksum ""test.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""da39a3ee5e6b4b0d3255bfef95601890afd80709""
|
@"#pragma checksum ""test.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""da39a3ee5e6b4b0d3255bfef95601890afd80709""
|
||||||
// <auto-generated/>
|
// <auto-generated/>
|
||||||
#pragma warning disable 1591
|
#pragma warning disable 1591
|
||||||
internal class TestClass : TestBase, IFoo, IBar
|
internal class TestClass<TKey, TValue> : TestBase, IFoo, IBar
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#pragma warning restore 1591
|
#pragma warning restore 1591
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
|
|
@ -66,6 +67,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
|
|
||||||
engine.ConfigureClass((document, @class) =>
|
engine.ConfigureClass((document, @class) =>
|
||||||
{
|
{
|
||||||
|
@class.TypeParameters = new[] { new TypeParameter() { ParameterName = "TValue", }, };
|
||||||
@class.Interfaces = new[] { "global::System.IDisposable" };
|
@class.Interfaces = new[] { "global::System.IDisposable" };
|
||||||
@class.BaseType = "CustomBaseType";
|
@class.BaseType = "CustomBaseType";
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace Razor
|
||||||
{
|
{
|
||||||
#line hidden
|
#line hidden
|
||||||
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"38aa8e26c5d2a85c61d8e93fe69dd326fe82671b", @"/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml")]
|
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"38aa8e26c5d2a85c61d8e93fe69dd326fe82671b", @"/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml")]
|
||||||
protected internal class MyClass : CustomBaseType, global::System.IDisposable
|
protected internal class MyClass<TValue> : CustomBaseType, global::System.IDisposable
|
||||||
{
|
{
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
public async override global::System.Threading.Tasks.Task ExecuteAsync()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -12,7 +13,7 @@ using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
{
|
{
|
||||||
// Serializes single IR nodes (shallow).
|
// Serializes single IR nodes (shallow).
|
||||||
public class IntermediateNodeWriter :
|
public class IntermediateNodeWriter :
|
||||||
IntermediateNodeVisitor,
|
IntermediateNodeVisitor,
|
||||||
IExtensionIntermediateNodeVisitor<SectionIntermediateNode>
|
IExtensionIntermediateNodeVisitor<SectionIntermediateNode>
|
||||||
{
|
{
|
||||||
|
|
@ -32,7 +33,21 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
|
|
||||||
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
|
||||||
{
|
{
|
||||||
WriteContentNode(node, string.Join(" ", node.Modifiers), node.ClassName, node.BaseType, string.Join(", ", node.Interfaces ?? new List<string>()));
|
var entries = new List<string>()
|
||||||
|
{
|
||||||
|
string.Join(" ", node.Modifiers),
|
||||||
|
node.ClassName,
|
||||||
|
node.BaseType,
|
||||||
|
string.Join(", ", node.Interfaces ?? Array.Empty<string>())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Avoid adding the type parameters to the baseline if they aren't present.
|
||||||
|
if (node.TypeParameters != null && node.TypeParameters.Count > 0)
|
||||||
|
{
|
||||||
|
entries.Add(string.Join(", ", node.TypeParameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteContentNode(node, entries.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node)
|
public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue