[Fixes #5844] Using ExtensionIRNode for Inject directive

This commit is contained in:
Ajay Bhargav Baaskaran 2017-02-28 15:55:44 -08:00
parent acfad83aa6
commit f7c2e5bffc
7 changed files with 207 additions and 29 deletions

View File

@ -0,0 +1,12 @@
// 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.
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
namespace Microsoft.AspNetCore.Mvc.Razor.Host
{
public interface IInjectDirectiveTargetExtension : IRuntimeTargetExtension
{
void WriteInjectProperty(CSharpRenderingContext context, InjectDirectiveIRNode node);
}
}

View File

@ -49,14 +49,15 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
typeName = typeName.Replace("<TModel>", "<" + modelType + ">");
var member = new CSharpStatementIRNode()
var injectNode = new InjectDirectiveIRNode()
{
TypeName = typeName,
MemberName = memberName,
Source = directive.Source,
Content = $"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]{Environment.NewLine}public {typeName} {memberName} {{ get; private set; }}",
Parent = visitor.Class,
};
visitor.Class.Children.Add(member);
visitor.Class.Children.Add(injectNode);
}
}
}

View File

@ -0,0 +1,55 @@
// 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.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Host
{
public class InjectDirectiveIRNode : ExtensionIRNode
{
public string TypeName { get; set; }
public string MemberName { get; set; }
public override IList<RazorIRNode> Children { get; } = new RazorIRNode[0];
public override RazorIRNode Parent { get; set; }
public override SourceSpan? Source { get; set; }
public override void Accept(RazorIRNodeVisitor visitor)
{
if (visitor == null)
{
throw new ArgumentNullException(nameof(visitor));
}
AcceptExtensionNode<InjectDirectiveIRNode>(this, visitor);
}
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
{
if (visitor == null)
{
throw new ArgumentNullException(nameof(visitor));
}
return AcceptExtensionNode<InjectDirectiveIRNode, TResult>(this, visitor);
}
public override void WriteNode(RuntimeTarget target, CSharpRenderingContext context)
{
if (target == null)
{
throw new ArgumentNullException(nameof(target));
}
var extension = target.GetExtension<IInjectDirectiveTargetExtension>();
extension.WriteInjectProperty(context, this);
}
}
}

View File

@ -0,0 +1,44 @@
// 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.
using System;
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
namespace Microsoft.AspNetCore.Mvc.Razor.Host
{
public class InjectDirectiveTargetExtension : IInjectDirectiveTargetExtension
{
private const string RazorInjectAttribute = "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]";
public void WriteInjectProperty(CSharpRenderingContext context, InjectDirectiveIRNode node)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
if (node.Source.HasValue)
{
using (context.Writer.BuildLinePragma(node.Source.Value))
{
context.Writer
.WriteLine(RazorInjectAttribute)
.WriteLine(property);
}
}
else
{
context.Writer
.WriteLine(RazorInjectAttribute)
.WriteLine(property);
}
}
}
}

View File

@ -184,6 +184,8 @@ namespace Microsoft.Extensions.DependencyInjection
InjectDirective.Register(b);
ModelDirective.Register(b);
PageDirective.Register(b);
b.AddTargetExtension(new InjectDirectiveTargetExtension());
b.Features.Add(new ModelExpressionPass());
b.Features.Add(new PagesPropertyInjectionPass());

View File

@ -0,0 +1,75 @@
// 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.
using System;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.CodeGeneration;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Host
{
public class InjectDirectiveTargetExtensionTest
{
[Fact]
public void InjectDirectiveTargetExtension_WritesProperty()
{
// Arrange
var context = GetRenderingContext();
var target = new InjectDirectiveTargetExtension();
var node = new InjectDirectiveIRNode()
{
TypeName = "PropertyType",
MemberName = "PropertyName",
};
// Act
target.WriteInjectProperty(context, node);
// Assert
Assert.Equal(
"[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType PropertyName { get; private set; }" + Environment.NewLine,
context.Writer.Builder.ToString());
}
[Fact]
public void InjectDirectiveTargetExtension_WritesPropertyWithLinePragma_WhenSourceIsSet()
{
// Arrange
var context = GetRenderingContext();
var target = new InjectDirectiveTargetExtension();
var node = new InjectDirectiveIRNode()
{
TypeName = "PropertyType<ModelType>",
MemberName = "PropertyName",
Source = new SourceSpan(
filePath: "test-path",
absoluteIndex: 0,
lineIndex: 1,
characterIndex: 1,
length: 10)
};
// Act
target.WriteInjectProperty(context, node);
// Assert
Assert.Equal(
"#line 2 \"test-path\"" + Environment.NewLine +
"[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType<ModelType> PropertyName { get; private set; }" + Environment.NewLine + Environment.NewLine +
"#line default" + Environment.NewLine +
"#line hidden" + Environment.NewLine,
context.Writer.Builder.ToString());
}
private CSharpRenderingContext GetRenderingContext()
{
return new CSharpRenderingContext()
{
Writer = new CSharpCodeWriter()
};
}
}
}

View File

@ -1,7 +1,6 @@
// 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.
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Razor.Evolution;
@ -36,11 +35,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Assert.NotNull(@class);
Assert.Equal(2, @class.Children.Count);
var statement = Assert.IsType<CSharpStatementIRNode>(@class.Children[1]);
Assert.Equal(
"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType PropertyName { get; private set; }",
statement.Content);
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
Assert.Equal("PropertyType", node.TypeName);
Assert.Equal("PropertyName", node.MemberName);
}
[Fact]
@ -68,11 +65,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Assert.NotNull(@class);
Assert.Equal(2, @class.Children.Count);
var statement = Assert.IsType<CSharpStatementIRNode>(@class.Children[1]);
Assert.Equal(
"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType2 PropertyName { get; private set; }",
statement.Content);
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
Assert.Equal("PropertyType2", node.TypeName);
Assert.Equal("PropertyName", node.MemberName);
}
[Fact]
@ -99,11 +94,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Assert.NotNull(@class);
Assert.Equal(2, @class.Children.Count);
var statement = Assert.IsType<CSharpStatementIRNode>(@class.Children[1]);
Assert.Equal(
"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType<dynamic> PropertyName { get; private set; }",
statement.Content);
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
Assert.Equal("PropertyType<dynamic>", node.TypeName);
Assert.Equal("PropertyName", node.MemberName);
}
[Fact]
@ -131,11 +124,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Assert.NotNull(@class);
Assert.Equal(2, @class.Children.Count);
var statement = Assert.IsType<CSharpStatementIRNode>(@class.Children[1]);
Assert.Equal(
"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType<ModelType> PropertyName { get; private set; }",
statement.Content);
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
Assert.Equal("PropertyType<ModelType>", node.TypeName);
Assert.Equal("PropertyName", node.MemberName);
}
[Fact]
@ -163,11 +154,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Host
Assert.NotNull(@class);
Assert.Equal(2, @class.Children.Count);
var statement = Assert.IsType<CSharpStatementIRNode>(@class.Children[1]);
Assert.Equal(
"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine +
"public PropertyType<ModelType> PropertyName { get; private set; }",
statement.Content);
var node = Assert.IsType<InjectDirectiveIRNode>(@class.Children[1]);
Assert.Equal("PropertyType<ModelType>", node.TypeName);
Assert.Equal("PropertyName", node.MemberName);
}
private RazorCodeDocument CreateDocument(string content)