Add Razor baseline test infrastructure

Ports somee infrastructure and converts Razor code generation tests to use
it. This makes it much easier to make cross cutting changes to code
generation and see the effect.

Use build /p:GenerateBaselines=true to update all of the generated code
in place or when adding new tests. Generally if tests are failing, the
easiest thing to do is to update the baselines and do a git diff to see
what the deltas are.

The changes to the tests here are to use the new baseline infrastructure
and to rename classes/methods to result in shorter file paths.
This commit is contained in:
Ryan Nowak 2018-04-03 16:37:25 -07:00
parent 2d89c11183
commit 707e781e5d
56 changed files with 2578 additions and 1037 deletions

View File

@ -14,12 +14,15 @@ namespace Microsoft.AspNetCore.Blazor.Razor
{
private const string ImportsFileName = "_ViewImports.cshtml";
private const string DefaultUsingImportContent = @"
@using System
@using System.Collections.Generic
@using System.Linq
@using System.Threading.Tasks
";
private static readonly char[] PathSeparators = new char[]{ '/', '\\' };
// Using explicit newlines here to avoid fooling our baseline tests
private const string DefaultUsingImportContent =
"\r\n" +
"@using System\r\n" +
"@using System.Collections.Generic\r\n" +
"@using System.Linq\r\n" +
"@using System.Threading.Tasks\r\n";
public RazorProjectEngine ProjectEngine { get; set; }
@ -40,9 +43,13 @@ namespace Microsoft.AspNetCore.Blazor.Razor
// the namespace through from the project.
if (projectItem.PhysicalPath != null && projectItem.FilePath != null)
{
// Avoiding the path-specific APIs here, we want to handle all styles of paths
// on all platforms
var trimLength = projectItem.FilePath.Length + (projectItem.FilePath.StartsWith("/") ? 0 : 1);
var baseDirectory = projectItem.PhysicalPath.Substring(0, projectItem.PhysicalPath.Length - trimLength);
var baseNamespace = Path.GetFileName(baseDirectory);
var lastSlash = baseDirectory.LastIndexOfAny(PathSeparators);
var baseNamespace = lastSlash == -1 ? baseDirectory : baseDirectory.Substring(lastSlash + 1);
if (!string.IsNullOrEmpty(baseNamespace))
{
imports.Add(new VirtualProjectItem($@"@addTagHelper ""*, {baseNamespace}"""));

View File

@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Blazor.Razor
{
public sealed class ComponentBodyExtensionNode : ExtensionIntermediateNode
internal sealed class ComponentBodyExtensionNode : ExtensionIntermediateNode
{
public ComponentBodyExtensionNode()
{

View File

@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
callBase.Children.Add(new IntermediateToken
{
Kind = TokenKind.CSharp,
Content = $"base.{BlazorApi.BlazorComponent.BuildRenderTree}(builder);" + Environment.NewLine
Content = $"base.{BlazorApi.BlazorComponent.BuildRenderTree}(builder);"
});
method.Children.Insert(0, callBase);
}
@ -108,7 +108,9 @@ namespace Microsoft.AspNetCore.Blazor.Razor
// the namespace through from the project.
var trimLength = relativePath.Length + (relativePath.StartsWith("/") ? 0 : 1);
var baseDirectory = filePath.Substring(0, filePath.Length - trimLength);
var baseNamespace = Path.GetFileName(baseDirectory);
var lastSlash = baseDirectory.LastIndexOfAny(PathSeparators);
var baseNamespace = lastSlash == -1 ? baseDirectory : baseDirectory.Substring(lastSlash + 1);
if (string.IsNullOrEmpty(baseNamespace))
{
@namespace = null;

View File

@ -78,30 +78,5 @@ namespace Microsoft.AspNetCore.Blazor.Razor
}
}
}
private class RouteAttributeExtensionNode : ExtensionIntermediateNode
{
public RouteAttributeExtensionNode(string template)
{
Template = template;
}
public string Template { get; }
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
public override void Accept(IntermediateNodeVisitor visitor) => AcceptExtensionNode(this, visitor);
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
{
context.CodeWriter.Write("[");
context.CodeWriter.Write(BlazorApi.RouteAttribute.FullTypeName);
context.CodeWriter.Write("(\"");
context.CodeWriter.Write(Template);
context.CodeWriter.Write("\")");
context.CodeWriter.Write("]");
context.CodeWriter.WriteLine();
}
}
}
}

View File

@ -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 Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Blazor.Razor
{
internal class RouteAttributeExtensionNode : ExtensionIntermediateNode
{
public RouteAttributeExtensionNode(string template)
{
Template = template;
}
public string Template { get; }
public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly;
public override void Accept(IntermediateNodeVisitor visitor) => AcceptExtensionNode(this, visitor);
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
{
context.CodeWriter.Write("[");
context.CodeWriter.Write(BlazorApi.RouteAttribute.FullTypeName);
context.CodeWriter.Write("(\"");
context.CodeWriter.Write(Template);
context.CodeWriter.Write("\")");
context.CodeWriter.Write("]");
context.CodeWriter.WriteLine();
}
}
}

View File

@ -1,500 +0,0 @@
// 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.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class DesignTimeCodeGenerationRazorIntegrationTest : RazorIntegrationTestBase
{
internal override bool DesignTime => true;
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void CodeGeneration_ChildComponent_WithParameters()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class SomeType
{
}
public class MyComponent : BlazorComponent
{
public int IntProperty { get; set; }
public bool BoolProperty { get; set; }
public string StringProperty { get; set; }
public SomeType ObjectProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent
IntProperty=""123""
BoolProperty=""true""
StringProperty=""My string""
ObjectProperty=""new SomeType()""/>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 3 ""x:\dir\subdir\Test\TestComponent.cshtml""
123
#line default
#line hidden
;
__o =
#line 4 ""x:\dir\subdir\Test\TestComponent.cshtml""
true
#line default
#line hidden
;
__o =
#line 6 ""x:\dir\subdir\Test\TestComponent.cshtml""
new SomeType()
#line default
#line hidden
;
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithExplicitStringParameter()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string StringProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent StringProperty=""@(42.ToString())"" />");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 2 ""x:\dir\subdir\Test\TestComponent.cshtml""
42.ToString()
#line default
#line hidden
;
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithNonPropertyAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent some-attribute=""foo"" another-attribute=""@(43.ToString())""/>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 2 ""x:\dir\subdir\Test\TestComponent.cshtml""
43.ToString()
#line default
#line hidden
;
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithLambdaEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent OnClick=""@((e) => { Increment(); })""/>
@functions {
private int counter;
private void Increment() {
counter++;
}
}");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o = new Microsoft.AspNetCore.Blazor.UIEventHandler(
#line 2 ""x:\dir\subdir\Test\TestComponent.cshtml""
(e) => { Increment(); }
#line default
#line hidden
);
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
#line 4 ""x:\dir\subdir\Test\TestComponent.cshtml""
private int counter;
private void Increment() {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithExplicitEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@using Microsoft.AspNetCore.Blazor
<MyComponent OnClick=""@Increment""/>
@functions {
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
}");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#line 2 ""x:\dir\subdir\Test\TestComponent.cshtml""
using Microsoft.AspNetCore.Blazor;
#line default
#line hidden
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o = new Microsoft.AspNetCore.Blazor.UIEventHandler(
#line 3 ""x:\dir\subdir\Test\TestComponent.cshtml""
Increment
#line default
#line hidden
);
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
#line 5 ""x:\dir\subdir\Test\TestComponent.cshtml""
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string MyAttr { get; set; }
public RenderFragment ChildContent { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent MyAttr=""abc"">Some text<some-child a='1'>Nested text</some-child></MyComponent>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = ""*, TestAssembly"";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.AddAttribute(-1, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
}
}

View File

@ -0,0 +1,209 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class DesignTimeCodeGenerationTest : RazorBaselineIntegrationTestBase
{
internal override bool DesignTime => true;
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void ChildComponent_WithParameters()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class SomeType
{
}
public class MyComponent : BlazorComponent
{
public int IntProperty { get; set; }
public bool BoolProperty { get; set; }
public string StringProperty { get; set; }
public SomeType ObjectProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent
IntProperty=""123""
BoolProperty=""true""
StringProperty=""My string""
ObjectProperty=""new SomeType()""/>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithExplicitStringParameter()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string StringProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent StringProperty=""@(42.ToString())"" />");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithNonPropertyAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent some-attribute=""foo"" another-attribute=""@(43.ToString())""/>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithLambdaEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent OnClick=""@((e) => { Increment(); })""/>
@functions {
private int counter;
private void Increment() {
counter++;
}
}");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithExplicitEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@using Microsoft.AspNetCore.Blazor
<MyComponent OnClick=""@Increment""/>
@functions {
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
}");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string MyAttr { get; set; }
public RenderFragment ChildContent { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent MyAttr=""abc"">Some text<some-child a='1'>Nested text</some-child></MyComponent>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
}
}

View File

@ -4,6 +4,18 @@
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Exclude the TestFiles directory from default wildcards -->
<DefaultItemExcludes>$(DefaultItemExcludes);TestFiles\**\*</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<!-- Embed test files so they can be referenced in tests -->
<EmbeddedResource Include="TestFiles\**" />
</ItemGroup>
<PropertyGroup Condition="'$(GenerateBaselines)'=='true'">
<DefineConstants>GENERATE_BASELINES;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>

View File

@ -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.Reflection;
using Microsoft.AspNetCore.Blazor.Build.Test;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
public class IntializeTestFileAttribute : BeforeAfterTestAttribute
{
public override void Before(MethodInfo methodUnderTest)
{
if (typeof(RazorBaselineIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.DeclaringType.GetTypeInfo()))
{
var typeName = methodUnderTest.DeclaringType.Name;
RazorBaselineIntegrationTestBase.DirectoryPath = $"TestFiles/{typeName}/{methodUnderTest.Name}";
}
}
public override void After(MethodInfo methodUnderTest)
{
if (typeof(RazorBaselineIntegrationTestBase).GetTypeInfo().IsAssignableFrom(methodUnderTest.DeclaringType.GetTypeInfo()))
{
RazorBaselineIntegrationTestBase.DirectoryPath = null;
}
}
}
}

View File

@ -0,0 +1,46 @@
// 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.IO;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
public static class IntermediateNodeSerializer
{
public static string Serialize(IntermediateNode node)
{
using (var writer = new StringWriter())
{
var walker = new Walker(writer);
walker.Visit(node);
return writer.ToString();
}
}
private class Walker : IntermediateNodeWalker
{
private readonly IntermediateNodeWriter _visitor;
private readonly TextWriter _writer;
public Walker(TextWriter writer)
{
_visitor = new IntermediateNodeWriter(writer);
_writer = writer;
}
public TextWriter Writer { get; }
public override void VisitDefault(IntermediateNode node)
{
_visitor.Visit(node);
_writer.WriteLine();
_visitor.Depth++;
base.VisitDefault(node);
_visitor.Depth--;
}
}
}
}

View File

@ -0,0 +1,275 @@
// 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.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
public static class IntermediateNodeVerifier
{
public static void Verify(IntermediateNode node, string[] baseline)
{
var walker = new Walker(baseline);
walker.Visit(node);
walker.AssertReachedEndOfBaseline();
}
private class Walker : IntermediateNodeWalker
{
private readonly string[] _baseline;
private readonly IntermediateNodeWriter _visitor;
private readonly StringWriter _writer;
private int _index;
public Walker(string[] baseline)
{
_writer = new StringWriter();
_visitor = new IntermediateNodeWriter(_writer);
_baseline = baseline;
}
public TextWriter Writer { get; }
public override void VisitDefault(IntermediateNode node)
{
var expected = _index < _baseline.Length ? _baseline[_index++] : null;
// Write the node as text for comparison
_writer.GetStringBuilder().Clear();
_visitor.Visit(node);
var actual = _writer.GetStringBuilder().ToString();
AssertNodeEquals(node, Ancestors, expected, actual);
_visitor.Depth++;
base.VisitDefault(node);
_visitor.Depth--;
}
public void AssertReachedEndOfBaseline()
{
// Since we're walking the nodes of our generated code there's the chance that our baseline is longer.
Assert.True(_baseline.Length == _index, "Not all lines of the baseline were visited!");
}
private void AssertNodeEquals(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual)
{
if (string.Equals(expected, actual))
{
// YAY!!! everything is great.
return;
}
if (expected == null)
{
var message = "The node is missing from baseline.";
throw new IntermediateNodeBaselineException(node, Ancestors.ToArray(), expected, actual, message);
}
int charsVerified = 0;
AssertNestingEqual(node, ancestors, expected, actual, ref charsVerified);
AssertNameEqual(node, ancestors, expected, actual, ref charsVerified);
AssertDelimiter(node, expected, actual, true, ref charsVerified);
AssertLocationEqual(node, ancestors, expected, actual, ref charsVerified);
AssertDelimiter(node, expected, actual, false, 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(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
{
var i = 0;
for (; i < expected.Length; i++)
{
if (expected[i] != ' ')
{
break;
}
}
var failed = false;
var j = 0;
for (; j < i; j++)
{
if (actual.Length <= j || actual[j] != ' ')
{
failed = true;
break;
}
}
if (actual.Length <= j + 1 || actual[j] == ' ')
{
failed = true;
}
if (failed)
{
var message = "The node is at the wrong level of nesting. This usually means a child is missing.";
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
}
charsVerified = j;
}
private void AssertNameEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
{
var expectedName = GetName(expected, charsVerified);
var actualName = GetName(actual, charsVerified);
if (!string.Equals(expectedName, actualName))
{
var message = $"Node names are not equal.";
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
}
charsVerified += expectedName.Length;
}
// Either both strings need to have a delimiter next or neither should.
private void AssertDelimiter(IntermediateNode node, string expected, string actual, bool required, ref int charsVerified)
{
if (charsVerified == expected.Length && required)
{
throw new InvalidOperationException($"Baseline text is not well-formed: '{expected}'.");
}
if (charsVerified == actual.Length && required)
{
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
}
if (charsVerified == expected.Length && charsVerified == actual.Length)
{
return;
}
var expectedDelimiter = expected.IndexOf(" - ", charsVerified);
if (expectedDelimiter != charsVerified && expectedDelimiter != -1)
{
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
}
var actualDelimiter = actual.IndexOf(" - ", charsVerified);
if (actualDelimiter != charsVerified && actualDelimiter != -1)
{
throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'.");
}
Assert.Equal(expectedDelimiter, actualDelimiter);
charsVerified += 3;
}
private void AssertLocationEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
{
var expectedLocation = GetLocation(expected, charsVerified);
var actualLocation = GetLocation(actual, charsVerified);
if (!string.Equals(expectedLocation, actualLocation))
{
var message = $"Locations are not equal.";
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
}
charsVerified += expectedLocation.Length;
}
private void AssertContentEqual(IntermediateNode node, IEnumerable<IntermediateNode> ancestors, string expected, string actual, ref int charsVerified)
{
var expectedContent = GetContent(expected, charsVerified);
var actualContent = GetContent(actual, charsVerified);
if (!string.Equals(expectedContent, actualContent))
{
var message = $"Contents are not equal.";
throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message);
}
charsVerified += expectedContent.Length;
}
private string GetName(string text, int start)
{
var delimiter = text.IndexOf(" - ", start);
if (delimiter == -1)
{
throw new InvalidOperationException($"Baseline text is not well-formed: '{text}'.");
}
return text.Substring(start, delimiter - start);
}
private string GetLocation(string text, int start)
{
var delimiter = text.IndexOf(" - ", start);
return delimiter == -1 ? text.Substring(start) : text.Substring(start, delimiter - start);
}
private string GetContent(string text, int start)
{
return start == text.Length ? string.Empty : text.Substring(start);
}
private class IntermediateNodeBaselineException : XunitException
{
public IntermediateNodeBaselineException(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage)
: base(Format(node, ancestors, expected, actual, userMessage))
{
Node = node;
Expected = expected;
Actual = actual;
}
public IntermediateNode Node { get; }
public string Actual { get; }
public string Expected { get; }
private static string Format(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage)
{
var builder = new StringBuilder();
builder.AppendLine(userMessage);
builder.AppendLine();
if (expected != null)
{
builder.Append("Expected: ");
builder.AppendLine(expected);
}
if (actual != null)
{
builder.Append("Actual: ");
builder.AppendLine(actual);
}
if (ancestors != null)
{
builder.AppendLine();
builder.AppendLine("Path:");
foreach (var ancestor in ancestors)
{
builder.AppendLine(ancestor.ToString());
}
}
return builder.ToString();
}
}
}
}
}

View File

@ -0,0 +1,292 @@
// 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.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Blazor.Razor;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
// Serializes single IR nodes (shallow).
public class IntermediateNodeWriter :
IntermediateNodeVisitor,
IExtensionIntermediateNodeVisitor<ComponentAttributeExtensionNode>,
IExtensionIntermediateNodeVisitor<ComponentBodyExtensionNode>,
IExtensionIntermediateNodeVisitor<ComponentCloseExtensionNode>,
IExtensionIntermediateNodeVisitor<ComponentOpenExtensionNode>,
IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>
{
private readonly TextWriter _writer;
public IntermediateNodeWriter(TextWriter writer)
{
_writer = writer;
}
public int Depth { get; set; }
public override void VisitDefault(IntermediateNode node)
{
WriteBasicNode(node);
}
public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node)
{
WriteContentNode(node, string.Join(" ", node.Modifiers), node.ClassName, node.BaseType, string.Join(", ", node.Interfaces ?? new List<string>()));
}
public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node)
{
WriteContentNode(node, node.Prefix);
}
public override void VisitCSharpCodeAttributeValue(CSharpCodeAttributeValueIntermediateNode node)
{
WriteContentNode(node, node.Prefix);
}
public override void VisitToken(IntermediateToken node)
{
WriteContentNode(node, node.Kind.ToString(), node.Content);
}
public override void VisitMalformedDirective(MalformedDirectiveIntermediateNode node)
{
WriteContentNode(node, node.DirectiveName);
}
public override void VisitDirective(DirectiveIntermediateNode node)
{
WriteContentNode(node, node.DirectiveName);
}
public override void VisitDirectiveToken(DirectiveTokenIntermediateNode node)
{
WriteContentNode(node, node.Content);
}
public override void VisitFieldDeclaration(FieldDeclarationIntermediateNode node)
{
WriteContentNode(node, string.Join(" ", node.Modifiers), node.FieldType, node.FieldName);
}
public override void VisitHtmlAttribute(HtmlAttributeIntermediateNode node)
{
WriteContentNode(node, node.Prefix, node.Suffix);
}
public override void VisitHtmlAttributeValue(HtmlAttributeValueIntermediateNode node)
{
WriteContentNode(node, node.Prefix);
}
public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node)
{
WriteContentNode(node, node.Content);
}
public override void VisitMethodDeclaration(MethodDeclarationIntermediateNode node)
{
WriteContentNode(node, string.Join(" ", node.Modifiers), node.ReturnType, node.MethodName);
}
public override void VisitUsingDirective(UsingDirectiveIntermediateNode node)
{
WriteContentNode(node, node.Content);
}
public override void VisitTagHelper(TagHelperIntermediateNode node)
{
WriteContentNode(node, node.TagName, string.Format("{0}.{1}", nameof(TagMode), node.TagMode));
}
public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node)
{
WriteContentNode(node, node.AttributeName, node.BoundAttribute.DisplayName, string.Format("HtmlAttributeValueStyle.{0}", node.AttributeStructure));
}
public override void VisitTagHelperHtmlAttribute(TagHelperHtmlAttributeIntermediateNode node)
{
WriteContentNode(node, node.AttributeName, string.Format("HtmlAttributeValueStyle.{0}", node.AttributeStructure));
}
public override void VisitExtension(ExtensionIntermediateNode node)
{
// This will be called for nodes that are internal implementation details of Razor,
// like the design time directive nodes.
if (node.GetType().Assembly == typeof(RazorCodeDocument).Assembly)
{
WriteBasicNode(node);
}
else
{
throw new InvalidOperationException("Unknown node type: " + node.GetType());
}
}
protected void WriteBasicNode(IntermediateNode node)
{
WriteIndent();
WriteName(node);
WriteSeparator();
WriteSourceRange(node);
}
protected void WriteContentNode(IntermediateNode node, params string[] content)
{
WriteIndent();
WriteName(node);
WriteSeparator();
WriteSourceRange(node);
for (var i = 0; i < content.Length; i++)
{
WriteSeparator();
WriteContent(content[i]);
}
}
protected void WriteIndent()
{
for (var i = 0; i < Depth; i++)
{
for (var j = 0; j < 4; j++)
{
_writer.Write(' ');
}
}
}
protected void WriteSeparator()
{
_writer.Write(" - ");
}
protected void WriteNewLine()
{
_writer.WriteLine();
}
protected void WriteName(IntermediateNode node)
{
var typeName = node.GetType().Name;
if (typeName.EndsWith("IntermediateNode"))
{
_writer.Write(typeName.Substring(0, typeName.Length - "IntermediateNode".Length));
}
else
{
_writer.Write(typeName);
}
}
protected void WriteSourceRange(IntermediateNode node)
{
if (node.Source != null)
{
WriteSourceRange(node.Source.Value);
}
}
protected void WriteSourceRange(SourceSpan sourceRange)
{
_writer.Write("(");
_writer.Write(sourceRange.AbsoluteIndex);
_writer.Write(":");
_writer.Write(sourceRange.LineIndex);
_writer.Write(",");
_writer.Write(sourceRange.CharacterIndex);
_writer.Write(" [");
_writer.Write(sourceRange.Length);
_writer.Write("] ");
if (sourceRange.FilePath != null)
{
var fileName = sourceRange.FilePath.Substring(sourceRange.FilePath.LastIndexOf('/') + 1);
_writer.Write(fileName);
}
_writer.Write(")");
}
protected void WriteDiagnostics(IntermediateNode node)
{
if (node.HasDiagnostics)
{
_writer.Write("| ");
for (var i = 0; i < node.Diagnostics.Count; i++)
{
var diagnostic = node.Diagnostics[i];
_writer.Write("{");
WriteSourceRange(diagnostic.Span);
_writer.Write(": ");
_writer.Write(diagnostic.Severity);
_writer.Write(" ");
_writer.Write(diagnostic.Id);
_writer.Write(": ");
// Purposefully not writing out the entire message to ensure readable IR and because messages
// can span multiple lines. Not using string.GetHashCode because we can't have any collisions.
using (var md5 = MD5.Create())
{
var diagnosticMessage = diagnostic.GetMessage();
var messageBytes = Encoding.UTF8.GetBytes(diagnosticMessage);
var messageHash = md5.ComputeHash(messageBytes);
var stringHashBuilder = new StringBuilder();
for (var j = 0; j < messageHash.Length; j++)
{
stringHashBuilder.Append(messageHash[j].ToString("x2"));
}
var stringHash = stringHashBuilder.ToString();
_writer.Write(stringHash);
}
_writer.Write("} ");
}
}
}
protected void WriteContent(string content)
{
if (content == null)
{
return;
}
// We explicitly escape newlines in node content so that the IR can be compared line-by-line. The escaped
// newline cannot be platform specific so we need to drop the windows \r.
// Also, escape our separator so we can search for ` - `to find delimiters.
_writer.Write(content.Replace("\r", string.Empty).Replace("\n", "\\n").Replace(" - ", "\\-"));
}
void IExtensionIntermediateNodeVisitor<ComponentOpenExtensionNode>.VisitExtension(ComponentOpenExtensionNode node)
{
WriteContentNode(node, node.TypeName);
}
void IExtensionIntermediateNodeVisitor<ComponentAttributeExtensionNode>.VisitExtension(ComponentAttributeExtensionNode node)
{
WriteContentNode(node, node.AttributeName, node.PropertyName);
}
void IExtensionIntermediateNodeVisitor<ComponentBodyExtensionNode>.VisitExtension(ComponentBodyExtensionNode node)
{
WriteBasicNode(node);
}
void IExtensionIntermediateNodeVisitor<ComponentCloseExtensionNode>.VisitExtension(ComponentCloseExtensionNode node)
{
WriteBasicNode(node);
}
void IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>.VisitExtension(RouteAttributeExtensionNode node)
{
WriteContentNode(node, node.Template);
}
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Razor.Language
{
public class RazorDiagnosticSerializer
{
public static string Serialize(RazorDiagnostic diagnostic)
{
return diagnostic.ToString();
}
}
}

