Add some new IR nodes

This adds the basics of a few new node types. I'll do a follow up to start
using these so we can eliminate some misuse of the statement node.
This commit is contained in:
Ryan Nowak 2017-05-11 09:38:46 -07:00
parent 2afe2e1627
commit d3e37f20ce
27 changed files with 437 additions and 59 deletions

View File

@ -70,14 +70,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public IList<DirectiveIRNode> Directives { get; } = new List<DirectiveIRNode>();
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (Class == null)
{
Class = node;
}
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
public override void VisitDirective(DirectiveIRNode node)

View File

@ -113,24 +113,24 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public IList<DirectiveIRNode> ModelDirectives { get; } = new List<DirectiveIRNode>();
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
if (Namespace == null)
{
Namespace = node;
}
base.VisitNamespace(node);
base.VisitNamespaceDeclaration(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (Class == null)
{
Class = node;
}
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
public override void VisitDirective(DirectiveIRNode node)

View File

@ -164,24 +164,24 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
// We want the last one, so get them all and then .
public DirectiveIRNode LastNamespaceDirective { get; private set; }
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
if (FirstNamespace == null)
{
FirstNamespace = node;
}
base.VisitNamespace(node);
base.VisitNamespaceDeclaration(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (FirstClass == null)
{
FirstClass = node;
}
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
public override void VisitDirective(DirectiveIRNode node)

View File

@ -51,14 +51,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public ClassDeclarationIRNode Class { get; private set; }
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (Class == null)
{
Class = node;
}
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
}
}

View File

@ -249,24 +249,24 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
}
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
if (Namespace == null)
{
Namespace = node;
}
base.VisitNamespace(node);
base.VisitNamespaceDeclaration(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (Class == null)
{
Class = node;
}
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)

View File

@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
Context.BasicWriter.WriteUsingStatement(Context, node);
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
Context.Writer
.Write("namespace ")
@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
}
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Context.Writer
.Write(node.AccessModifier)
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
}
}
public override void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public override void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
Context.Writer.WriteLine("#pragma warning disable 1998");
@ -174,6 +174,16 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
Context.Writer.WriteLine("#pragma warning restore 1998");
}
public override void VisitFieldDeclaration(FieldDeclarationIRNode node)
{
Context.Writer.WriteField(node.AccessModifier, node.Modifiers, node.Type, node.Name);
}
public override void VisitPropertyDeclaration(PropertyDeclarationIRNode node)
{
Context.Writer.WriteAutoPropertyDeclaration(node.AccessModifier, node.Modifiers, node.Type, node.Name);
}
public override void VisitExtension(ExtensionIRNode node)
{
node.WriteNode(_target, Context);

View File

@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Razor.Language
public IList<DirectiveIRNode> SectionDirectiveNodes { get; } = new List<DirectiveIRNode>();
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
if (ClassNode == null)
{

View File

@ -141,6 +141,12 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitDefault(RazorIRNode node)
{
if (node is MemberDeclarationIRNode)
{
_class.Add(node);
return;
}
_method.Add(node);
}
}

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public class ClassDeclarationIRNode : RazorIRNode
public sealed class ClassDeclarationIRNode : MemberDeclarationIRNode
{
private ItemCollection _annotations;
@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
return _annotations;
}
}
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
public override RazorIRNode Parent { get; set; }
@ -43,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
throw new ArgumentNullException(nameof(visitor));
}
visitor.VisitClass(this);
visitor.VisitClassDeclaration(this);
}
}
}

View File

@ -0,0 +1,50 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public sealed class FieldDeclarationIRNode : MemberDeclarationIRNode
{
private ItemCollection _annotations;
public override ItemCollection Annotations
{
get
{
if (_annotations == null)
{
_annotations = new DefaultItemCollection();
}
return _annotations;
}
}
public override IList<RazorIRNode> Children { get; } = EmptyArray;
public IList<string> Modifiers { get; set; } = new List<string>();
public override RazorIRNode Parent { get; set; }
public override SourceSpan? Source { get; set; }
public string AccessModifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public override void Accept(RazorIRNodeVisitor visitor)
{
if (visitor == null)
{
throw new ArgumentNullException(nameof(visitor));
}
visitor.VisitFieldDeclaration(this);
}
}
}

