Add RazorIRNodeReference for manipulating nodes
This commit is contained in:
parent
1fb3c8c26f
commit
6ce71c24e5
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
|||
internal static class ViewComponentResources
|
||||
{
|
||||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.CodeAnalysis.Razor.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
|
||||
= new ResourceManager("Microsoft.AspNetCore.Mvc.Razor.Extensions.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.
|
||||
|
|
|
|||
|
|
@ -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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
|
@ -9,7 +8,6 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||
{
|
||||
|
|
@ -37,9 +35,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var (node, parent) in visitor.CreateTagHelpers)
|
||||
foreach (var (parent, node) in visitor.CreateTagHelpers)
|
||||
{
|
||||
RewriteCreateNode(visitor.Namespace, visitor.Class, node, parent);
|
||||
RewriteCreateNode(visitor.Namespace, visitor.Class, (CreateTagHelperIRNode)node, parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +228,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
|||
|
||||
public NamespaceDeclarationIRNode Namespace { get; private set; }
|
||||
|
||||
public List<(CreateTagHelperIRNode node, RazorIRNode parent)> CreateTagHelpers { get; } = new List<(CreateTagHelperIRNode node, RazorIRNode parent)>();
|
||||
public List<RazorIRNodeReference> CreateTagHelpers { get; } = new List<RazorIRNodeReference>();
|
||||
|
||||
public Dictionary<string, TagHelperDescriptor> TagHelpers { get; } = new Dictionary<string, TagHelperDescriptor>();
|
||||
|
||||
|
|
@ -243,7 +241,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
|||
var vcName = tagHelper.Metadata[ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey];
|
||||
TagHelpers[vcName] = tagHelper;
|
||||
|
||||
CreateTagHelpers.Add((node, Parent));
|
||||
CreateTagHelpers.Add(new RazorIRNodeReference(Parent, node));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,25 +16,28 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var parserOptions = irDocument.Options;
|
||||
|
||||
var designTime = parserOptions.DesignTime;
|
||||
var walker = new DirectiveWalker();
|
||||
walker.VisitDocument(irDocument);
|
||||
|
||||
var classNode = walker.ClassNode;
|
||||
foreach (var (node, parent) in walker.FunctionsDirectiveNodes)
|
||||
var classNode = irDocument.FindPrimaryClass();
|
||||
if (classNode == null)
|
||||
{
|
||||
parent.Children.Remove(node);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var child in node.Children.Except(node.Tokens))
|
||||
foreach (var functions in irDocument.FindDirectiveReferences(CSharpCodeParser.FunctionsDirectiveDescriptor))
|
||||
{
|
||||
functions.Remove();
|
||||
|
||||
for (var i =0; i < functions.Node.Children.Count; i++)
|
||||
{
|
||||
classNode.Children.Add(child);
|
||||
classNode.Children.Add(functions.Node.Children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (node, parent) in walker.InheritsDirectiveNodes.Reverse())
|
||||
foreach (var inherits in irDocument.FindDirectiveReferences(CSharpCodeParser.InheritsDirectiveDescriptor).Reverse())
|
||||
{
|
||||
parent.Children.Remove(node);
|
||||
inherits.Remove();
|
||||
|
||||
var token = node.Tokens.FirstOrDefault();
|
||||
var token = ((DirectiveIRNode)inherits.Node).Tokens.FirstOrDefault();
|
||||
if (token != null)
|
||||
{
|
||||
classNode.BaseType = token.Content;
|
||||
|
|
@ -42,74 +45,30 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var (node, parent) in walker.SectionDirectiveNodes)
|
||||
foreach (var section in irDocument.FindDirectiveReferences(CSharpCodeParser.SectionDirectiveDescriptor))
|
||||
{
|
||||
var sectionIndex = parent.Children.IndexOf(node);
|
||||
parent.Children.Remove(node);
|
||||
|
||||
var defineSectionEndStatement = new CSharpCodeIRNode();
|
||||
RazorIRBuilder.Create(defineSectionEndStatement)
|
||||
.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = "});"
|
||||
});
|
||||
|
||||
parent.Children.Insert(sectionIndex, defineSectionEndStatement);
|
||||
|
||||
foreach (var child in node.Children.Except(node.Tokens).Reverse())
|
||||
{
|
||||
parent.Children.Insert(sectionIndex, child);
|
||||
}
|
||||
|
||||
var lambdaContent = designTime ? "__razor_section_writer" : string.Empty;
|
||||
var sectionName = node.Tokens.FirstOrDefault()?.Content;
|
||||
var defineSectionStartStatement = new CSharpCodeIRNode();
|
||||
RazorIRBuilder.Create(defineSectionStartStatement)
|
||||
.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = $"DefineSection(\"{sectionName}\", async ({lambdaContent}) => {{"
|
||||
});
|
||||
var sectionName = ((DirectiveIRNode)section.Node).Tokens.FirstOrDefault()?.Content;
|
||||
|
||||
parent.Children.Insert(sectionIndex, defineSectionStartStatement);
|
||||
}
|
||||
}
|
||||
|
||||
private class DirectiveWalker : RazorIRNodeWalker
|
||||
{
|
||||
public ClassDeclarationIRNode ClassNode { get; private set; }
|
||||
|
||||
public IList<(DirectiveIRNode node, RazorIRNode parent)> FunctionsDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>();
|
||||
|
||||
public IList<(DirectiveIRNode node, RazorIRNode parent)> InheritsDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>();
|
||||
|
||||
public IList<(DirectiveIRNode node, RazorIRNode parent)> SectionDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>();
|
||||
|
||||
public override void VisitClassDeclaration(ClassDeclarationIRNode node)
|
||||
{
|
||||
if (ClassNode == null)
|
||||
var builder = RazorIRBuilder.Create(new CSharpCodeIRNode());
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
ClassNode = node;
|
||||
}
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = $"DefineSection(\"{sectionName}\", async ({lambdaContent}) => {{"
|
||||
});
|
||||
section.InsertBefore(builder.Build());
|
||||
|
||||
section.InsertBefore(section.Node.Children.Except(((DirectiveIRNode)section.Node).Tokens));
|
||||
|
||||
VisitDefault(node);
|
||||
}
|
||||
builder = RazorIRBuilder.Create(new CSharpCodeIRNode());
|
||||
builder.Add(new RazorIRToken()
|
||||
{
|
||||
Kind = RazorIRToken.TokenKind.CSharp,
|
||||
Content = "});"
|
||||
});
|
||||
section.InsertAfter(builder.Build());
|
||||
|
||||
public override void VisitDirective(DirectiveIRNode node)
|
||||
{
|
||||
if (string.Equals(node.Name, CSharpCodeParser.FunctionsDirectiveDescriptor.Directive, StringComparison.Ordinal))
|
||||
{
|
||||
FunctionsDirectiveNodes.Add((node, Parent));
|
||||
}
|
||||
else if (string.Equals(node.Name, CSharpCodeParser.InheritsDirectiveDescriptor.Directive, StringComparison.Ordinal))
|
||||
{
|
||||
InheritsDirectiveNodes.Add((node, Parent));
|
||||
}
|
||||
else if (string.Equals(node.Name, CSharpCodeParser.SectionDirectiveDescriptor.Directive, StringComparison.Ordinal))
|
||||
{
|
||||
SectionDirectiveNodes.Add((node, Parent));
|
||||
}
|
||||
section.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// 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
|
||||
{
|
||||
|
|
@ -37,6 +38,23 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
return FindWithAnnotation<NamespaceDeclarationIRNode>(node, CommonAnnotations.PrimaryNamespace);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<RazorIRNodeReference> FindDirectiveReferences(this DocumentIRNode node, DirectiveDescriptor directive)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (directive == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(directive));
|
||||
}
|
||||
|
||||
var visitor = new DirectiveVisitor(directive);
|
||||
visitor.Visit(node);
|
||||
return visitor.Directives;
|
||||
}
|
||||
|
||||
private static T FindWithAnnotation<T>(RazorIRNode node, object annotation) where T : RazorIRNode
|
||||
{
|
||||
if (node is T target && object.ReferenceEquals(target.Annotations[annotation], annotation))
|
||||
|
|
@ -55,5 +73,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private class DirectiveVisitor : RazorIRNodeWalker
|
||||
{
|
||||
private readonly DirectiveDescriptor _directive;
|
||||
|
||||
public DirectiveVisitor(DirectiveDescriptor directive)
|
||||
{
|
||||
_directive = directive;
|
||||
}
|
||||
|
||||
public List<RazorIRNodeReference> Directives = new List<RazorIRNodeReference>();
|
||||
|
||||
public override void VisitDirective(DirectiveIRNode node)
|
||||
{
|
||||
if (_directive == node.Descriptor)
|
||||
{
|
||||
Directives.Add(new RazorIRNodeReference(Parent, node));
|
||||
}
|
||||
|
||||
base.VisitDirective(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,209 @@
|
|||
// 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 struct RazorIRNodeReference
|
||||
{
|
||||
public RazorIRNodeReference(RazorIRNode parent, RazorIRNode node)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parent));
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
Parent = parent;
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public void Deconstruct(out RazorIRNode parent, out RazorIRNode node)
|
||||
{
|
||||
parent = Parent;
|
||||
node = Node;
|
||||
}
|
||||
|
||||
public RazorIRNode Node { get; }
|
||||
|
||||
public RazorIRNode Parent { get; }
|
||||
|
||||
public RazorIRNodeReference InsertAfter(RazorIRNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
Parent.Children.Insert(index + 1, node);
|
||||
return new RazorIRNodeReference(Parent, node);
|
||||
}
|
||||
|
||||
public void InsertAfter(IEnumerable<RazorIRNode> nodes)
|
||||
{
|
||||
if (nodes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(nodes));
|
||||
}
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
Parent.Children.Insert(++index, node);
|
||||
}
|
||||
}
|
||||
|
||||
public RazorIRNodeReference InsertBefore(RazorIRNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
Parent.Children.Insert(index, node);
|
||||
return new RazorIRNodeReference(Parent, node);
|
||||
}
|
||||
|
||||
public void InsertBefore(IEnumerable<RazorIRNode> nodes)
|
||||
{
|
||||
if (nodes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(nodes));
|
||||
}
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
Parent.Children.Insert(index++, node);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
Parent.Children.RemoveAt(index);
|
||||
}
|
||||
|
||||
public RazorIRNodeReference Replace(RazorIRNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.IRNodeReference_NotInitialized);
|
||||
}
|
||||
|
||||
if (Parent.Children.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_CollectionIsReadOnly(Parent));
|
||||
}
|
||||
|
||||
var index = Parent.Children.IndexOf(Node);
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatIRNodeReference_NodeNotFound(
|
||||
Node,
|
||||
Parent));
|
||||
}
|
||||
|
||||
Parent.Children[index] = node;
|
||||
return new RazorIRNodeReference(Parent, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -458,6 +458,48 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
internal static string FormatKeyMustNotBeNull()
|
||||
=> GetString("KeyMustNotBeNull");
|
||||
|
||||
/// <summary>
|
||||
/// The reference is invalid. The node '{0}' could not be found as a child of '{1}'.
|
||||
/// </summary>
|
||||
internal static string IRNodeReference_NodeNotFound
|
||||
{
|
||||
get => GetString("IRNodeReference_NodeNotFound");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The reference is invalid. The node '{0}' could not be found as a child of '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatIRNodeReference_NodeNotFound(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("IRNodeReference_NodeNotFound"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// The reference is invalid. References initialized with the default constructor cannot modify nodes.
|
||||
/// </summary>
|
||||
internal static string IRNodeReference_NotInitialized
|
||||
{
|
||||
get => GetString("IRNodeReference_NotInitialized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The reference is invalid. References initialized with the default constructor cannot modify nodes.
|
||||
/// </summary>
|
||||
internal static string FormatIRNodeReference_NotInitialized()
|
||||
=> GetString("IRNodeReference_NotInitialized");
|
||||
|
||||
/// <summary>
|
||||
/// The node '{0}' has a read-only child collection and cannot be modified.
|
||||
/// </summary>
|
||||
internal static string IRNodeReference_CollectionIsReadOnly
|
||||
{
|
||||
get => GetString("IRNodeReference_CollectionIsReadOnly");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The node '{0}' has a read-only child collection and cannot be modified.
|
||||
/// </summary>
|
||||
internal static string FormatIRNodeReference_CollectionIsReadOnly(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("IRNodeReference_CollectionIsReadOnly"), p0);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -213,4 +213,13 @@
|
|||
<data name="KeyMustNotBeNull" xml:space="preserve">
|
||||
<value>The key must not be null.</value>
|
||||
</data>
|
||||
<data name="IRNodeReference_NodeNotFound" xml:space="preserve">
|
||||
<value>The reference is invalid. The node '{0}' could not be found as a child of '{1}'.</value>
|
||||
</data>
|
||||
<data name="IRNodeReference_NotInitialized" xml:space="preserve">
|
||||
<value>The reference is invalid. References initialized with the default constructor cannot modify nodes.</value>
|
||||
</data>
|
||||
<data name="IRNodeReference_CollectionIsReadOnly" xml:space="preserve">
|
||||
<value>The node '{0}' has a read-only child collection and cannot be modified.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -60,5 +60,54 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
// Assert
|
||||
Assert.Same(@namespace, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindDirectiveReferences_FindsMatchingDirectives()
|
||||
{
|
||||
// Arrange
|
||||
var directive = DirectiveDescriptor.CreateSingleLineDirective("test");
|
||||
var directive2 = DirectiveDescriptor.CreateSingleLineDirective("test");
|
||||
|
||||
var document = new DocumentIRNode();
|
||||
var @namespace = new NamespaceDeclarationIRNode();
|
||||
|
||||
var builder = RazorIRBuilder.Create(document);
|
||||
builder.Push(@namespace);
|
||||
|
||||
var match1 = new DirectiveIRNode()
|
||||
{
|
||||
Descriptor = directive,
|
||||
};
|
||||
builder.Add(match1);
|
||||
|
||||
var nonMatch = new DirectiveIRNode()
|
||||
{
|
||||
Descriptor = directive2,
|
||||
};
|
||||
builder.Add(nonMatch);
|
||||
|
||||
var match2 = new DirectiveIRNode()
|
||||
{
|
||||
Descriptor = directive,
|
||||
};
|
||||
builder.Add(match2);
|
||||
|
||||
// Act
|
||||
var results = document.FindDirectiveReferences(directive);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
results,
|
||||
r =>
|
||||
{
|
||||
Assert.Same(@namespace, r.Parent);
|
||||
Assert.Same(match1, r.Node);
|
||||
},
|
||||
r =>
|
||||
{
|
||||
Assert.Same(@namespace, r.Parent);
|
||||
Assert.Same(match2, r.Node);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,514 @@
|
|||
// 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.Intermediate
|
||||
{
|
||||
public class RazorIRNodeReferenceTest
|
||||
{
|
||||
[Fact]
|
||||
public void InsertAfter_SingleNode_AddsNodeAfterNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node3);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act
|
||||
reference.InsertAfter(node2);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_SingleNode_AddsNodeAfterNode_AtEnd()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node2);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node2);
|
||||
|
||||
// Act
|
||||
reference.InsertAfter(node3);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MultipleNodes_AddsNodesAfterNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
var node4 = new BasicIRNode("Node4");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node4);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act
|
||||
reference.InsertAfter(new[] { node2, node3 });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, node4, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MultipleNodes_AddsNodesAfterNode_AtEnd()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
var node4 = new BasicIRNode("Node4");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node2);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node2);
|
||||
|
||||
// Act
|
||||
reference.InsertAfter(new[] { node3, node4 });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, node4, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_SingleNode_AddsNodeBeforeNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node3);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node3);
|
||||
|
||||
// Act
|
||||
reference.InsertBefore(node2);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_SingleNode_AddsNodeBeforeNode_AtBeginning()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
|
||||
parent.Children.Add(node2);
|
||||
parent.Children.Add(node3);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node2);
|
||||
|
||||
// Act
|
||||
reference.InsertBefore(node1);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_MultipleNodes_AddsNodesBeforeNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
var node4 = new BasicIRNode("Node4");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node4);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node4);
|
||||
|
||||
// Act
|
||||
reference.InsertBefore(new[] { node2, node3 });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, node4, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MultipleNodes_AddsNodesBeforeNode_AtBeginning()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
var node4 = new BasicIRNode("Node4");
|
||||
|
||||
parent.Children.Add(node3);
|
||||
parent.Children.Add(node4);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node3);
|
||||
|
||||
// Act
|
||||
reference.InsertBefore(new[] { node1, node2 });
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, node4, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_RemovesNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node3);
|
||||
parent.Children.Add(node2);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node3);
|
||||
|
||||
// Act
|
||||
reference.Remove();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2,}, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_ReplacesNode()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
var node2 = new BasicIRNode("Node2");
|
||||
var node3 = new BasicIRNode("Node3");
|
||||
var node4 = new BasicIRNode("Node4");
|
||||
|
||||
parent.Children.Add(node1);
|
||||
parent.Children.Add(node4);
|
||||
parent.Children.Add(node3);
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node4);
|
||||
|
||||
// Act
|
||||
reference.Replace(node2);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(new[] { node1, node2, node3, }, parent.Children);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_SingleNode_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MulipleNodes_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_SingleNode_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_MulipleNodes_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Remove());
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_ThrowsForReferenceNotInitialized()
|
||||
{
|
||||
// Arrange
|
||||
var reference = new RazorIRNodeReference();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Replace(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. References initialized with the default constructor cannot modify nodes.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_SingleNode_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new BasicIRNode("_")));
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MulipleNodes_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_SingleNode_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new BasicIRNode("_")));
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_MulipleNodes_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Remove());
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_ThrowsForReadOnlyCollection()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent", ReadOnlyIRNodeCollection.Instance);
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Replace(new BasicIRNode("_")));
|
||||
Assert.Equal("The node 'Parent' has a read-only child collection and cannot be modified.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_SingleNode_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertAfter_MulipleNodes_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertAfter(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_SingleNode_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsertBefore_MulipleNodes_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.InsertBefore(new[] { new BasicIRNode("_") }));
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Remove());
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Replace_ThrowsForNodeNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var parent = new BasicIRNode("Parent");
|
||||
|
||||
var node1 = new BasicIRNode("Node1");
|
||||
|
||||
var reference = new RazorIRNodeReference(parent, node1);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => reference.Replace(new BasicIRNode("_")));
|
||||
Assert.Equal("The reference is invalid. The node 'Node1' could not be found as a child of 'Parent'.", exception.Message);
|
||||
}
|
||||
|
||||
private class BasicIRNode : RazorIRNode
|
||||
{
|
||||
public BasicIRNode(string name)
|
||||
: this(name, new DefaultIRNodeCollection())
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public BasicIRNode(string name, RazorIRNodeCollection children)
|
||||
{
|
||||
Name = name;
|
||||
Children = children;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public override ItemCollection Annotations { get; } = new DefaultItemCollection();
|
||||
|
||||
public override RazorIRNodeCollection Children { get; }
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||
|
|
@ -43,14 +44,68 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
Assert.Equal(nodes, walker.Visited.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IRNodeWalker_Visit_SetsParentAndAncestors()
|
||||
{
|
||||
// Arrange
|
||||
var walker = new DerivedIRNodeWalker();
|
||||
|
||||
var nodes = new RazorIRNode[]
|
||||
{
|
||||
new BasicIRNode("Root"),
|
||||
new BasicIRNode("Root->A"),
|
||||
new BasicIRNode("Root->B"),
|
||||
new BasicIRNode("Root->B->1"),
|
||||
new BasicIRNode("Root->B->2"),
|
||||
new BasicIRNode("Root->C"),
|
||||
};
|
||||
|
||||
var ancestors = new Dictionary<string, string[]>()
|
||||
{
|
||||
{ "Root", new string[]{ } },
|
||||
{ "Root->A", new string[] { "Root" } },
|
||||
{ "Root->B", new string[] { "Root" } },
|
||||
{ "Root->B->1", new string[] { "Root->B", "Root" } },
|
||||
{ "Root->B->2", new string[] { "Root->B", "Root" } },
|
||||
{ "Root->C", new string[] { "Root" } },
|
||||
};
|
||||
|
||||
walker.OnVisiting = (n) =>
|
||||
{
|
||||
Assert.Equal(ancestors[((BasicIRNode)n).Name], walker.Ancestors.Cast<BasicIRNode>().Select(b => b.Name));
|
||||
Assert.Equal(ancestors[((BasicIRNode)n).Name].FirstOrDefault(), ((BasicIRNode)walker.Parent)?.Name);
|
||||
};
|
||||
|
||||
var builder = new DefaultRazorIRBuilder();
|
||||
builder.Push(nodes[0]);
|
||||
builder.Add(nodes[1]);
|
||||
builder.Push(nodes[2]);
|
||||
builder.Add(nodes[3]);
|
||||
builder.Add(nodes[4]);
|
||||
builder.Pop();
|
||||
builder.Add(nodes[5]);
|
||||
|
||||
var root = builder.Pop();
|
||||
|
||||
// Act & Assert
|
||||
walker.Visit(root);
|
||||
}
|
||||
|
||||
private class DerivedIRNodeWalker : RazorIRNodeWalker
|
||||
{
|
||||
public new IEnumerable<RazorIRNode> Ancestors => base.Ancestors;
|
||||
|
||||
public new RazorIRNode Parent => base.Parent;
|
||||
|
||||
public List<RazorIRNode> Visited { get; } = new List<RazorIRNode>();
|
||||
|
||||
public Action<RazorIRNode> OnVisiting { get; set; }
|
||||
|
||||
public override void VisitDefault(RazorIRNode node)
|
||||
{
|
||||
Visited.Add(node);
|
||||
|
||||
OnVisiting?.Invoke(node);
|
||||
base.VisitDefault(node);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +115,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private class BasicIRNode : RazorIRNode
|
||||
{
|
||||
public BasicIRNode(string name)
|
||||
|
|
|
|||
Loading…
Reference in New Issue