View File

@ -0,0 +1,47 @@
// 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.Text;
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
public static class SourceMappingsSerializer
{
public static string Serialize(RazorCSharpDocument csharpDocument, RazorSourceDocument sourceDocument)
{
var builder = new StringBuilder();
var charBuffer = new char[sourceDocument.Length];
sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length);
var sourceContent = new string(charBuffer);
for (var i = 0; i < csharpDocument.SourceMappings.Count; i++)
{
var sourceMapping = csharpDocument.SourceMappings[i];
builder.Append("Source Location: ");
AppendMappingLocation(builder, sourceMapping.OriginalSpan, sourceContent);
builder.Append("Generated Location: ");
AppendMappingLocation(builder, sourceMapping.GeneratedSpan, csharpDocument.GeneratedCode);
builder.AppendLine();
}
return builder.ToString();
}
private static void AppendMappingLocation(StringBuilder builder, SourceSpan location, string content)
{
builder
.AppendLine(location.ToString())
.Append("|");
for (var i = 0; i < location.Length; i++)
{
builder.Append(content[location.AbsoluteIndex + i]);
}
builder.AppendLine("|");
}
}
}

View File

@ -0,0 +1,89 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Reflection;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language
{
public class TestFile
{
private TestFile(string resourceName, Assembly assembly)
{
Assembly = assembly;
ResourceName = Assembly.GetName().Name + "." + resourceName.Replace('/', '.').Replace('\\', '.');
}
public Assembly Assembly { get; }
public string ResourceName { get; }
public static TestFile Create(string resourceName, Type type)
{
return new TestFile(resourceName, type.GetTypeInfo().Assembly);
}
public static TestFile Create(string resourceName, Assembly assembly)
{
return new TestFile(resourceName, assembly);
}
public Stream OpenRead()
{
var stream = Assembly.GetManifestResourceStream(ResourceName);
if (stream == null)
{
Assert.True(false, string.Format("Manifest resource: {0} not found", ResourceName));
}
return stream;
}
public bool Exists()
{
var resourceNames = Assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
{
// Resource names are case-sensitive.
if (string.Equals(ResourceName, resourceName, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
public string ReadAllText()
{
using (var reader = new StreamReader(OpenRead()))
{
// The .Replace() calls normalize line endings, in case you get \n instead of \r\n
// since all the unit tests rely on the assumption that the files will have \r\n endings.
return reader.ReadToEnd().Replace("\r", "").Replace("\n", "\r\n");
}
}
/// <summary>
/// Saves the file to the specified path.
/// </summary>
public void Save(string filePath)
{
var directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (var outStream = File.Create(filePath))
{
using (var inStream = OpenRead())
{
inStream.CopyTo(outStream);
}
}
}
}
}

View File

@ -0,0 +1,47 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
namespace Microsoft.AspNetCore.Razor.Language
{
public static class TestProject
{
public static string GetProjectDirectory(Type type)
{
var solutionDir = GetSolutionRootDirectory("Blazor");
var assemblyName = type.Assembly.GetName().Name;
var projectDirectory = Path.Combine(solutionDir, "test", assemblyName);
if (!Directory.Exists(projectDirectory))
{
throw new InvalidOperationException(
$@"Could not locate project directory for type {type.FullName}.
Directory probe path: {projectDirectory}.");
}
return projectDirectory;
}
public static string GetSolutionRootDirectory(string solution)
{
var applicationBasePath = AppContext.BaseDirectory;
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
var projectFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, $"{solution}.sln"));
if (projectFileInfo.Exists)
{
return projectFileInfo.DirectoryName;
}
directoryInfo = directoryInfo.Parent;
}
while (directoryInfo.Parent != null);
throw new Exception($"Solution file {solution}.sln could not be found in {applicationBasePath} or its parent directories.");
}
}
}

View File

@ -0,0 +1,179 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.IntegrationTests;
using Xunit;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
[IntializeTestFile]
public abstract class RazorBaselineIntegrationTestBase : RazorIntegrationTestBase
{
private static readonly AsyncLocal<string> _directoryPath = new AsyncLocal<string>();
protected RazorBaselineIntegrationTestBase()
{
TestProjectRoot = TestProject.GetProjectDirectory(GetType());
}
// Used by the test framework to set the directory for test files.
public static string DirectoryPath
{
get { return _directoryPath.Value; }
set { _directoryPath.Value = value; }
}
#if GENERATE_BASELINES
protected bool GenerateBaselines { get; set; } = true;
#else
protected bool GenerateBaselines { get; set; } = false;
#endif
protected string TestProjectRoot { get; }
// For consistent line endings because the character counts are going to be recorded in files.
internal override string LineEnding => "\r\n";
internal override bool NormalizeSourceLineEndings => true;
internal override string PathSeparator => "\\";
// Force consistent paths since they are going to be recorded in files.
internal override string WorkingDirectory => ArbitraryWindowsPath;
protected void AssertDocumentNodeMatchesBaseline(RazorCodeDocument codeDocument)
{
var document = codeDocument.GetDocumentIntermediateNode();
var baselineFilePath = GetBaselineFilePath(codeDocument, ".ir.txt");
if (GenerateBaselines)
{
var baselineFullPath = Path.Combine(TestProjectRoot, baselineFilePath);
Directory.CreateDirectory(Path.GetDirectoryName(baselineFullPath));
File.WriteAllText(baselineFullPath, IntermediateNodeSerializer.Serialize(document));
return;
}
var irFile = TestFile.Create(baselineFilePath, GetType().Assembly);
if (!irFile.Exists())
{
throw new XunitException($"The resource {baselineFilePath} was not found.");
}
// Normalize newlines by splitting into an array.
var baseline = irFile.ReadAllText().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
IntermediateNodeVerifier.Verify(document, baseline);
}
protected void AssertCSharpDocumentMatchesBaseline(RazorCodeDocument codeDocument)
{
var document = codeDocument.GetCSharpDocument();
var baselineFilePath = GetBaselineFilePath(codeDocument, ".codegen.cs");
var baselineDiagnosticsFilePath = GetBaselineFilePath(codeDocument, ".diagnostics.txt");
var baselineMappingsFilePath = GetBaselineFilePath(codeDocument, ".mappings.txt");
var serializedMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
if (GenerateBaselines)
{
var baselineFullPath = Path.Combine(TestProjectRoot, baselineFilePath);
Directory.CreateDirectory(Path.GetDirectoryName(baselineFullPath));
File.WriteAllText(baselineFullPath, document.GeneratedCode);
var baselineDiagnosticsFullPath = Path.Combine(TestProjectRoot, baselineDiagnosticsFilePath);
var lines = document.Diagnostics.Select(RazorDiagnosticSerializer.Serialize).ToArray();
if (lines.Any())
{
File.WriteAllLines(baselineDiagnosticsFullPath, lines);
}
else if (File.Exists(baselineDiagnosticsFullPath))
{
File.Delete(baselineDiagnosticsFullPath);
}
var baselineMappingsFullPath = Path.Combine(TestProjectRoot, baselineMappingsFilePath);
var text = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
if (!string.IsNullOrEmpty(text))
{
File.WriteAllText(baselineMappingsFullPath, text);
}
else if (File.Exists(baselineMappingsFullPath))
{
File.Delete(baselineMappingsFullPath);
}
return;
}
var codegenFile = TestFile.Create(baselineFilePath, GetType().Assembly);
if (!codegenFile.Exists())
{
throw new XunitException($"The resource {baselineFilePath} was not found.");
}
var baseline = codegenFile.ReadAllText();
// Normalize newlines to match those in the baseline.
var actualCode = document.GeneratedCode.Replace("\r", "").Replace("\n", "\r\n");
Assert.Equal(baseline, actualCode);
var baselineDiagnostics = string.Empty;
var diagnosticsFile = TestFile.Create(baselineDiagnosticsFilePath, GetType().Assembly);
if (diagnosticsFile.Exists())
{
baselineDiagnostics = diagnosticsFile.ReadAllText();
}
var actualDiagnostics = string.Concat(document.Diagnostics.Select(d => RazorDiagnosticSerializer.Serialize(d) + "\r\n"));
Assert.Equal(baselineDiagnostics, actualDiagnostics);
var baselineMappings = string.Empty;
var mappingsFile = TestFile.Create(baselineMappingsFilePath, GetType().Assembly);
if (mappingsFile.Exists())
{
baselineMappings = mappingsFile.ReadAllText();
}
var actualMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
actualMappings = actualMappings.Replace("\r", "").Replace("\n", "\r\n");
Assert.Equal(baselineMappings, actualMappings);
}
private string GetBaselineFilePath(RazorCodeDocument codeDocument, string extension)
{
if (codeDocument == null)
{
throw new ArgumentNullException(nameof(codeDocument));
}
if (extension == null)
{
throw new ArgumentNullException(nameof(extension));
}
var lastSlash = codeDocument.Source.FilePath.LastIndexOfAny(new []{ '/', '\\' });
var fileName = lastSlash == -1 ? null : codeDocument.Source.FilePath.Substring(lastSlash + 1);
if (string.IsNullOrEmpty(fileName))
{
var message = "Integration tests require a filename";
throw new InvalidOperationException(message);
}
if (DirectoryPath == null)
{
var message = $"{nameof(AssertDocumentNodeMatchesBaseline)} should only be called from an integration test..";
throw new InvalidOperationException(message);
}
return Path.Combine(DirectoryPath, Path.ChangeExtension(fileName, extension));
}
}
}

View File

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Blazor.Rendering;
using Microsoft.AspNetCore.Blazor.RenderTree;
using Microsoft.AspNetCore.Blazor.Test.Helpers;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor;
@ -60,11 +61,11 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
Configuration = BlazorExtensionInitializer.DefaultConfiguration;
FileSystem = new VirtualRazorProjectFileSystem();
PathSeparator = Path.DirectorySeparatorChar.ToString();
WorkingDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ArbitraryWindowsPath : ArbitraryMacLinuxPath;
DefaultBaseNamespace = "Test"; // Matches the default working directory
DefaultFileName = "TestComponent.cshtml";
}
internal List<RazorProjectItem> AdditionalRazorItems { get; }
@ -81,6 +82,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
internal virtual VirtualRazorProjectFileSystem FileSystem { get; }
// Used to force a specific style of line-endings for testing. This matters
// for the baseline tests that exercise line mappings. Even though we normalize
// newlines for testing, the difference between platforms affects the data through
// the *count* of characters written.
internal virtual string LineEnding { get; }
internal virtual string PathSeparator { get; }
internal virtual bool NormalizeSourceLineEndings { get; }
internal virtual bool UseTwoPhaseCompilation { get; }
internal virtual string WorkingDirectory { get; }
@ -92,6 +103,11 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
// Turn off checksums, we're testing code generation.
b.Features.Add(new SuppressChecksum());
if (LineEnding != null)
{
b.Phases.Insert(0, new ForceLineEndingPhase(LineEnding));
}
BlazorExtensionInitializer.Register(b);
b.Features.Add(new CompilationTagHelperFeature());
@ -102,20 +118,27 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
});
}
internal RazorProjectItem CreateProjectItem(string chtmlRelativePath, string cshtmlContent)
internal RazorProjectItem CreateProjectItem(string cshtmlRelativePath, string cshtmlContent)
{
var fullPath = WorkingDirectory + PathSeparator + cshtmlRelativePath;
// FilePaths in Razor are **always** are of the form '/a/b/c.cshtml'
var filePath = chtmlRelativePath.Replace('\\', '/');
var filePath = cshtmlRelativePath.Replace('\\', '/');
if (!filePath.StartsWith('/'))
{
filePath = '/' + filePath;
}
if (NormalizeSourceLineEndings)
{
cshtmlContent = cshtmlContent.Replace("\r", "").Replace("\n", LineEnding);
}
return new VirtualProjectItem(
WorkingDirectory,
filePath,
Path.Combine(WorkingDirectory, chtmlRelativePath),
chtmlRelativePath,
fullPath,
cshtmlRelativePath,
Encoding.UTF8.GetBytes(cshtmlContent.TrimStart()));
}
@ -400,5 +423,22 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
options.SuppressChecksum = true;
}
}
private class ForceLineEndingPhase : RazorEnginePhaseBase
{
public ForceLineEndingPhase(string lineEnding)
{
LineEnding = lineEnding;
}
public string LineEnding { get; }
protected override void ExecuteCore(RazorCodeDocument codeDocument)
{
var field = typeof(CodeRenderingContext).GetField("NewLineString", BindingFlags.Static | BindingFlags.NonPublic);
var key = field.GetValue(null);
codeDocument.Items[key] = LineEnding;
}
}
}
}