View File

@ -0,0 +1,9 @@
// 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 abstract class MemberDeclarationIRNode : RazorIRNode
{
}
}

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public class MethodDeclarationIRNode : RazorIRNode
public sealed class MethodDeclarationIRNode : MemberDeclarationIRNode
{
private ItemCollection _annotations;
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
public string AccessModifier { get; set; }
public IList<string> Modifiers { get; set; }
public IList<string> Modifiers { get; set; } = new List<string>();
public string Name { get; set; }
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
throw new ArgumentNullException(nameof(visitor));
}
visitor.VisitRazorMethodDeclaration(this);
visitor.VisitMethodDeclaration(this);
}
}
}

View File

@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
throw new ArgumentNullException(nameof(visitor));
}
visitor.VisitNamespace(this);
visitor.VisitNamespaceDeclaration(this);
}
}
}

View File

@ -0,0 +1,50 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public sealed class PropertyDeclarationIRNode : MemberDeclarationIRNode
{
private ItemCollection _annotations;
public override ItemCollection Annotations
{
get
{
if (_annotations == null)
{
_annotations = new DefaultItemCollection();
}
return _annotations;
}
}
public override IList<RazorIRNode> Children { get; } = EmptyArray;
public IList<string> Modifiers { get; set; } = new List<string>();
public override RazorIRNode Parent { get; set; }
public override SourceSpan? Source { get; set; }
public string AccessModifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public override void Accept(RazorIRNodeVisitor visitor)
{
if (visitor == null)
{
throw new ArgumentNullException(nameof(visitor));
}
visitor.VisitPropertyDeclaration(this);
}
}
}

View File

@ -64,12 +64,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
VisitDefault(node);
}
public virtual void VisitClass(ClassDeclarationIRNode node)
public virtual void VisitClassDeclaration(ClassDeclarationIRNode node)
{
VisitDefault(node);
}
public virtual void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public virtual void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
VisitDefault(node);
}
public virtual void VisitFieldDeclaration(FieldDeclarationIRNode node)
{
VisitDefault(node);
}
public virtual void VisitPropertyDeclaration(PropertyDeclarationIRNode node)
{
VisitDefault(node);
}
@ -84,7 +94,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
VisitDefault(node);
}
public virtual void VisitNamespace(NamespaceDeclarationIRNode node)
public virtual void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
VisitDefault(node);
}

View File

