Implement IR lowering phase
This is a first cut of IR lowering and includes the basic node types and some tests.
This commit is contained in:
parent
d0e1b810c4
commit
d8b626c843
|
|
@ -0,0 +1,215 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
internal class DefaultRazorIRLoweringPhase : RazorEnginePhaseBase, IRazorIRLoweringPhase
|
||||
{
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDependency<RazorSyntaxTree>(syntaxTree);
|
||||
|
||||
var visitor = new Visitor();
|
||||
|
||||
visitor.VisitBlock(syntaxTree.Root);
|
||||
|
||||
var irDocument = (DocumentIRNode)visitor.Builder.Build();
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
}
|
||||
|
||||
private class Visitor : ParserVisitor
|
||||
{
|
||||
public Visitor()
|
||||
{
|
||||
Builder = RazorIRBuilder.Document();
|
||||
|
||||
Namespace = new NamespaceDeclarationIRNode();
|
||||
NamespaceBuilder = RazorIRBuilder.Create(Namespace);
|
||||
Builder.Push(Namespace);
|
||||
|
||||
Class = new ClassDeclarationIRNode();
|
||||
ClassBuilder = RazorIRBuilder.Create(Class);
|
||||
Builder.Push(Class);
|
||||
|
||||
Method = new MethodDeclarationIRNode();
|
||||
Builder.Push(Method);
|
||||
}
|
||||
|
||||
public RazorIRBuilder Builder { get; }
|
||||
|
||||
public NamespaceDeclarationIRNode Namespace { get; }
|
||||
|
||||
public RazorIRBuilder NamespaceBuilder { get; }
|
||||
|
||||
public ClassDeclarationIRNode Class { get; }
|
||||
|
||||
public RazorIRBuilder ClassBuilder { get; }
|
||||
|
||||
public MethodDeclarationIRNode Method { get; }
|
||||
|
||||
public override void VisitStartAttributeBlock(AttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Push(new HtmlAttributeIRNode()
|
||||
{
|
||||
Name = chunk.Name,
|
||||
Prefix = chunk.Prefix,
|
||||
Suffix = chunk.Prefix,
|
||||
|
||||
SourceLocation = block.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitEndAttributeBlock(AttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Pop();
|
||||
}
|
||||
|
||||
public override void VisitStartDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Push(new CSharpAttributeValueIRNode()
|
||||
{
|
||||
Prefix = chunk.Prefix,
|
||||
SourceLocation = block.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitEndDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Pop();
|
||||
}
|
||||
|
||||
public override void VisitLiteralAttributeSpan(LiteralAttributeChunkGenerator chunk, Span span)
|
||||
{
|
||||
Builder.Add(new HtmlAttributeValueIRNode()
|
||||
{
|
||||
Prefix = chunk.Prefix,
|
||||
SourceLocation = span.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitStartTemplateBlock(TemplateBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Push(new TemplateIRNode());
|
||||
}
|
||||
|
||||
public override void VisitEndTemplateBlock(TemplateBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Pop();
|
||||
}
|
||||
|
||||
// CSharp expressions are broken up into blocks and spans because Razor allows Razor comments
|
||||
// inside an expression.
|
||||
// Ex:
|
||||
// @DateTime.@*This is a comment*@Now
|
||||
//
|
||||
// We need to capture this in the IR so that we can give each piece the correct source mappings
|
||||
public override void VisitStartExpressionBlock(ExpressionChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Push(new CSharpExpressionIRNode()
|
||||
{
|
||||
SourceLocation = block.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitEndExpressionBlock(ExpressionChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Pop();
|
||||
}
|
||||
|
||||
public override void VisitExpressionSpan(ExpressionChunkGenerator chunk, Span span)
|
||||
{
|
||||
Builder.Add(new CSharpTokenIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
SourceLocation = span.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitStartSectionBlock(SectionChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Push(new SectionIRNode()
|
||||
{
|
||||
Name = chunk.SectionName,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitEndSectionBlock(SectionChunkGenerator chunk, Block block)
|
||||
{
|
||||
Builder.Pop();
|
||||
}
|
||||
|
||||
public override void VisitTypeMemberSpan(TypeMemberChunkGenerator chunk, Span span)
|
||||
{
|
||||
ClassBuilder.Add(new CSharpStatementIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
SourceLocation = span.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunk, Span span)
|
||||
{
|
||||
// Empty for now
|
||||
}
|
||||
|
||||
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunk, Span span)
|
||||
{
|
||||
// Empty for now
|
||||
}
|
||||
|
||||
public override void VisitTagHelperPrefixSpan(TagHelperPrefixDirectiveChunkGenerator chunk, Span span)
|
||||
{
|
||||
// Empty for now
|
||||
}
|
||||
|
||||
public override void VisitStatementSpan(StatementChunkGenerator chunk, Span span)
|
||||
{
|
||||
Builder.Add(new CSharpStatementIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
SourceLocation = span.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitSetBaseTypeSpan(SetBaseTypeChunkGenerator chunk, Span span)
|
||||
{
|
||||
Class.BaseType = span.Content;
|
||||
}
|
||||
|
||||
public override void VisitMarkupSpan(MarkupChunkGenerator chunk, Span span)
|
||||
{
|
||||
Builder.Add(new HtmlContentIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
SourceLocation = span.Start,
|
||||
});
|
||||
}
|
||||
|
||||
public override void VisitImportSpan(AddImportChunkGenerator chunk, Span span)
|
||||
{
|
||||
// For prettiness, let's insert the usings before the class declaration.
|
||||
var i = 0;
|
||||
for (; i < Namespace.Children.Count; i++)
|
||||
{
|
||||
if (Namespace.Children[i] is ClassDeclarationIRNode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var @using = new UsingStatementIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
Parent = Namespace,
|
||||
SourceLocation = span.Start,
|
||||
};
|
||||
|
||||
Namespace.Children.Insert(i, @using);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
public interface IRazorIRLoweringPhase : IRazorEnginePhase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class BlockDirectiveIRNode : RazorIRNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitBlockDirective(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitBlockDirective(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class CSharpAttributeValueIRNode : RazorIRNode
|
||||
{
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitCSharpAttributeValue(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitCSharpAttributeValue(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class CSharpExpressionIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitCSharpExpression(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitCSharpExpression(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class CSharpStatementIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitCSharpStatement(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitCSharpStatement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class CSharpTokenIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = EmptyArray;
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitCSharpToken(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitCSharpToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class ClassDeclarationIRNode : RazorIRNode
|
||||
{
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string BaseType { get; set; }
|
||||
|
||||
public IList<string> Interfaces { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitClass(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitClass(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,17 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
Pop();
|
||||
}
|
||||
|
||||
public override RazorIRNode Build()
|
||||
{
|
||||
RazorIRNode node = null;
|
||||
while (_depth > 0)
|
||||
{
|
||||
node = Pop();
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
public override RazorIRNode Pop()
|
||||
{
|
||||
if (_depth == 0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class DirectiveTokenIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitDirectiveToken(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitDirectiveToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,22 +2,18 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public sealed class RazorIRDocument : RazorIRNode
|
||||
public sealed class DocumentIRNode : RazorIRNode
|
||||
{
|
||||
// Only allow creation of documents through the builder API because
|
||||
// they can't be nested.
|
||||
internal RazorIRDocument()
|
||||
{
|
||||
Children = new List<RazorIRNode>();
|
||||
}
|
||||
|
||||
public override IList<RazorIRNode> Children { get; }
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitDocument(this);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class HtmlAttributeIRNode : RazorIRNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public string Suffix { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitHtmlAttribute(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitHtmlAttribute(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class HtmlAttributeValueIRNode : RazorIRNode
|
||||
{
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitHtmlAttributeValue(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitHtmlAttributeValue(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public sealed class HtmlContentIRNode : RazorIRNode
|
||||
{
|
||||
public string Content { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitHtml(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitHtml(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class MethodDeclarationIRNode : RazorIRNode
|
||||
{
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public IList<string> Modifiers { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string ReturnType { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitMethodDeclaration(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitMethodDeclaration(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class NamespaceDeclarationIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitNamespace(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitNamespace(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,26 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public abstract class RazorIRBuilder
|
||||
{
|
||||
public static RazorIRBuilder Document()
|
||||
{
|
||||
return Create(new DocumentIRNode());
|
||||
}
|
||||
|
||||
public static RazorIRBuilder Create(RazorIRNode root)
|
||||
{
|
||||
if (root == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(root));
|
||||
}
|
||||
|
||||
var builder = new DefaultRazorIRBuilder();
|
||||
builder.Push(new RazorIRDocument());
|
||||
builder.Push(root);
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
@ -16,6 +28,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
|
||||
public abstract void Add(RazorIRNode node);
|
||||
|
||||
public abstract RazorIRNode Build();
|
||||
|
||||
public abstract void Push(RazorIRNode node);
|
||||
|
||||
public abstract RazorIRNode Pop();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
|
|
@ -13,6 +14,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
|
||||
public abstract RazorIRNode Parent { get; set; }
|
||||
|
||||
internal abstract SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public abstract void Accept(RazorIRNodeVisitor visitor);
|
||||
|
||||
public abstract TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,87 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void VisitDocument(RazorIRDocument node)
|
||||
public virtual void VisitDirectiveToken(DirectiveTokenIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitSection(SectionIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitHtmlAttributeValue(HtmlAttributeValueIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitCSharpAttributeValue(CSharpAttributeValueIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitHtmlAttribute(HtmlAttributeIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitSingleLineDirective(SingleLineDirectiveIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitBlockDirective(BlockDirectiveIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitMethodDeclaration(MethodDeclarationIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitDocument(DocumentIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitHtml(HtmlContentIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual void VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
VisitDefault(node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,86 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
return default(TResult);
|
||||
}
|
||||
|
||||
public virtual TResult VisitDocument(RazorIRDocument node)
|
||||
public virtual TResult VisitDirectiveToken(DirectiveTokenIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitTemplate(TemplateIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitSection(SectionIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitCSharpStatement(CSharpStatementIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitCSharpExpression(CSharpExpressionIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitCSharpToken(CSharpTokenIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitHtmlAttributeValue(HtmlAttributeValueIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitCSharpAttributeValue(CSharpAttributeValueIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitHtmlAttribute(HtmlAttributeIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitClass(ClassDeclarationIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitSingleLineDirective(SingleLineDirectiveIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitBlockDirective(BlockDirectiveIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
public virtual TResult VisitMethodDeclaration(MethodDeclarationIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitDocument(DocumentIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitHtml(HtmlContentIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitNamespace(NamespaceDeclarationIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
||||
public virtual TResult VisitUsingStatement(UsingStatementIRNode node)
|
||||
{
|
||||
return VisitDefault(node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class SectionIRNode : RazorIRNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitSection(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitSection(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class SingleLineDirectiveIRNode : RazorIRNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitSingleLineDirective(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitSingleLineDirective(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class TemplateIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
visitor.VisitTemplate(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
return visitor.VisitTemplate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class UsingStatementIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
visitor.VisitUsingStatement(this);
|
||||
}
|
||||
|
||||
public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
return visitor.VisitUsingStatement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string Namespace { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitImportSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
var ns = Namespace;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string LookupText { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitAddTagHelperSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
//context.ChunkTreeBuilder.AddAddTagHelperChunk(LookupText, target);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
//context.ChunkTreeBuilder.EndParentChunk();
|
||||
}
|
||||
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartAttributeBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndAttributeBlock(this, block);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, "Attr:{0},{1:F},{2:F}", Name, Prefix, Suffix);
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
return hashCodeCombiner.CombinedHash;
|
||||
}
|
||||
|
||||
public override void Accept(ParserVisitor visitor)
|
||||
{
|
||||
visitor.VisitBlock(this);
|
||||
}
|
||||
|
||||
private class EquivalenceComparer : IEqualityComparer<SyntaxTreeNode>
|
||||
{
|
||||
public static readonly EquivalenceComparer Default = new EquivalenceComparer();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
|
|
@ -22,6 +23,16 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public SourceLocation ValueStart { get; }
|
||||
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartDynamicAttributeBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndDynamicAttributeBlock(this, block);
|
||||
}
|
||||
|
||||
public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
|
||||
{
|
||||
//var chunk = context.ChunkTreeBuilder.StartParentChunk<DynamicCodeAttributeChunk>(target);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
{
|
||||
internal class ExpressionChunkGenerator : ISpanChunkGenerator, IParentChunkGenerator
|
||||
|
|
@ -22,6 +24,21 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
//context.ChunkTreeBuilder.EndParentChunk();
|
||||
}
|
||||
|
||||
public void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitExpressionSpan(this, span);
|
||||
}
|
||||
|
||||
public void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartExpressionBlock(this, block);
|
||||
}
|
||||
|
||||
public void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndExpressionBlock(this, block);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Expr";
|
||||
|
|
|
|||
|
|
@ -7,5 +7,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
void GenerateStartParentChunk(Block target, ChunkGeneratorContext context);
|
||||
void GenerateEndParentChunk(Block target, ChunkGeneratorContext context);
|
||||
void AcceptStart(ParserVisitor visitor, Block block);
|
||||
void AcceptEnd(ParserVisitor visitor, Block block);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,5 +6,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
internal interface ISpanChunkGenerator
|
||||
{
|
||||
void GenerateChunk(Span target, ChunkGeneratorContext context);
|
||||
|
||||
void Accept(ParserVisitor visitor, Span span);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public LocationTagged<SpanChunkGenerator> ValueGenerator { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitLiteralAttributeSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
//var chunk = context.ChunkTreeBuilder.StartParentChunk<LiteralCodeAttributeChunk>(target);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
//context.ChunkTreeBuilder.AddLiteralChunk(target.Content, target);
|
||||
}
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitMarkupSpan(this, span);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Markup";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public static readonly IParentChunkGenerator Null = new NullParentChunkGenerator();
|
||||
|
||||
public abstract void AcceptStart(ParserVisitor visitor, Block block);
|
||||
public abstract void AcceptEnd(ParserVisitor visitor, Block block);
|
||||
|
||||
public virtual void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
|
||||
{
|
||||
}
|
||||
|
|
@ -42,6 +45,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
return "None";
|
||||
}
|
||||
|
||||
public void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
{
|
||||
internal abstract class ParserVisitor
|
||||
{
|
||||
public virtual void VisitBlock(Block block)
|
||||
{
|
||||
VisitStartBlock(block);
|
||||
|
||||
for (var i = 0; i < block.Children.Count; i++)
|
||||
{
|
||||
block.Children[i].Accept(this);
|
||||
}
|
||||
|
||||
VisitEndBlock(block);
|
||||
}
|
||||
|
||||
public virtual void VisitStartBlock(Block block)
|
||||
{
|
||||
if (block.ChunkGenerator != null)
|
||||
{
|
||||
block.ChunkGenerator.AcceptStart(this, block);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void VisitEndBlock(Block block)
|
||||
{
|
||||
if (block.ChunkGenerator != null)
|
||||
{
|
||||
block.ChunkGenerator.AcceptEnd(this, block);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void VisitSpan(Span span)
|
||||
{
|
||||
if (span.ChunkGenerator != null)
|
||||
{
|
||||
span.ChunkGenerator.Accept(this, span);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void VisitStartDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndDynamicAttributeBlock(DynamicAttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartExpressionBlock(ExpressionChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndExpressionBlock(ExpressionChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartAttributeBlock(AttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndAttributeBlock(AttributeBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitExpressionSpan(ExpressionChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitSetBaseTypeSpan(SetBaseTypeChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitTagHelperPrefixSpan(TagHelperPrefixDirectiveChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitTypeMemberSpan(TypeMemberChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitMarkupSpan(MarkupChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitImportSpan(AddImportChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStatementSpan(StatementChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitLiteralAttributeSpan(LiteralAttributeChunkGenerator chunk, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndTemplateBlock(TemplateBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartTemplateBlock(TemplateBlockChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartSectionBlock(SectionChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndSectionBlock(SectionChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitEndCommentBlock(RazorCommentChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void VisitStartCommentBlock(RazorCommentChunkGenerator chunk, Block block)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,5 +5,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
internal class RazorCommentChunkGenerator : ParentChunkGenerator
|
||||
{
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartCommentBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndCommentBlock(this, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string LookupText { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitRemoveTagHelperSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
//context.ChunkTreeBuilder.AddRemoveTagHelperChunk(LookupText, target);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,16 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string SectionName { get; }
|
||||
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartSectionBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndSectionBlock(this, block);
|
||||
}
|
||||
|
||||
public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
|
||||
{
|
||||
//var chunk = context.ChunkTreeBuilder.StartParentChunk<SectionChunk>(target);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string BaseType { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitSetBaseTypeSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,5 +131,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
// Hash code should include only immutable properties but Equals also checks the type.
|
||||
return TypeHashCode;
|
||||
}
|
||||
|
||||
public override void Accept(ParserVisitor visitor)
|
||||
{
|
||||
visitor.VisitSpan(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
||||
{
|
||||
internal abstract class SpanChunkGenerator : ISpanChunkGenerator
|
||||
|
|
@ -9,6 +11,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public static readonly ISpanChunkGenerator Null = new NullSpanChunkGenerator();
|
||||
|
||||
public abstract void Accept(ParserVisitor visitor, Span span);
|
||||
|
||||
public virtual void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
}
|
||||
|
|
@ -26,6 +30,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
private class NullSpanChunkGenerator : ISpanChunkGenerator
|
||||
{
|
||||
public void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
}
|
||||
|
||||
public void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
internal class StatementChunkGenerator : SpanChunkGenerator
|
||||
{
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitStatementSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
//context.ChunkTreeBuilder.AddStatementChunk(target.Content, target);
|
||||
|
|
|
|||
|
|
@ -41,5 +41,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
/// <see cref="EquivalentTo"/> comparisons.
|
||||
/// </returns>
|
||||
public abstract int GetEquivalenceHash();
|
||||
|
||||
public abstract void Accept(ParserVisitor visitor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
|
||||
public string Prefix { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitTagHelperPrefixSpan(this, span);
|
||||
}
|
||||
|
||||
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
|
||||
{
|
||||
//context.ChunkTreeBuilder.AddTagHelperPrefixDirectiveChunk(Prefix, target);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,16 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
{
|
||||
internal class TemplateBlockChunkGenerator : ParentChunkGenerator
|
||||
{
|
||||
public override void AcceptStart(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitStartTemplateBlock(this, block);
|
||||
}
|
||||
|
||||
public override void AcceptEnd(ParserVisitor visitor, Block block)
|
||||
{
|
||||
visitor.VisitEndTemplateBlock(this, block);
|
||||
}
|
||||
|
||||
public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
|
||||
{
|
||||
//context.ChunkTreeBuilder.StartParentChunk<TemplateChunk>(target);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
|
|||
//context.ChunkTreeBuilder.AddTypeMemberChunk(target.Content, target);
|
||||
}
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
{
|
||||
visitor.VisitTypeMemberSpan(this, span);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "TypeMember";
|
||||
|
|
|
|||
|
|
@ -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 Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
|
|
@ -26,5 +27,25 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
|
||||
document.Items[typeof(RazorSyntaxTree)] = syntaxTree;
|
||||
}
|
||||
|
||||
public static DocumentIRNode GetIRDocument(this RazorCodeDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
return document.Items[typeof(DocumentIRNode)] as DocumentIRNode;
|
||||
}
|
||||
|
||||
public static void SetIRDocument(this RazorCodeDocument document, DocumentIRNode irDocument)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
document.Items[typeof(DocumentIRNode)] = irDocument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
{
|
||||
builder.Phases.Add(new DefaultRazorParsingPhase());
|
||||
builder.Phases.Add(new DefaultRazorSyntaxTreePhase());
|
||||
builder.Phases.Add(new DefaultRazorIRLoweringPhase());
|
||||
|
||||
builder.Features.Add(new TagHelperBinderSyntaxTreePass());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -125,12 +126,34 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
Assert.Collection(parent.Children, n => Assert.Same(node, n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_PopsMultipleLevels()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultRazorIRBuilder();
|
||||
|
||||
var document = new DocumentIRNode();
|
||||
builder.Push(document);
|
||||
|
||||
var node = new BasicIRNode();
|
||||
builder.Push(node);
|
||||
|
||||
// Act
|
||||
var result = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.Same(document, result);
|
||||
Assert.Null(builder.Current);
|
||||
}
|
||||
|
||||
private class BasicIRNode : RazorIRNode
|
||||
{
|
||||
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();
|
||||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
// 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 static Microsoft.AspNetCore.Razor.Evolution.Intermediate.RazorIRAssert;
|
||||
using Xunit;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public class LoweringIntegrationTest
|
||||
{
|
||||
[Fact]
|
||||
public void Lower_EmptyDocument()
|
||||
{
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
var @class = SingleChild<ClassDeclarationIRNode>(@namespace);
|
||||
var method = SingleChild<MethodDeclarationIRNode>(@class);
|
||||
var html = SingleChild<HtmlContentIRNode>(method);
|
||||
|
||||
Assert.Equal(string.Empty, html.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_HelloWorld()
|
||||
{
|
||||
var codeDocument = TestRazorCodeDocument.Create("Hello, World!");
|
||||
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
var @class = SingleChild<ClassDeclarationIRNode>(@namespace);
|
||||
var method = SingleChild<MethodDeclarationIRNode>(@class);
|
||||
var html = SingleChild<HtmlContentIRNode>(method);
|
||||
|
||||
Assert.Equal("Hello, World!", html.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_HtmlWithAttributes()
|
||||
{
|
||||
var codeDocument = TestRazorCodeDocument.Create(@"
|
||||
<html>
|
||||
<body>
|
||||
<span data-val=""@Hello"" />
|
||||
</body>
|
||||
</html>");
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
var @class = SingleChild<ClassDeclarationIRNode>(@namespace);
|
||||
var method = SingleChild<MethodDeclarationIRNode>(@class);
|
||||
Children(method,
|
||||
n => Html(Environment.NewLine, n),
|
||||
n => Html("<html>", n),
|
||||
n => Html(Environment.NewLine + " ", n),
|
||||
n => Html("<body>", n),
|
||||
n => Html(Environment.NewLine + " ", n),
|
||||
n => Html("<span", n),
|
||||
n => Html(" data-val=\"", n),
|
||||
n => CSharpExpression("Hello", n),
|
||||
n => Html("\"", n),
|
||||
n => Html(" />", n),
|
||||
n => Html(Environment.NewLine + " ", n),
|
||||
n => Html("</body>", n),
|
||||
n => Html(Environment.NewLine, n),
|
||||
n => Html("</html>", n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_WithUsing()
|
||||
{
|
||||
var codeDocument = TestRazorCodeDocument.Create(@"@functions { public int Foo { get; set; }}");
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
var @class = SingleChild<ClassDeclarationIRNode>(@namespace);
|
||||
Children(@class,
|
||||
n => Assert.IsType<MethodDeclarationIRNode>(n),
|
||||
n => Assert.IsType<CSharpStatementIRNode>(n));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lower_WithFunctions()
|
||||
{
|
||||
var codeDocument = TestRazorCodeDocument.Create(@"@using System");
|
||||
var irDocument = Lower(codeDocument);
|
||||
|
||||
var @namespace = SingleChild<NamespaceDeclarationIRNode>(irDocument);
|
||||
Children(@namespace,
|
||||
n => Using("using System", n),
|
||||
n => Assert.IsType<ClassDeclarationIRNode>(n));
|
||||
}
|
||||
|
||||
private DocumentIRNode Lower(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var engine = RazorEngine.Create();
|
||||
|
||||
for (var i = 0; i < engine.Phases.Count; i++)
|
||||
{
|
||||
var phase = engine.Phases[i];
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
if (phase is IRazorIRLoweringPhase)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
Assert.NotNull(irDocument);
|
||||
return irDocument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
// 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.Text;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
{
|
||||
public static class RazorIRAssert
|
||||
{
|
||||
public static TNode SingleChild<TNode>(RazorIRNode node)
|
||||
{
|
||||
if (node.Children.Count == 0)
|
||||
{
|
||||
throw new IRAssertException(node, "The node has no children.");
|
||||
}
|
||||
else if (node.Children.Count > 1)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, "The node has multiple children");
|
||||
}
|
||||
|
||||
var child = node.Children[0];
|
||||
return Assert.IsType<TNode>(child);
|
||||
}
|
||||
|
||||
public static void NoChildren(RazorIRNode node)
|
||||
{
|
||||
if (node.Children.Count > 0)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, "The node has children.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Children(RazorIRNode node, params Action<RazorIRNode>[] validators)
|
||||
{
|
||||
var i = 0;
|
||||
for (; i < validators.Length; i++)
|
||||
{
|
||||
if (node.Children.Count == i)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, $"The node only has {node.Children.Count} children.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
validators[i].Invoke(node.Children[i]);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, $"Failed while validating node {node.Children[i]} at {i}.", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < node.Children.Count)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, $"The node has extra child {node.Children[i]} at {i}.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Html(string expected, RazorIRNode node)
|
||||
{
|
||||
try
|
||||
{
|
||||
var html = Assert.IsType<HtmlContentIRNode>(node);
|
||||
Assert.Equal(expected, html.Content);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Using(string expected, RazorIRNode node)
|
||||
{
|
||||
try
|
||||
{
|
||||
var @using = Assert.IsType<UsingStatementIRNode>(node);
|
||||
Assert.Equal(expected, @using.Content);
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CSharpExpression(string expected, RazorIRNode node)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cSharp = Assert.IsType<CSharpExpressionIRNode>(node);
|
||||
|
||||
var content = new StringBuilder();
|
||||
for (var i = 0; i < cSharp.Children.Count; i++)
|
||||
{
|
||||
content.Append(((CSharpTokenIRNode)cSharp.Children[i]).Content);
|
||||
}
|
||||
|
||||
Assert.Equal(expected, content.ToString());
|
||||
}
|
||||
catch (XunitException e)
|
||||
{
|
||||
throw new IRAssertException(node, node.Children, e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class IRAssertException : XunitException
|
||||
{
|
||||
public IRAssertException(RazorIRNode node, string userMessage)
|
||||
: base(Format(node, null, userMessage))
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public IRAssertException(RazorIRNode node, IEnumerable<RazorIRNode> nodes, string userMessage)
|
||||
: base(Format(node, nodes, userMessage))
|
||||
{
|
||||
Node = node;
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
public IRAssertException(
|
||||
RazorIRNode node,
|
||||
IEnumerable<RazorIRNode> nodes,
|
||||
string userMessage,
|
||||
Exception innerException)
|
||||
: base(Format(node, nodes, userMessage), innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public RazorIRNode Node { get; }
|
||||
|
||||
public IEnumerable<RazorIRNode> Nodes { get; }
|
||||
|
||||
private static string Format(RazorIRNode node, IEnumerable<RazorIRNode> nodes, string userMessage)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine(userMessage);
|
||||
builder.AppendLine();
|
||||
|
||||
if (nodes != null)
|
||||
{
|
||||
builder.AppendLine("Nodes:");
|
||||
|
||||
foreach (var n in nodes)
|
||||
{
|
||||
builder.AppendLine(n.ToString());
|
||||
}
|
||||
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
builder.AppendLine("Path:");
|
||||
|
||||
var current = node;
|
||||
do
|
||||
{
|
||||
builder.AppendLine(current.ToString());
|
||||
}
|
||||
while ((current = current.Parent) != null);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
var builder = RazorIRBuilder.Document();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<RazorIRDocument>(builder.Current);
|
||||
Assert.IsType<DocumentIRNode>(builder.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||
|
|
@ -74,6 +75,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
|||
|
||||
public override RazorIRNode Parent { get; set; }
|
||||
|
||||
internal override SourceLocation SourceLocation { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
((DerivedIRNodeWalker)visitor).VisitBasic(this);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
|
|
@ -37,5 +38,36 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
// Assert
|
||||
Assert.Same(expected, codeDocument.Items[typeof(RazorSyntaxTree)]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetIRDocument_ReturnsIRDocument()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
var expected = RazorIRBuilder.Document().Build();
|
||||
codeDocument.Items[typeof(DocumentIRNode)] = expected;
|
||||
|
||||
// Act
|
||||
var actual = codeDocument.GetIRDocument();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetIRDocument_SetsIRDocument()
|
||||
{
|
||||
// Arrange
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
var expected = RazorIRBuilder.Document().Build();
|
||||
|
||||
// Act
|
||||
codeDocument.SetIRDocument((DocumentIRNode)expected);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, codeDocument.Items[typeof(DocumentIRNode)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
Assert.Collection(
|
||||
phases,
|
||||
phase => Assert.IsType<DefaultRazorParsingPhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorSyntaxTreePhase>(phase));
|
||||
phase => Assert.IsType<DefaultRazorSyntaxTreePhase>(phase),
|
||||
phase => Assert.IsType<DefaultRazorIRLoweringPhase>(phase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
return new TestRazorCodeDocument(source);
|
||||
}
|
||||
|
||||
public static TestRazorCodeDocument Create(string content)
|
||||
{
|
||||
var source = TestRazorSourceDocument.Create(content);
|
||||
return new TestRazorCodeDocument(source);
|
||||
}
|
||||
|
||||
private TestRazorCodeDocument(RazorSourceDocument source)
|
||||
: base(source)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue