From 503ba669d0646b78472095fca6506c699713b788 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 8 Jun 2017 18:51:22 -0700 Subject: [PATCH] Get rid of Parent from IR node --- .../InjectDirective.cs | 1 - .../InjectDirectiveIRNode.cs | 2 - .../InstrumentationPass.cs | 27 +++++----- .../ModelExpressionPass.cs | 1 - .../PagesPropertyInjectionPass.cs | 10 +--- .../ViewComponentTagHelperPass.cs | 20 ++++--- .../DesignTimeTagHelperWriter.cs | 20 +++++-- .../CodeGeneration/RuntimeTagHelperWriter.cs | 21 +++++--- .../DefaultDirectiveIRPass.cs | 33 ++++++------ .../DefaultRazorIRLoweringPhase.cs | 3 +- .../DirectiveRemovalIROptimizationPass.cs | 8 +-- .../Extensions/TemplateIRNode.cs | 4 +- ...reallocatedTagHelperHtmlAttributeIRNode.cs | 2 - .../AddTagHelperHtmlAttributeIRNode.cs | 3 -- .../CSharpCodeAttributeValueIRNode.cs | 3 -- .../Intermediate/CSharpCodeIRNode.cs | 3 -- .../CSharpExpressionAttributeValueIRNode.cs | 3 -- .../Intermediate/CSharpExpressionIRNode.cs | 3 -- .../Intermediate/ChecksumIRNode.cs | 2 - .../Intermediate/ClassDeclarationIRNode.cs | 2 - .../Intermediate/CreateTagHelperIRNode.cs | 3 -- ...arePreallocatedTagHelperAttributeIRNode.cs | 3 -- ...reallocatedTagHelperHtmlAttributeIRNode.cs | 3 -- .../DeclareTagHelperFieldsIRNode.cs | 2 - .../Intermediate/DefaultRazorIRBuilder.cs | 7 +-- .../Intermediate/DesignTimeDirectiveIRNode.cs | 3 -- .../Intermediate/DirectiveIRNode.cs | 3 -- .../Intermediate/DirectiveTokenIRNode.cs | 5 -- .../Intermediate/DocumentIRNode.cs | 3 -- .../Intermediate/FieldDeclarationIRNode.cs | 2 - .../Intermediate/HtmlAttributeIRNode.cs | 3 -- .../Intermediate/HtmlAttributeValueIRNode.cs | 2 - .../Intermediate/HtmlContentIRNode.cs | 2 - .../Intermediate/MethodDeclarationIRNode.cs | 2 - .../NamespaceDeclarationIRNode.cs | 3 -- .../Intermediate/PropertyDeclarationIRNode.cs | 2 - .../Intermediate/RazorIRNode.cs | 6 --- .../Intermediate/RazorIRNodeWalker.cs | 28 ++++++++-- .../Intermediate/RazorIRToken.cs | 2 - .../SetPreallocatedTagHelperPropertyIRNode.cs | 4 -- .../SetTagHelperPropertyIRNode.cs | 3 -- .../Intermediate/TagHelperBodyIRNode.cs | 3 -- .../Intermediate/TagHelperIRNode.cs | 3 -- .../Intermediate/UsingStatementIRNode.cs | 3 -- ...Microsoft.AspNetCore.Razor.Language.csproj | 6 ++- ...catedTagHelperAttributeOptimizationPass.cs | 12 ++--- .../RemovePragmaChecksumFeature.cs | 6 +-- .../NamespaceDirectiveTest.cs | 3 -- .../DesignTimeBasicWriterTest.cs | 2 - .../CodeGeneration/RuntimeBasicWriterTest.cs | 3 -- .../Intermediate/DefaultRazorIRBuilderTest.cs | 16 ++---- .../Intermediate/ExtensionIRNodeTest.cs | 1 - .../Intermediate/RazorIRNodeWalkerTest.cs | 2 - .../IntegrationTests/RazorIRNodeVerifier.cs | 53 ++++++++++--------- .../Langauge/Intermediate/RazorIRAssert.cs | 30 ++++++++--- 55 files changed, 169 insertions(+), 236 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirective.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirective.cs index e0a93785c6..c859f4a431 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirective.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirective.cs @@ -59,7 +59,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { TypeName = typeName, MemberName = memberName, - Parent = visitor.Class, }; visitor.Class.Children.Add(injectNode); diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirectiveIRNode.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirectiveIRNode.cs index 57b2770065..ec0b6af280 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirectiveIRNode.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InjectDirectiveIRNode.cs @@ -16,8 +16,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs index 1ae1ef0969..e03777add1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs @@ -30,10 +30,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions var beginContextMethodName = "BeginContext"; /* ORIGINAL: BeginContextMethodName */ var endContextMethodName = "EndContext"; /* ORIGINAL: EndContextMethodName */ - var beginNode = new CSharpCodeIRNode() - { - Parent = item.Node.Parent - }; + var beginNode = new CSharpCodeIRNode(); RazorIRBuilder.Create(beginNode) .Add(new RazorIRToken() { @@ -45,10 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions item.IsLiteral ? "true" : "false") }); - var endNode = new CSharpCodeIRNode() - { - Parent = item.Node.Parent - }; + var endNode = new CSharpCodeIRNode(); RazorIRBuilder.Create(endNode) .Add(new RazorIRToken() { @@ -56,22 +50,25 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions Content = string.Format("{0}();", endContextMethodName) }); - var nodeIndex = item.Node.Parent.Children.IndexOf(item.Node); - item.Node.Parent.Children.Insert(nodeIndex, beginNode); - item.Node.Parent.Children.Insert(nodeIndex + 2, endNode); + var nodeIndex = item.Parent.Children.IndexOf(item.Node); + item.Parent.Children.Insert(nodeIndex, beginNode); + item.Parent.Children.Insert(nodeIndex + 2, endNode); } private struct InstrumentationItem { - public InstrumentationItem(RazorIRNode node, bool isLiteral, SourceSpan source) + public InstrumentationItem(RazorIRNode node, RazorIRNode parent, bool isLiteral, SourceSpan source) { Node = node; + Parent = parent; IsLiteral = isLiteral; Source = source; } public RazorIRNode Node { get; } + public RazorIRNode Parent { get; } + public bool IsLiteral { get; } public SourceSpan Source { get; } @@ -85,7 +82,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { if (node.Source != null) { - Items.Add(new InstrumentationItem(node, isLiteral: true, source: node.Source.Value)); + Items.Add(new InstrumentationItem(node, Parent, isLiteral: true, source: node.Source.Value)); } VisitDefault(node); @@ -95,7 +92,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { if (node.Source != null) { - Items.Add(new InstrumentationItem(node, isLiteral: false, source: node.Source.Value)); + Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value)); } VisitDefault(node); @@ -105,7 +102,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions { if (node.Source != null) { - Items.Add(new InstrumentationItem(node, isLiteral: false, source: node.Source.Value)); + Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value)); } VisitDefault(node); diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ModelExpressionPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ModelExpressionPass.cs index 1b4a402f1a..73a9a47493 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ModelExpressionPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ModelExpressionPass.cs @@ -79,7 +79,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions node.Children.Clear(); node.Children.Add(expression); - expression.Parent = node; } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/PagesPropertyInjectionPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/PagesPropertyInjectionPass.cs index ebfffc63ee..65a51559e7 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/PagesPropertyInjectionPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/PagesPropertyInjectionPass.cs @@ -22,10 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions var @class = visitor.Class; var viewDataType = $"global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<{modelType}>"; - var vddProperty = new CSharpCodeIRNode() - { - Parent = @class - }; + var vddProperty = new CSharpCodeIRNode(); RazorIRBuilder.Create(vddProperty) .Add(new RazorIRToken() { @@ -34,10 +31,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions }); @class.Children.Add(vddProperty); - var modelProperty = new CSharpCodeIRNode() - { - Parent = @class - }; + var modelProperty = new CSharpCodeIRNode(); RazorIRBuilder.Create(modelProperty) .Add(new RazorIRToken() { diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperPass.cs index 9bc4dd44a0..950306dd97 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperPass.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/ViewComponentTagHelperPass.cs @@ -37,9 +37,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions } } - foreach (var createNode in visitor.CreateTagHelpers) + foreach (var (node, parent) in visitor.CreateTagHelpers) { - RewriteCreateNode(visitor.Namespace, visitor.Class, createNode); + RewriteCreateNode(visitor.Namespace, visitor.Class, node, parent); } } @@ -48,10 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions var writer = new CSharpCodeWriter(); WriteClass(writer, tagHelper); - var statement = new CSharpCodeIRNode() - { - Parent = @class - }; + var statement = new CSharpCodeIRNode(); RazorIRBuilder.Create(statement) .Add(new RazorIRToken() { @@ -65,12 +62,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions private void RewriteCreateNode( NamespaceDeclarationIRNode @namespace, ClassDeclarationIRNode @class, - CreateTagHelperIRNode node) + CreateTagHelperIRNode node, + RazorIRNode parent) { var newTypeName = GetVCTHFullName(@namespace, @class, node.Descriptor); - for (var i = 0; i < node.Parent.Children.Count; i++) + for (var i = 0; i < parent.Children.Count; i++) { - if (node.Parent.Children[i] is SetTagHelperPropertyIRNode setProperty && + if (parent.Children[i] is SetTagHelperPropertyIRNode setProperty && node.Descriptor.BoundAttributes.Contains(setProperty.Descriptor)) { setProperty.TagHelperTypeName = newTypeName; @@ -232,7 +230,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions public NamespaceDeclarationIRNode Namespace { get; private set; } - public List CreateTagHelpers { get; } = new List(); + public List<(CreateTagHelperIRNode node, RazorIRNode parent)> CreateTagHelpers { get; } = new List<(CreateTagHelperIRNode node, RazorIRNode parent)>(); public Dictionary TagHelpers { get; } = new Dictionary(); @@ -245,7 +243,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions var vcName = tagHelper.Metadata[ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey]; TagHelpers[vcName] = tagHelper; - CreateTagHelpers.Add(node); + CreateTagHelpers.Add((node, Parent)); } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeTagHelperWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeTagHelperWriter.cs index 2843b9e356..330daa7e49 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeTagHelperWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/DesignTimeTagHelperWriter.cs @@ -136,14 +136,26 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration private void RenderTagHelperAttributeInline( CSharpRenderingContext context, + SetTagHelperPropertyIRNode property, + SourceSpan documentLocation) + { + for (var i = 0; i < property.Children.Count; i++) + { + RenderTagHelperAttributeInline(context, property, property.Children[i], documentLocation); + } + } + + private void RenderTagHelperAttributeInline( + CSharpRenderingContext context, + SetTagHelperPropertyIRNode property, RazorIRNode node, SourceSpan documentLocation) { - if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode || node is HtmlContentIRNode) + if (node is CSharpExpressionIRNode || node is HtmlContentIRNode) { for (var i = 0; i < node.Children.Count; i++) { - RenderTagHelperAttributeInline(context, node.Children[i], documentLocation); + RenderTagHelperAttributeInline(context, property, node.Children[i], documentLocation); } } else if (node is RazorIRToken token) @@ -165,9 +177,9 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration } else if (node is TemplateIRNode) { - var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent; + var expectedTypeName = property.IsIndexerNameMatch ? property.Descriptor.IndexerTypeName : property.Descriptor.TypeName; var error = new RazorError( - LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(attributeValueNode.Descriptor.TypeName), + LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(expectedTypeName), new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length), documentLocation.Length); context.Diagnostics.Add(RazorDiagnostic.Create(error)); diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs index acf5d74d4e..7bdca9f791 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/RuntimeTagHelperWriter.cs @@ -421,14 +421,26 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration private void RenderTagHelperAttributeInline( CSharpRenderingContext context, + SetTagHelperPropertyIRNode property, + SourceSpan documentLocation) + { + for (var i = 0; i < property.Children.Count; i++) + { + RenderTagHelperAttributeInline(context, property, property.Children[i], documentLocation); + } + } + + private void RenderTagHelperAttributeInline( + CSharpRenderingContext context, + SetTagHelperPropertyIRNode property, RazorIRNode node, SourceSpan documentLocation) { - if (node is SetTagHelperPropertyIRNode || node is CSharpExpressionIRNode || node is HtmlContentIRNode) + if (node is CSharpExpressionIRNode || node is HtmlContentIRNode) { for (var i = 0; i < node.Children.Count; i++) { - RenderTagHelperAttributeInline(context, node.Children[i], documentLocation); + RenderTagHelperAttributeInline(context, property, node.Children[i], documentLocation); } } else if (node is RazorIRToken token) @@ -445,10 +457,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration } else if (node is TemplateIRNode) { - var attributeValueNode = (SetTagHelperPropertyIRNode)node.Parent; - var expectedTypeName = attributeValueNode.IsIndexerNameMatch ? - attributeValueNode.Descriptor.IndexerTypeName : - attributeValueNode.Descriptor.TypeName; + var expectedTypeName = property.IsIndexerNameMatch ? property.Descriptor.IndexerTypeName : property.Descriptor.TypeName; var error = new RazorError( LegacyResources.FormatTagHelpers_InlineMarkupBlocks_NotSupported_InAttributes(expectedTypeName), new SourceLocation(documentLocation.AbsoluteIndex, documentLocation.CharacterIndex, documentLocation.Length), diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveIRPass.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveIRPass.cs index c0d5c1cbbe..4968b75f09 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveIRPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveIRPass.cs @@ -20,20 +20,19 @@ namespace Microsoft.AspNetCore.Razor.Language walker.VisitDocument(irDocument); var classNode = walker.ClassNode; - foreach (var node in walker.FunctionsDirectiveNodes) + foreach (var (node, parent) in walker.FunctionsDirectiveNodes) { - node.Parent.Children.Remove(node); + parent.Children.Remove(node); foreach (var child in node.Children.Except(node.Tokens)) { - child.Parent = classNode; classNode.Children.Add(child); } } - foreach (var node in walker.InheritsDirectiveNodes.Reverse()) + foreach (var (node, parent) in walker.InheritsDirectiveNodes.Reverse()) { - node.Parent.Children.Remove(node); + parent.Children.Remove(node); var token = node.Tokens.FirstOrDefault(); if (token != null) @@ -43,10 +42,10 @@ namespace Microsoft.AspNetCore.Razor.Language } } - foreach (var node in walker.SectionDirectiveNodes) + foreach (var (node, parent) in walker.SectionDirectiveNodes) { - var sectionIndex = node.Parent.Children.IndexOf(node); - node.Parent.Children.Remove(node); + var sectionIndex = parent.Children.IndexOf(node); + parent.Children.Remove(node); var defineSectionEndStatement = new CSharpCodeIRNode(); RazorIRBuilder.Create(defineSectionEndStatement) @@ -56,11 +55,11 @@ namespace Microsoft.AspNetCore.Razor.Language Content = "});" }); - node.Parent.Children.Insert(sectionIndex, defineSectionEndStatement); + parent.Children.Insert(sectionIndex, defineSectionEndStatement); foreach (var child in node.Children.Except(node.Tokens).Reverse()) { - node.Parent.Children.Insert(sectionIndex, child); + parent.Children.Insert(sectionIndex, child); } var lambdaContent = designTime ? "__razor_section_writer" : string.Empty; @@ -73,7 +72,7 @@ namespace Microsoft.AspNetCore.Razor.Language Content = $"DefineSection(\"{sectionName}\", async ({lambdaContent}) => {{" }); - node.Parent.Children.Insert(sectionIndex, defineSectionStartStatement); + parent.Children.Insert(sectionIndex, defineSectionStartStatement); } } @@ -81,11 +80,11 @@ namespace Microsoft.AspNetCore.Razor.Language { public ClassDeclarationIRNode ClassNode { get; private set; } - public IList FunctionsDirectiveNodes { get; } = new List(); + public IList<(DirectiveIRNode node, RazorIRNode parent)> FunctionsDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>(); - public IList InheritsDirectiveNodes { get; } = new List(); + public IList<(DirectiveIRNode node, RazorIRNode parent)> InheritsDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>(); - public IList SectionDirectiveNodes { get; } = new List(); + public IList<(DirectiveIRNode node, RazorIRNode parent)> SectionDirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>(); public override void VisitClassDeclaration(ClassDeclarationIRNode node) { @@ -101,15 +100,15 @@ namespace Microsoft.AspNetCore.Razor.Language { if (string.Equals(node.Name, CSharpCodeParser.FunctionsDirectiveDescriptor.Directive, StringComparison.Ordinal)) { - FunctionsDirectiveNodes.Add(node); + FunctionsDirectiveNodes.Add((node, Parent)); } else if (string.Equals(node.Name, CSharpCodeParser.InheritsDirectiveDescriptor.Directive, StringComparison.Ordinal)) { - InheritsDirectiveNodes.Add(node); + InheritsDirectiveNodes.Add((node, Parent)); } else if (string.Equals(node.Name, CSharpCodeParser.SectionDirectiveDescriptor.Directive, StringComparison.Ordinal)) { - SectionDirectiveNodes.Add(node); + SectionDirectiveNodes.Add((node, Parent)); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs index e1aa470d32..b71f8d5ec8 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs @@ -551,7 +551,6 @@ namespace Microsoft.AspNetCore.Razor.Language Content = span.Content, Kind = RazorIRToken.TokenKind.Html, Source = BuildSourceSpanFromNode(span), - Parent = node }); if (node.Source != null) @@ -571,7 +570,7 @@ namespace Microsoft.AspNetCore.Razor.Language { if (_tagHelperFields == null) { - _tagHelperFields = new DeclareTagHelperFieldsIRNode() { Parent = _document, }; + _tagHelperFields = new DeclareTagHelperFieldsIRNode(); _document.Children.Add(_tagHelperFields); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs b/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs index 28033645fa..00a0935767 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs @@ -15,19 +15,19 @@ namespace Microsoft.AspNetCore.Razor.Language var visitor = new Visitor(); visitor.VisitDocument(irDocument); - foreach (var node in visitor.DirectiveNodes) + foreach (var (node, parent) in visitor.DirectiveNodes) { - node.Parent.Children.Remove(node); + parent.Children.Remove(node); } } private class Visitor : RazorIRNodeWalker { - public IList DirectiveNodes { get; } = new List(); + public IList<(DirectiveIRNode node, RazorIRNode parent)> DirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>(); public override void VisitDirective(DirectiveIRNode node) { - DirectiveNodes.Add(node); + DirectiveNodes.Add((node, Parent)); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Extensions/TemplateIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Extensions/TemplateIRNode.cs index cde0ecb2eb..3bc0554e45 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Extensions/TemplateIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Extensions/TemplateIRNode.cs @@ -10,9 +10,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions public sealed class TemplateIRNode : ExtensionIRNode { public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - - public override RazorIRNode Parent { get; set; } - + public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs index 0e79381bbf..18596049ea 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs @@ -10,8 +10,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string VariableName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddTagHelperHtmlAttributeIRNode.cs index f57ac7a7e9..a3a8b274db 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/AddTagHelperHtmlAttributeIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.Legacy; namespace Microsoft.AspNetCore.Razor.Language.Intermediate @@ -13,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Name { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeAttributeValueIRNode.cs index 87c0d7a51f..540fafb96c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeAttributeValueIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Prefix { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeIRNode.cs index 293bcd0e41..eb17780042 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpCodeIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -25,8 +24,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs index 08066000e5..0368bd6d94 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionAttributeValueIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Prefix { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionIRNode.cs index bbe51d6842..bccaf88d15 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CSharpExpressionIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -25,8 +24,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs index a18908683c..f6d77a3573 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs @@ -11,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Bytes { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIRNode.cs index 1e72a55154..f6745bdaa3 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ClassDeclarationIRNode.cs @@ -25,8 +25,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string AccessModifier { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CreateTagHelperIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CreateTagHelperIRNode.cs index f8f954c348..05e4181145 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CreateTagHelperIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/CreateTagHelperIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string TagHelperTypeName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs index 6e7a6a9902..7d1aa90e6a 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.Legacy; @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string VariableName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs index 347ec21fe6..9c87931564 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.Legacy; @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string VariableName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclareTagHelperFieldsIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclareTagHelperFieldsIRNode.cs index 9684c03102..c776f73217 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclareTagHelperFieldsIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DeclareTagHelperFieldsIRNode.cs @@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public ISet UsedTagHelperTypeNames { get; set; } = new HashSet(StringComparer.Ordinal); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DefaultRazorIRBuilder.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DefaultRazorIRBuilder.cs index 8564771a10..012744b50e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DefaultRazorIRBuilder.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DefaultRazorIRBuilder.cs @@ -30,8 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { throw new ArgumentNullException(nameof(node)); } - - node.Parent = Current; + Current.Children.Add(node); } @@ -41,8 +40,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { throw new ArgumentOutOfRangeException(nameof(index)); } - - node.Parent = Current; + if (index == Current.Children.Count) { // Allow inserting at 'Children.Count' to be friendlier than List<> typically is. @@ -95,7 +93,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate if (_depth > 0) { var parent = _stack[_depth - 1]; - node.Parent = parent; parent.Children.Add(node); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DesignTimeDirectiveIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DesignTimeDirectiveIRNode.cs index 148810f661..30b0392995 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DesignTimeDirectiveIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DesignTimeDirectiveIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.CodeGeneration; namespace Microsoft.AspNetCore.Razor.Language.Intermediate @@ -11,8 +10,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveIRNode.cs index 56386f7b9c..dbee2e7152 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveIRNode.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.AspNetCore.Razor.Language.Legacy; namespace Microsoft.AspNetCore.Razor.Language.Intermediate { @@ -26,8 +25,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Name { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveTokenIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveTokenIRNode.cs index 7d9146e1b2..c55097ee6e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveTokenIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DirectiveTokenIRNode.cs @@ -1,9 +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; - namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public sealed class DirectiveTokenIRNode : RazorIRNode @@ -12,8 +9,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Content { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DocumentIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DocumentIRNode.cs index 1b2acd11df..4217de8f06 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DocumentIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/DocumentIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.CodeGeneration; namespace Microsoft.AspNetCore.Razor.Language.Intermediate @@ -30,8 +29,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public RazorCodeGenerationOptions Options { get; set; } - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public CodeTarget Target { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/FieldDeclarationIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/FieldDeclarationIRNode.cs index 862b2311d2..9e82492900 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/FieldDeclarationIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/FieldDeclarationIRNode.cs @@ -27,8 +27,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public IList Modifiers { get; set; } = new List(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string AccessModifier { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeIRNode.cs index e0de6e025f..8101bf6e1c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Name { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs index 2c461c7b8c..a47aaca684 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlAttributeValueIRNode.cs @@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Prefix { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlContentIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlContentIRNode.cs index 5a85f33723..68d368e29e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlContentIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/HtmlContentIRNode.cs @@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MethodDeclarationIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MethodDeclarationIRNode.cs index 75306499af..b2a02ad0c0 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MethodDeclarationIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MethodDeclarationIRNode.cs @@ -25,8 +25,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string AccessModifier { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/NamespaceDeclarationIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/NamespaceDeclarationIRNode.cs index 6f88829eba..940cb3474e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/NamespaceDeclarationIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/NamespaceDeclarationIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -25,8 +24,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Content { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/PropertyDeclarationIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/PropertyDeclarationIRNode.cs index 004b9933bb..9568689bcc 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/PropertyDeclarationIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/PropertyDeclarationIRNode.cs @@ -27,8 +27,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public IList Modifiers { get; set; } = new List(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string AccessModifier { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNode.cs index b23e4bd0a4..b56bc4472a 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNode.cs @@ -1,20 +1,14 @@ // 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.Collections.Generic; - namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public abstract class RazorIRNode { - internal static readonly RazorIRNode[] EmptyArray = new RazorIRNode[0]; - public abstract ItemCollection Annotations { get; } public abstract RazorIRNodeCollection Children { get; } - public abstract RazorIRNode Parent { get; set; } - public abstract SourceSpan? Source { get; set; } public abstract void Accept(RazorIRNodeVisitor visitor); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeWalker.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeWalker.cs index 047b2d09b0..9cb437110e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeWalker.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeWalker.cs @@ -1,17 +1,39 @@ // 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.Collections.Generic; + namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public abstract class RazorIRNodeWalker : RazorIRNodeVisitor { + private readonly Stack _ancestors = new Stack(); + + protected IEnumerable Ancestors => _ancestors; + + protected RazorIRNode Parent => _ancestors.Count > 0 ? _ancestors.Peek() : null; + public override void VisitDefault(RazorIRNode node) { var children = node.Children; - for (var i = 0; i < node.Children.Count; i++) + if (node.Children.Count == 0) { - var child = children[i]; - Visit(child); + return; + } + + _ancestors.Push(node); + + try + { + for (var i = 0; i < node.Children.Count; i++) + { + var child = children[i]; + Visit(child); + } + } + finally + { + _ancestors.Pop(); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRToken.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRToken.cs index 8f56e0f8f2..60ca7ff606 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRToken.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRToken.cs @@ -19,8 +19,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public TokenKind Kind { get; set; } = TokenKind.Unknown; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs index 08fba87438..c11d4109f3 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs @@ -2,9 +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; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; -using Microsoft.AspNetCore.Razor.Language.Legacy; namespace Microsoft.AspNetCore.Razor.Language.Intermediate { @@ -12,8 +10,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string VariableName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetTagHelperPropertyIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetTagHelperPropertyIRNode.cs index 6e503fbd18..f20067389e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetTagHelperPropertyIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/SetTagHelperPropertyIRNode.cs @@ -2,7 +2,6 @@ // 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.Language.Legacy; namespace Microsoft.AspNetCore.Razor.Language.Intermediate @@ -13,8 +12,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string TagHelperTypeName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperBodyIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperBodyIRNode.cs index feac7431be..4410886554 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperBodyIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperBodyIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperIRNode.cs index 7a40379e81..8560f1f9dc 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/TagHelperIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -25,8 +24,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string TagName { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/UsingStatementIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/UsingStatementIRNode.cs index 41d942395b..09f1573c12 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/UsingStatementIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/UsingStatementIRNode.cs @@ -2,7 +2,6 @@ // 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 { @@ -12,8 +11,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public string Content { get; set; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj b/src/Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj index 07659cb71c..5f22e929dd 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj +++ b/src/Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj @@ -11,7 +11,11 @@ - + + + + + diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorPreallocatedTagHelperAttributeOptimizationPass.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorPreallocatedTagHelperAttributeOptimizationPass.cs index ceab49f05a..64609d0703 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorPreallocatedTagHelperAttributeOptimizationPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorPreallocatedTagHelperAttributeOptimizationPass.cs @@ -72,7 +72,6 @@ namespace Microsoft.AspNetCore.Razor.Language Name = node.Name, Value = plainTextValue, ValueStyle = node.ValueStyle, - Parent = _classDeclaration }; _classDeclaration.Children.Insert(_preallocatedDeclarationCount++, declaration); } @@ -80,11 +79,10 @@ namespace Microsoft.AspNetCore.Razor.Language var addPreAllocatedAttribute = new AddPreallocatedTagHelperHtmlAttributeIRNode { VariableName = declaration.VariableName, - Parent = node.Parent }; - var nodeIndex = node.Parent.Children.IndexOf(node); - node.Parent.Children[nodeIndex] = addPreAllocatedAttribute; + var nodeIndex = Parent.Children.IndexOf(node); + Parent.Children[nodeIndex] = addPreAllocatedAttribute; } public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node) @@ -127,7 +125,6 @@ namespace Microsoft.AspNetCore.Razor.Language Name = node.AttributeName, Value = plainTextValue, ValueStyle = node.ValueStyle, - Parent = _classDeclaration }; _classDeclaration.Children.Insert(_preallocatedDeclarationCount++, declaration); } @@ -140,12 +137,11 @@ namespace Microsoft.AspNetCore.Razor.Language PropertyName = node.PropertyName, Descriptor = node.Descriptor, Binding = node.Binding, - Parent = node.Parent, IsIndexerNameMatch = node.IsIndexerNameMatch, }; - var nodeIndex = node.Parent.Children.IndexOf(node); - node.Parent.Children[nodeIndex] = setPreallocatedProperty; + var nodeIndex = Parent.Children.IndexOf(node); + Parent.Children[nodeIndex] = setPreallocatedProperty; } private string GetContent(HtmlContentIRNode node) diff --git a/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs index b6eae1d18f..4b36929a6f 100644 --- a/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs +++ b/src/RazorPageGenerator/RemovePragmaChecksumFeature.cs @@ -13,16 +13,16 @@ namespace RazorPageGenerator var walker = new Walker(); walker.Visit(irDocument); - walker.ChecksumNode.Parent.Children.Remove(walker.ChecksumNode); + walker.Checksum.parent.Children.Remove(walker.Checksum.node); } private class Walker : RazorIRNodeWalker { - public ChecksumIRNode ChecksumNode { get; private set; } + public (ChecksumIRNode node, RazorIRNode parent) Checksum { get; private set; } public override void VisitChecksum(ChecksumIRNode node) { - ChecksumNode = node; + Checksum = (node, Parent); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/NamespaceDirectiveTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/NamespaceDirectiveTest.cs index 32e329d405..d90f707642 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/NamespaceDirectiveTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/NamespaceDirectiveTest.cs @@ -41,7 +41,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions Source = new SourceSpan(imports, 0, 0, 0, 0), }; node.Children.Add(new DirectiveTokenIRNode() { Content = string.Empty }); - node.Children[0].Parent = node; // Act var computed = NamespaceDirective.TryComputeNamespace(source, node, out var @namespace); @@ -71,7 +70,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions }; node.Children.Add(new DirectiveTokenIRNode() { Content = "Base" }); - node.Children[0].Parent = node; // Act var computed = NamespaceDirective.TryComputeNamespace(source, node, out var @namespace); @@ -102,7 +100,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions }; node.Children.Add(new DirectiveTokenIRNode() { Content = "Base" }); - node.Children[0].Parent = node; // Act var computed = NamespaceDirective.TryComputeNamespace(source, node, out var @namespace); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs index 4707b6a2e1..792d86af17 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeBasicWriterTest.cs @@ -551,8 +551,6 @@ Render Node - CSharpExpressionIRNode { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs index e6345dc757..6dc0210641 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeBasicWriterTest.cs @@ -445,7 +445,6 @@ if (true) { } { Content = "SomeContent", Kind = RazorIRToken.TokenKind.Html, - Parent = node }); // Act @@ -476,7 +475,6 @@ if (true) { } { Content = new string('*', 2000), Kind = RazorIRToken.TokenKind.Html, - Parent = node }); // Act @@ -652,7 +650,6 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get; set; } public override SourceSpan? Source { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/DefaultRazorIRBuilderTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/DefaultRazorIRBuilderTest.cs index 8002f65c71..3595d3e15e 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/DefaultRazorIRBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/DefaultRazorIRBuilderTest.cs @@ -34,11 +34,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(node, builder.Current); - Assert.Null(node.Parent); } [Fact] - public void Push_WhenNonEmpty_SetsUpParentAndChild() + public void Push_WhenNonEmpty_SetsUpChild() { // Arrange var builder = new DefaultRazorIRBuilder(); @@ -53,7 +52,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(node, builder.Current); - Assert.Same(parent, node.Parent); Assert.Collection(parent.Children, n => Assert.Same(node, n)); } @@ -122,12 +120,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(parent, builder.Current); - Assert.Same(parent, node.Parent); Assert.Collection(parent.Children, n => Assert.Same(node, n)); } [Fact] - public void Insert_AddsToChildrenAndSetsParent_EmptyCollection() + public void Insert_AddsToChildren_EmptyCollection() { // Arrange var builder = new DefaultRazorIRBuilder(); @@ -142,12 +139,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(parent, builder.Current); - Assert.Same(parent, node.Parent); Assert.Collection(parent.Children, n => Assert.Same(node, n)); } [Fact] - public void Insert_AddsToChildrenAndSetsParent_NonEmpyCollection() + public void Insert_AddsToChildren_NonEmpyCollection() { // Arrange var builder = new DefaultRazorIRBuilder(); @@ -165,12 +161,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(parent, builder.Current); - Assert.Same(parent, node.Parent); Assert.Collection(parent.Children, n => Assert.Same(node, n), n => Assert.Same(child, n)); } [Fact] - public void Insert_AddsToChildrenAndSetsParent_NonEmpyCollection_AtEnd() + public void Insert_AddsToChildren_NonEmpyCollection_AtEnd() { // Arrange var builder = new DefaultRazorIRBuilder(); @@ -188,7 +183,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate // Assert Assert.Same(parent, builder.Current); - Assert.Same(parent, node.Parent); Assert.Collection(parent.Children, n => Assert.Same(child, n), n => Assert.Same(node, n)); } @@ -218,8 +212,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/ExtensionIRNodeTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/ExtensionIRNodeTest.cs index ce7f3cadff..9f1d301d3b 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/ExtensionIRNodeTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/ExtensionIRNodeTest.cs @@ -46,7 +46,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance; - public override RazorIRNode Parent { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public override SourceSpan? Source { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/RazorIRNodeWalkerTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/RazorIRNodeWalkerTest.cs index 7fd0e59762..3d143571da 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/RazorIRNodeWalkerTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Intermediate/RazorIRNodeWalkerTest.cs @@ -74,8 +74,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection(); - public override RazorIRNode Parent { get; set; } - public override SourceSpan? Source { get; set; } public override void Accept(RazorIRNodeVisitor visitor) diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/IntegrationTests/RazorIRNodeVerifier.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/IntegrationTests/RazorIRNodeVerifier.cs index 3b34bb5ecb..fee0773c56 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/IntegrationTests/RazorIRNodeVerifier.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/IntegrationTests/RazorIRNodeVerifier.cs @@ -2,7 +2,9 @@ // 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.IO; +using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Xunit; @@ -47,7 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests _visitor.Visit(node); var actual = _writer.GetStringBuilder().ToString(); - AssertNodeEquals(node, expected, actual); + AssertNodeEquals(node, Ancestors, expected, actual); _visitor.Depth++; base.VisitDefault(node); @@ -60,7 +62,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests Assert.True(_baseline.Length == _index, "Not all lines of the baseline were visited!"); } - private void AssertNodeEquals(RazorIRNode node, string expected, string actual) + private void AssertNodeEquals(RazorIRNode node, IEnumerable ancestors, string expected, string actual) { if (string.Equals(expected, actual)) { @@ -71,21 +73,21 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests if (expected == null) { var message = "The node is missing from baseline."; - throw new IRBaselineException(node, expected, actual, message); + throw new IRBaselineException(node, Ancestors.ToArray(), expected, actual, message); } int charsVerified = 0; - AssertNestingEqual(node, expected, actual, ref charsVerified); - AssertNameEqual(node, expected, actual, ref charsVerified); + AssertNestingEqual(node, ancestors, expected, actual, ref charsVerified); + AssertNameEqual(node, ancestors, expected, actual, ref charsVerified); AssertDelimiter(node, expected, actual, true, ref charsVerified); - AssertLocationEqual(node, expected, actual, ref charsVerified); + AssertLocationEqual(node, ancestors, expected, actual, ref charsVerified); AssertDelimiter(node, expected, actual, false, ref charsVerified); - AssertContentEqual(node, expected, actual, ref charsVerified); + AssertContentEqual(node, ancestors, expected, actual, ref charsVerified); throw new InvalidOperationException("We can't figure out HOW these two things are different. This is a bug."); } - private void AssertNestingEqual(RazorIRNode node, string expected, string actual, ref int charsVerified) + private void AssertNestingEqual(RazorIRNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) { var i = 0; for (; i < expected.Length; i++) @@ -115,13 +117,13 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests if (failed) { var message = "The node is at the wrong level of nesting. This usually means a child is missing."; - throw new IRBaselineException(node, expected, actual, message); + throw new IRBaselineException(node, ancestors.ToArray(), expected, actual, message); } charsVerified = j; } - private void AssertNameEqual(RazorIRNode node, string expected, string actual, ref int charsVerified) + private void AssertNameEqual(RazorIRNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) { var expectedName = GetName(expected, charsVerified); var actualName = GetName(actual, charsVerified); @@ -129,7 +131,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests if (!string.Equals(expectedName, actualName)) { var message = $"Node names are not equal."; - throw new IRBaselineException(node, expected, actual, message); + throw new IRBaselineException(node, ancestors.ToArray(), expected, actual, message); } charsVerified += expectedName.Length; @@ -170,7 +172,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests charsVerified += 3; } - private void AssertLocationEqual(RazorIRNode node, string expected, string actual, ref int charsVerified) + private void AssertLocationEqual(RazorIRNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) { var expectedLocation = GetLocation(expected, charsVerified); var actualLocation = GetLocation(actual, charsVerified); @@ -178,13 +180,13 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests if (!string.Equals(expectedLocation, actualLocation)) { var message = $"Locations are not equal."; - throw new IRBaselineException(node, expected, actual, message); + throw new IRBaselineException(node, ancestors.ToArray(), expected, actual, message); } charsVerified += expectedLocation.Length; } - private void AssertContentEqual(RazorIRNode node, string expected, string actual, ref int charsVerified) + private void AssertContentEqual(RazorIRNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) { var expectedContent = GetContent(expected, charsVerified); var actualContent = GetContent(actual, charsVerified); @@ -192,7 +194,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests if (!string.Equals(expectedContent, actualContent)) { var message = $"Contents are not equal."; - throw new IRBaselineException(node, expected, actual, message); + throw new IRBaselineException(node, ancestors.ToArray(), expected, actual, message); } charsVerified += expectedContent.Length; @@ -222,8 +224,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests private class IRBaselineException : XunitException { - public IRBaselineException(RazorIRNode node, string expected, string actual, string userMessage) - : base(Format(node, expected, actual, userMessage)) + public IRBaselineException(RazorIRNode node, RazorIRNode[] ancestors, string expected, string actual, string userMessage) + : base(Format(node, ancestors, expected, actual, userMessage)) { Node = node; Expected = expected; @@ -236,7 +238,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests public string Expected { get; } - private static string Format(RazorIRNode node, string expected, string actual, string userMessage) + private static string Format(RazorIRNode node, RazorIRNode[] ancestors, string expected, string actual, string userMessage) { var builder = new StringBuilder(); builder.AppendLine(userMessage); @@ -254,15 +256,16 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests builder.AppendLine(actual); } - builder.AppendLine(); - builder.AppendLine("Path:"); - - var current = node; - do + if (ancestors != null) { - builder.AppendLine(current.ToString()); + builder.AppendLine(); + builder.AppendLine("Path:"); + + foreach (var ancestor in ancestors) + { + builder.AppendLine(ancestor.ToString()); + } } - while ((current = current.Parent) != null); return builder.ToString(); } diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/Intermediate/RazorIRAssert.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/Intermediate/RazorIRAssert.cs index 2504c30925..b3d4af3db7 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/Intermediate/RazorIRAssert.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/Intermediate/RazorIRAssert.cs @@ -431,13 +431,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate private class IRAssertException : XunitException { public IRAssertException(RazorIRNode node, string userMessage) - : base(Format(node, null, userMessage)) + : base(Format(node, null, null, userMessage)) { Node = node; } public IRAssertException(RazorIRNode node, IEnumerable nodes, string userMessage) - : base(Format(node, nodes, userMessage)) + : base(Format(node, null, nodes, userMessage)) { Node = node; Nodes = nodes; @@ -448,7 +448,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate IEnumerable nodes, string userMessage, Exception innerException) - : base(Format(node, nodes, userMessage), innerException) + : base(Format(node, null, nodes, userMessage), innerException) + { + } + + public IRAssertException( + RazorIRNode node, + RazorIRNode[] ancestors, + IEnumerable nodes, + string userMessage, + Exception innerException) + : base(Format(node, ancestors, nodes, userMessage), innerException) { } @@ -456,7 +466,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public IEnumerable Nodes { get; } - private static string Format(RazorIRNode node, IEnumerable nodes, string userMessage) + private static string Format(RazorIRNode node, RazorIRNode[] ancestors, IEnumerable nodes, string userMessage) { var builder = new StringBuilder(); builder.AppendLine(userMessage); @@ -477,12 +487,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate builder.AppendLine("Path:"); - var current = node; - do + if (ancestors != null) { - builder.AppendLine(current.ToString()); + builder.AppendLine(); + builder.AppendLine("Path:"); + + foreach (var ancestor in ancestors) + { + builder.AppendLine(ancestor.ToString()); + } } - while ((current = current.Parent) != null); return builder.ToString(); }