@ -358,6 +358,66 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
string.Format(CultureInfo.InvariantCulture, InstanceMethodFormat, instanceName, methodName));
}
public CSharpCodeWriter WriteField(string accessibility, string typeName, string fieldName)
{
if (accessibility == null)
{
throw new ArgumentNullException(nameof(accessibility));
}
if (typeName == null)
{
throw new ArgumentNullException(nameof(typeName));
}
if (fieldName == null)
{
throw new ArgumentNullException(nameof(fieldName));
}
return WriteField(accessibility, Array.Empty<string>(), typeName, fieldName);
}
public CSharpCodeWriter WriteField(string accessibility, IList<string> modifiers, string typeName, string fieldName)
{
if (accessibility == null)
{
throw new ArgumentNullException(nameof(accessibility));
}
if (modifiers == null)
{
throw new ArgumentNullException(nameof(modifiers));
}
if (typeName == null)
{
throw new ArgumentNullException(nameof(typeName));
}
if (fieldName == null)
{
throw new ArgumentNullException(nameof(fieldName));
}
Write(accessibility);
Write(" ");
for (var i = 0; i < modifiers.Count; i++)
{
Write(modifiers[i]);
Write(" ");
}
Write(typeName);
Write(" ");
Write(fieldName);
Write(";");
WriteLine();
return this;
}
public CSharpCodeWriter WriteMethodInvocation(string methodName, params string[] parameters)
{
return WriteMethodInvocation(methodName, endLine: true, parameters: parameters);
@ -370,15 +430,64 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
.WriteEndMethodInvocation(endLine);
}
public CSharpCodeWriter WriteAutoPropertyDeclaration(string accessibility, string typeName, string name)
public CSharpCodeWriter WriteAutoPropertyDeclaration(string accessibility, string typeName, string propertyName)
{
return Write(accessibility)
.Write(" ")
.Write(typeName)
.Write(" ")
.Write(name)
.Write(" { get; set; }")
.WriteLine();
if (accessibility == null)
{
throw new ArgumentNullException(nameof(accessibility));
}
if (typeName == null)
{
throw new ArgumentNullException(nameof(typeName));
}
if (propertyName == null)
{
throw new ArgumentNullException(nameof(propertyName));
}
return WriteAutoPropertyDeclaration(accessibility, Array.Empty<string>(), typeName, propertyName);
}
public CSharpCodeWriter WriteAutoPropertyDeclaration(string accessibility, IList<string> modifiers, string typeName, string propertyName)
{
if (accessibility == null)
{
throw new ArgumentNullException(nameof(accessibility));
}
if (modifiers == null)
{
throw new ArgumentNullException(nameof(modifiers));
}
if (typeName == null)
{
throw new ArgumentNullException(nameof(typeName));
}
if (propertyName == null)
{
throw new ArgumentNullException(nameof(propertyName));
}
Write(accessibility);
Write(" ");
for (var i = 0; i < modifiers.Count; i++)
{
Write(modifiers[i]);
Write(" ");
}
Write(typeName);
Write(" ");
Write(propertyName);
Write(" { get; set; }");
WriteLine();
return this;
}
public CSharpDisableWarningScope BuildDisableWarningScope(int warning)

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
private DesignTimeDirectiveIRNode _designTimeDirectiveIRNode;
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
var designTimeHelperDeclaration = new CSharpStatementIRNode();
RazorIRBuilder.Create(designTimeHelperDeclaration)

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language
private int _variableCountOffset;
private int _preallocatedDeclarationCount = 0;
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
_classDeclaration = node;
_variableCountOffset = node.Children.Count;

View File

@ -216,7 +216,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public ClassDeclarationIRNode Node { get; set; }
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Node = node;
}

View File

@ -277,7 +277,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public ClassDeclarationIRNode Node { get; set; }
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Node = node;
}
@ -287,7 +287,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public NamespaceDeclarationIRNode Node { get; set; }
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
Node = node;
}

View File

@ -223,21 +223,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public MethodDeclarationIRNode Method { get; private set; }
public override void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public override void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
Method = node;
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
Namespace = node;
base.VisitNamespace(node);
base.VisitNamespaceDeclaration(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Class = node;
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
}
}

View File

@ -249,21 +249,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public MethodDeclarationIRNode Method { get; private set; }
public override void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public override void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
Method = node;
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
Namespace = node;
base.VisitNamespace(node);
base.VisitNamespaceDeclaration(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Class = node;
base.VisitClass(node);
base.VisitClassDeclaration(node);
}
}
}

View File

@ -348,7 +348,7 @@ public class __Generated__TagCloudViewComponentTagHelper : Microsoft.AspNetCore.
{
public ClassDeclarationIRNode Node { get; set; }
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
Node = node;
}

View File