View File

@ -1,497 +0,0 @@
// 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.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class RuntimeCodeGenerationRazorIntegrationTest : RazorIntegrationTestBase
{
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void CodeGeneration_ChildComponent_Simple()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent />");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithParameters()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class SomeType
{
}
public class MyComponent : BlazorComponent
{
public int IntProperty { get; set; }
public bool BoolProperty { get; set; }
public string StringProperty { get; set; }
public SomeType ObjectProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent
IntProperty=""123""
BoolProperty=""true""
StringProperty=""My string""
ObjectProperty=""new SomeType()""/>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""IntProperty"", 123);
builder.AddAttribute(2, ""BoolProperty"", true);
builder.AddAttribute(3, ""StringProperty"", ""My string"");
builder.AddAttribute(4, ""ObjectProperty"", new SomeType());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithExplicitStringParameter()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string StringProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent StringProperty=""@(42.ToString())"" />");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""StringProperty"", 42.ToString());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithNonPropertyAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent some-attribute=""foo"" another-attribute=""@(43.ToString())""/>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""some-attribute"", ""foo"");
builder.AddAttribute(2, ""another-attribute"", 43.ToString());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithLambdaEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent OnClick=""@(e => { Increment(); })""/>
@functions {
private int counter;
private void Increment() {
counter++;
}
}");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""OnClick"", new Microsoft.AspNetCore.Blazor.UIEventHandler(e => { Increment(); }));
builder.CloseComponent();
builder.AddContent(2, ""\n\n"");
}
#pragma warning restore 1998
#line 4 ""x:\dir\subdir\Test\TestComponent.cshtml""
private int counter;
private void Increment() {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithExplicitEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@using Microsoft.AspNetCore.Blazor
<MyComponent OnClick=""@Increment""/>
@functions {
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
}");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""OnClick"", new Microsoft.AspNetCore.Blazor.UIEventHandler(Increment));
builder.CloseComponent();
builder.AddContent(2, ""\n\n"");
}
#pragma warning restore 1998
#line 5 ""x:\dir\subdir\Test\TestComponent.cshtml""
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string MyAttr { get; set; }
public RenderFragment ChildContent { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent MyAttr=""abc"">Some text<some-child a='1'>Nested text</some-child></MyComponent>");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, ""MyAttr"", ""abc"");
builder.AddAttribute(2, ""ChildContent"", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
builder2.AddContent(3, ""Some text"");
builder2.OpenElement(4, ""some-child"");
builder2.AddAttribute(5, ""a"", ""1"");
builder2.AddContent(6, ""Nested text"");
builder2.CloseElement();
}
));
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
[Fact]
public void CodeGeneration_ChildComponent_WithPageDirective()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@page ""/MyPage""
@page ""/AnotherRoute/{id}""
<MyComponent />");
// Assert
CompileToAssembly(generated);
AssertSourceEquals(@"
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
[Microsoft.AspNetCore.Blazor.Components.RouteAttribute(""/MyPage"")]
[Microsoft.AspNetCore.Blazor.Components.RouteAttribute(""/AnotherRoute/{id}"")]
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
", generated);
}
}
}