@ -125,6 +125,82 @@ internal virtual async string TestMethod()
{
}
#pragma warning restore 1998
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteDocument_WritesField()
{
// Arrange
var codeDocument = TestRazorCodeDocument.CreateEmpty();
var options = RazorParserOptions.CreateDefaultOptions();
var target = RuntimeTarget.CreateDefault(codeDocument, options);
var context = new CSharpRenderingContext()
{
Options = options,
Writer = new Legacy.CSharpCodeWriter(),
};
var writer = new DefaultDocumentWriter(target, context);
var builder = RazorIRBuilder.Document();
builder.Add(new FieldDeclarationIRNode()
{
AccessModifier = "internal",
Modifiers = new List<string> { "readonly",},
Name = "_foo",
Type = "string",
});
var document = (DocumentIRNode)builder.Build();
// Act
writer.WriteDocument(document);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"internal readonly string _foo;
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteDocument_WritesProperty()
{
// Arrange
var codeDocument = TestRazorCodeDocument.CreateEmpty();
var options = RazorParserOptions.CreateDefaultOptions();
var target = RuntimeTarget.CreateDefault(codeDocument, options);
var context = new CSharpRenderingContext()
{
Options = options,
Writer = new Legacy.CSharpCodeWriter(),
};
var writer = new DefaultDocumentWriter(target, context);
var builder = RazorIRBuilder.Document();
builder.Add(new PropertyDeclarationIRNode()
{
AccessModifier = "internal",
Modifiers = new List<string> { "virtual", },
Name = "Foo",
Type = "string",
});
var document = (DocumentIRNode)builder.Build();
// Act
writer.WriteDocument(document);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"internal virtual string Foo { get; set; }
",
csharp,
ignoreLineEndingDifferences: true);

View File

@ -1,6 +1,7 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -45,5 +46,61 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
// Assert
Assert.Equal(expected, code);
}
[Fact]
public void WriteField_WritesFieldDeclaration()
{
// Arrange
var writer = new CSharpCodeWriter();
// Act
writer.WriteField("private", "global::System.String", "_myString");
// Assert
var output = writer.GenerateCode();
Assert.Equal("private global::System.String _myString;" + Environment.NewLine, output);
}
[Fact]
public void WriteField_WithModifiers_WritesFieldDeclaration()
{
// Arrange
var writer = new CSharpCodeWriter();
// Act
writer.WriteField("private", new[] { "readonly", "static" }, "global::System.String", "_myString");
// Assert
var output = writer.GenerateCode();
Assert.Equal("private readonly static global::System.String _myString;" + Environment.NewLine, output);
}
[Fact]
public void WriteAutoPropertyDeclaration_WritesPropertyDeclaration()
{
// Arrange
var writer = new CSharpCodeWriter();
// Act
writer.WriteAutoPropertyDeclaration("public", "global::System.String", "MyString");
// Assert
var output = writer.GenerateCode();
Assert.Equal("public global::System.String MyString { get; set; }" + Environment.NewLine, output);
}
[Fact]
public void WriteAutoPropertyDeclaration_WithModifiers_WritesPropertyDeclaration()
{
// Arrange
var writer = new CSharpCodeWriter();
// Act
writer.WriteAutoPropertyDeclaration("public", new[] { "static" }, "global::System.String", "MyString");
// Assert
var output = writer.GenerateCode();
Assert.Equal("public static global::System.String MyString { get; set; }" + Environment.NewLine, output);
}
}
}

View File

@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
private class ApiSetsIRWalker : RazorIRNodeWalker
{
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
node.Name = Filename.Replace('/', '_');
node.AccessModifier = "public";
@ -229,14 +229,14 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
VisitDefault(node);
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
node.Content = "Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles";
VisitDefault(node);
}
public override void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public override void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
node.AccessModifier = "public";
node.Modifiers = new[] { "async" };

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
WriteBasicNode(node);
}
public override void VisitClass(ClassDeclarationIRNode node)
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
{
WriteContentNode(node, node.AccessModifier, node.Name, node.BaseType, string.Join(", ", node.Interfaces ?? new List<string>()));
}
@ -61,12 +61,12 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
WriteContentNode(node, node.Prefix, node.Content);
}
public override void VisitNamespace(NamespaceDeclarationIRNode node)
public override void VisitNamespaceDeclaration(NamespaceDeclarationIRNode node)
{
WriteContentNode(node, node.Content);
}
public override void VisitRazorMethodDeclaration(MethodDeclarationIRNode node)
public override void VisitMethodDeclaration(MethodDeclarationIRNode node)
{
WriteContentNode(node, node.AccessModifier, string.Join(", ", node.Modifiers ?? new List<string>()), node.ReturnType, node.Name);
}