View File

@ -0,0 +1,262 @@
// 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.CodeAnalysis.CSharp;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
{
public class RuntimeCodeGenerationTest : RazorBaselineIntegrationTestBase
{
internal override bool UseTwoPhaseCompilation => true;
[Fact]
public void ChildComponent_Simple()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent />");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithParameters()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class SomeType
{
}
public class MyComponent : BlazorComponent
{
public int IntProperty { get; set; }
public bool BoolProperty { get; set; }
public string StringProperty { get; set; }
public SomeType ObjectProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent
IntProperty=""123""
BoolProperty=""true""
StringProperty=""My string""
ObjectProperty=""new SomeType()""/>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithExplicitStringParameter()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string StringProperty { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent StringProperty=""@(42.ToString())"" />");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithNonPropertyAttributes()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent some-attribute=""foo"" another-attribute=""@(43.ToString())""/>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithLambdaEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent OnClick=""@(e => { Increment(); })""/>
@functions {
private int counter;
private void Increment() {
counter++;
}
}");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithExplicitEventHandler()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using System;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public UIEventHandler OnClick { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@using Microsoft.AspNetCore.Blazor
<MyComponent OnClick=""@Increment""/>
@functions {
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
}");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithChildContent()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
public string MyAttr { get; set; }
public RenderFragment ChildContent { get; set; }
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
<MyComponent MyAttr=""abc"">Some text<some-child a='1'>Nested text</some-child></MyComponent>");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ChildComponent_WithPageDirective()
{
// Arrange
AdditionalSyntaxTrees.Add(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class MyComponent : BlazorComponent
{
}
}
"));
// Act
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@page ""/MyPage""
@page ""/AnotherRoute/{id}""
<MyComponent />");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
}
}

View File

@ -0,0 +1,34 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,36 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (31:1,0 [91] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.StartTagAndEndTag
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml) - MyAttr - MyAttr
HtmlContent - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - abc
ComponentBodyExtensionNode -
HtmlContent - (57:1,26 [51] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (57:1,26 [9] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Some text
IntermediateToken - (66:1,35 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <some-child
IntermediateToken - (77:1,46 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - a='1'
IntermediateToken - (83:1,52 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - >
IntermediateToken - (84:1,53 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Nested text
IntermediateToken - (95:1,64 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - </some-child>
ComponentCloseExtensionNode -

View File

@ -0,0 +1,5 @@
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (468:14,38 [15] )
|*, TestAssembly|

View File

@ -0,0 +1,55 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
using Microsoft.AspNetCore.Blazor;
#line default
#line hidden
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o = new Microsoft.AspNetCore.Blazor.UIEventHandler(
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
Increment
#line default
#line hidden
);
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,36 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
UsingDirective - (32:1,1 [33] x:\dir\subdir\Test\TestComponent.cshtml) - Microsoft.AspNetCore.Blazor
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
HtmlContent - (65:1,34 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (65:1,34 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (67:2,0 [35] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (89:2,22 [10] x:\dir\subdir\Test\TestComponent.cshtml) - OnClick - OnClick
CSharpExpression - (90:2,23 [9] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (90:2,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Increment
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -
HtmlContent - (102:2,35 [4] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (102:2,35 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
CSharpCode - (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private int counter;\n private void Increment(UIEventArgs e) {\n counter++;\n }\n

View File

@ -0,0 +1,30 @@
Source Location: (32:1,1 [33] x:\dir\subdir\Test\TestComponent.cshtml)
|using Microsoft.AspNetCore.Blazor|
Generated Location: (257:10,0 [33] )
|using Microsoft.AspNetCore.Blazor|
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (586:19,38 [15] )
|*, TestAssembly|
Source Location: (90:2,23 [9] x:\dir\subdir\Test\TestComponent.cshtml)
|Increment|
Generated Location: (1154:33,23 [9] )
|Increment|
Source Location: (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml)
|
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
|
Generated Location: (1471:44,12 [100] )
|
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
|

View File

@ -0,0 +1,41 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
42.ToString()
#line default
#line hidden
;
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,29 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (31:1,0 [49] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (60:1,29 [16] x:\dir\subdir\Test\TestComponent.cshtml) - StringProperty - StringProperty
CSharpExpression - (62:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (62:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 42.ToString()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,10 @@
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (468:14,38 [15] )
|*, TestAssembly|
Source Location: (62:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml)
|42.ToString()|
Generated Location: (997:28,31 [13] )
|42.ToString()|

View File

@ -0,0 +1,50 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o = new Microsoft.AspNetCore.Blazor.UIEventHandler(
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
(e) => { Increment(); }
#line default
#line hidden
);
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
private int counter;
private void Increment() {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,33 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (31:1,0 [51] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (53:1,22 [26] x:\dir\subdir\Test\TestComponent.cshtml) - OnClick - OnClick
CSharpExpression - (54:1,23 [25] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (55:1,24 [23] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - (e) => { Increment(); }
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -
HtmlContent - (82:1,51 [4] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (82:1,51 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
CSharpCode - (98:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (98:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private int counter;\n private void Increment() {\n counter++;\n }\n

View File

@ -0,0 +1,25 @@
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (468:14,38 [15] )
|*, TestAssembly|
Source Location: (55:1,24 [23] x:\dir\subdir\Test\TestComponent.cshtml)
|(e) => { Increment(); }|
Generated Location: (1037:28,24 [23] )
|(e) => { Increment(); }|
Source Location: (98:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml)
|
private int counter;
private void Increment() {
counter++;
}
|
Generated Location: (1368:39,12 [87] )
|
private int counter;
private void Increment() {
counter++;
}
|

View File

@ -0,0 +1,41 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
43.ToString()
#line default
#line hidden
;
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,32 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (31:1,0 [72] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - - some-attribute -
HtmlContent - (60:1,29 [3] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (60:1,29 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - foo
ComponentAttributeExtensionNode - - another-attribute -
CSharpExpression - (84:1,53 [16] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (86:1,55 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 43.ToString()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,10 @@
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (468:14,38 [15] )
|*, TestAssembly|
Source Location: (86:1,55 [13] x:\dir\subdir\Test\TestComponent.cshtml)
|43.ToString()|
Generated Location: (1021:28,55 [13] )
|43.ToString()|

View File

@ -0,0 +1,55 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o =
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
123
#line default
#line hidden
;
__o =
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
true
#line default
#line hidden
;
__o =
#line 6 "x:\dir\subdir\Test\TestComponent.cshtml"
new SomeType()
#line default
#line hidden
;
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,35 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
TagHelper - (31:1,0 [132] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (63:2,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) - IntProperty - IntProperty
IntermediateToken - (63:2,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 123
ComponentAttributeExtensionNode - (87:3,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) - BoolProperty - BoolProperty
IntermediateToken - (87:3,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - true
ComponentAttributeExtensionNode - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml) - StringProperty - StringProperty
HtmlContent - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml) - Html - My string
ComponentAttributeExtensionNode - (146:5,20 [14] x:\dir\subdir\Test\TestComponent.cshtml) - ObjectProperty - ObjectProperty
IntermediateToken - (146:5,20 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - new SomeType()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,20 @@
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (468:14,38 [15] )
|*, TestAssembly|
Source Location: (63:2,17 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|123|
Generated Location: (983:28,17 [3] )
|123|
Source Location: (87:3,18 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|true|
Generated Location: (1123:35,18 [4] )
|true|
Source Location: (146:5,20 [14] x:\dir\subdir\Test\TestComponent.cshtml)
|new SomeType()|
Generated Location: (1266:42,20 [14] )
|new SomeType()|

View File

@ -0,0 +1,22 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,14 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [15] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,31 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "MyAttr", "abc");
builder.AddAttribute(2, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
builder2.AddContent(3, "Some text");
builder2.OpenElement(4, "some-child");
builder2.AddAttribute(5, "a", "1");
builder2.AddContent(6, "Nested text");
builder2.CloseElement();
}
));
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,24 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [91] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.StartTagAndEndTag
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml) - MyAttr - MyAttr
HtmlContent - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (52:1,21 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - abc
ComponentBodyExtensionNode -
HtmlContent - (57:1,26 [51] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (57:1,26 [9] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Some text
IntermediateToken - (66:1,35 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <some-child
IntermediateToken - (77:1,46 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - a='1'
IntermediateToken - (83:1,52 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - >
IntermediateToken - (84:1,53 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Nested text
IntermediateToken - (95:1,64 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - </some-child>
ComponentCloseExtensionNode -

View File

@ -0,0 +1,34 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "OnClick", new Microsoft.AspNetCore.Blazor.UIEventHandler(Increment));
builder.CloseComponent();
builder.AddContent(2, "\n\n");
}
#pragma warning restore 1998
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,22 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
UsingDirective - (32:1,1 [35] x:\dir\subdir\Test\TestComponent.cshtml) - Microsoft.AspNetCore.Blazor
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (67:2,0 [35] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (89:2,22 [10] x:\dir\subdir\Test\TestComponent.cshtml) - OnClick - OnClick
CSharpExpression - (90:2,23 [9] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (90:2,23 [9] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Increment
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -
HtmlContent - (102:2,35 [4] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (102:2,35 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
CSharpCode - (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private int counter;\n private void Increment(UIEventArgs e) {\n counter++;\n }\n

View File

@ -0,0 +1,15 @@
Source Location: (118:4,12 [100] x:\dir\subdir\Test\TestComponent.cshtml)
|
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
|
Generated Location: (910:23,12 [100] )
|
private int counter;
private void Increment(UIEventArgs e) {
counter++;
}
|

View File

@ -0,0 +1,23 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "StringProperty", 42.ToString());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,17 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [49] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (60:1,29 [16] x:\dir\subdir\Test\TestComponent.cshtml) - StringProperty - StringProperty
CSharpExpression - (62:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (62:1,31 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 42.ToString()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,33 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "OnClick", new Microsoft.AspNetCore.Blazor.UIEventHandler(e => { Increment(); }));
builder.CloseComponent();
builder.AddContent(2, "\n\n");
}
#pragma warning restore 1998
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
private int counter;
private void Increment() {
counter++;
}
#line default
#line hidden
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,21 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [49] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (53:1,22 [24] x:\dir\subdir\Test\TestComponent.cshtml) - OnClick - OnClick
CSharpExpression - (54:1,23 [23] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (55:1,24 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - e => { Increment(); }
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -
HtmlContent - (80:1,49 [4] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (80:1,49 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
CSharpCode - (96:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (96:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private int counter;\n private void Increment() {\n counter++;\n }\n

View File

@ -0,0 +1,15 @@
Source Location: (96:3,12 [87] x:\dir\subdir\Test\TestComponent.cshtml)
|
private int counter;
private void Increment() {
counter++;
}
|
Generated Location: (882:22,12 [87] )
|
private int counter;
private void Increment() {
counter++;
}
|

View File

@ -0,0 +1,24 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "some-attribute", "foo");
builder.AddAttribute(2, "another-attribute", 43.ToString());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,20 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [72] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - - some-attribute -
HtmlContent - (60:1,29 [3] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (60:1,29 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - foo
ComponentAttributeExtensionNode - - another-attribute -
CSharpExpression - (84:1,53 [16] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (86:1,55 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 43.ToString()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,24 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
[Microsoft.AspNetCore.Blazor.Components.RouteAttribute("/MyPage")]
[Microsoft.AspNetCore.Blazor.Components.RouteAttribute("/AnotherRoute/{id}")]
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,16 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
RouteAttributeExtensionNode - - /MyPage
RouteAttributeExtensionNode - - /AnotherRoute/{id}
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (76:3,0 [15] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -

View File

@ -0,0 +1,26 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenComponent<Test.MyComponent>(0);
builder.AddAttribute(1, "IntProperty", 123);
builder.AddAttribute(2, "BoolProperty", true);
builder.AddAttribute(3, "StringProperty", "My string");
builder.AddAttribute(4, "ObjectProperty", new SomeType());
builder.CloseComponent();
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,23 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
TagHelper - (31:1,0 [132] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - TagMode.SelfClosing
ComponentOpenExtensionNode - - Test.MyComponent
ComponentAttributeExtensionNode - (63:2,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) - IntProperty - IntProperty
IntermediateToken - (63:2,17 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 123
ComponentAttributeExtensionNode - (87:3,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) - BoolProperty - BoolProperty
IntermediateToken - (87:3,18 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - true
ComponentAttributeExtensionNode - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml) - StringProperty - StringProperty
HtmlContent - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (114:4,20 [9] x:\dir\subdir\Test\TestComponent.cshtml) - Html - My string
ComponentAttributeExtensionNode - (146:5,20 [14] x:\dir\subdir\Test\TestComponent.cshtml) - ObjectProperty - ObjectProperty
IntermediateToken - (146:5,20 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - new SomeType()
ComponentBodyExtensionNode -
ComponentCloseExtensionNode -