Adds Instrumentation support

Instrumentation is added as an optional pass that can be configured by
MVC.
This commit is contained in:
Ajay Bhargav Baaskaran 2016-12-28 16:25:07 -08:00 committed by Ryan Nowak
parent 0324ac80dd
commit ffd455b77e
17 changed files with 594 additions and 34 deletions

View File

@ -0,0 +1,109 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
namespace Microsoft.AspNetCore.Razor.Evolution
{
internal class DefaultInstrumentationPass : RazorIRPassBase
{
public override int Order => RazorIRPass.DefaultLoweringOrder;
public override DocumentIRNode ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
var walker = new Visitor();
walker.VisitDocument(irDocument);
for (var i = 0; i < walker.Items.Count; i++)
{
var node = walker.Items[i];
AddInstrumentation(node);
}
return irDocument;
}
private static void AddInstrumentation(InstrumentationItem item)
{
var beginContextMethodName = "Instrumentation.BeginContext"; /* ORIGINAL: BeginContextMethodName */
var endContextMethodName = "Instrumentation.EndContext"; /* ORIGINAL: EndContextMethodName */
var beginNode = new CSharpStatementIRNode()
{
Content = string.Format("{0}({1}, {2}, {3});",
beginContextMethodName,
item.Source.AbsoluteIndex.ToString(CultureInfo.InvariantCulture),
item.Source.Length.ToString(CultureInfo.InvariantCulture),
item.IsLiteral ? "true" : "false"),
Parent = item.Node.Parent
};
var endNode = new CSharpStatementIRNode()
{
Content = string.Format("{0}();", endContextMethodName),
Parent = item.Node.Parent
};
var nodeIndex = item.Node.Parent.Children.IndexOf(item.Node);
item.Node.Parent.Children.Insert(nodeIndex, beginNode);
item.Node.Parent.Children.Insert(nodeIndex + 2, endNode);
}
private struct InstrumentationItem
{
public InstrumentationItem(RazorIRNode node, bool isLiteral, SourceSpan source)
{
Node = node;
IsLiteral = isLiteral;
Source = source;
}
public RazorIRNode Node { get; }
public bool IsLiteral { get; }
public SourceSpan Source { get; }
}
private class Visitor : RazorIRNodeWalker
{
public List<InstrumentationItem> Items { get; } = new List<InstrumentationItem>();
public override void VisitHtml(HtmlContentIRNode node)
{
if (node.Source != null)
{
Items.Add(new InstrumentationItem(node, isLiteral: true, source: node.Source.Value));
}
VisitDefault(node);
}
public override void VisitCSharpExpression(CSharpExpressionIRNode node)
{
if (node.Source != null && !(node.Parent is CSharpAttributeValueIRNode))
{
Items.Add(new InstrumentationItem(node, isLiteral: false, source: node.Source.Value));
}
VisitDefault(node);
}
internal override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
// As a special case the TagHelperIRNode (which must be the parent) is the one that carries
// the location. The execute node won't have one, but the instrumentation goes around the call
// to execute.
if (node.Parent is TagHelperIRNode && node.Parent.Source != null)
{
Items.Add(new InstrumentationItem(node, isLiteral: false, source: node.Parent.Source.Value));
}
VisitDefault(node);
}
}
}
}

View File

@ -299,7 +299,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
DeclareTagHelperFields(tagHelperBlock);
Builder.Push(new TagHelperIRNode());
Builder.Push(new TagHelperIRNode()
{
Source = BuildSourceRangeFromNode(block)
});
Builder.Push(new InitializeTagHelperStructureIRNode()
{

View File

@ -0,0 +1,213 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
using Xunit;
using static Microsoft.AspNetCore.Razor.Evolution.Intermediate.RazorIRAssert;
namespace Microsoft.AspNetCore.Razor.Evolution
{
public class DefaultInstrumentationPassTest
{
[Fact]
public void InstrumentationPass_InstrumentsHtml()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Add(new HtmlContentIRNode()
{
Content = "Hi",
Source = CreateSource(1),
});
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n => BeginInstrumentation("1, 1, true", n),
n => Html("Hi", n),
n => EndInstrumentation(n));
}
[Fact]
public void InstrumentationPass_SkipsHtml_WithoutLocation()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Add(new HtmlContentIRNode()
{
Content = "Hi",
});
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n => Html("Hi", n));
}
[Fact]
public void InstrumentationPass_InstrumentsCSharpExpression()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Push(new CSharpExpressionIRNode()
{
Source = CreateSource(2),
});
builder.Add(new CSharpTokenIRNode()
{
Content = "Hi",
});
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n => BeginInstrumentation("2, 2, false", n),
n => CSharpExpression("Hi", n),
n => EndInstrumentation(n));
}
[Fact]
public void InstrumentationPass_SkipsCSharpExpression_WithoutLocation()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Push(new CSharpExpressionIRNode());
builder.Add(new CSharpTokenIRNode()
{
Content = "Hi",
});
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n => CSharpExpression("Hi", n));
}
[Fact]
public void InstrumentationPass_InstrumentsExecuteTagHelper_InsideTagHelper()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Push(new TagHelperIRNode()
{
Source = CreateSource(3),
});
builder.Add(new ExecuteTagHelpersIRNode());
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n =>
{
Assert.IsType<TagHelperIRNode>(n);
Children(
n,
c => BeginInstrumentation("3, 3, false", c),
c => Assert.IsType<ExecuteTagHelpersIRNode>(c),
c => EndInstrumentation(c));
});
}
[Fact]
public void InstrumentationPass_SkipsExecuteTagHelper_WithoutLocation()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Push(new TagHelperIRNode());
builder.Add(new ExecuteTagHelpersIRNode());
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n =>
{
Assert.IsType<TagHelperIRNode>(n);
Children(
n,
c => Assert.IsType<ExecuteTagHelpersIRNode>(c));
});
}
[Fact]
public void InstrumentationPass_SkipsExecuteTagHelper_MalformedTagHelper()
{
// Arrange
var builder = RazorIRBuilder.Document();
builder.Push(new TagHelperIRNode()
{
Source = CreateSource(3),
});
builder.Push(new CSharpExpressionIRNode());
builder.Add(new ExecuteTagHelpersIRNode()); // Malformed
var irDocument = (DocumentIRNode)builder.Build();
var pass = new DefaultInstrumentationPass();
// Act
var result = pass.ExecuteCore(TestRazorCodeDocument.CreateEmpty(), irDocument);
// Assert
Children(
irDocument,
n =>
{
Assert.IsType<TagHelperIRNode>(n);
Children(
n,
c => SingleChild<ExecuteTagHelpersIRNode>(Assert.IsType<CSharpExpressionIRNode>(c)));
});
}
private SourceSpan CreateSource(int number)
{
// The actual source span doesn't really matter, we just want to see the values used.
return new SourceSpan(new SourceLocation(number, number, number), number);
}
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Testing.xunit;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests

View File

@ -1419,7 +1419,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
{
builder.Features.Add(new ApiSetsIRTestAdapter());
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
DefaultRazorRuntimeCSharpLoweringPhase.GenerateUniqueTagHelperId = "test";
});
var document = CreateCodeDocument();
@ -1438,7 +1437,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
{
builder.Features.Add(new ApiSetsIRTestAdapter());
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
DefaultRazorRuntimeCSharpLoweringPhase.GenerateUniqueTagHelperId = "test";
});
var document = CreateCodeDocument();

View File

@ -0,0 +1,58 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
{
public class InstrumentationPassIntegrationTest : IntegrationTestBase
{
[Fact]
public void BasicTest()
{
// Arrange
var descriptors = new[]
{
new TagHelperDescriptor
{
TagName = "p",
TypeName = "PTagHelper"
},
new TagHelperDescriptor
{
TagName = "form",
TypeName = "FormTagHelper"
},
new TagHelperDescriptor
{
TagName = "input",
TypeName = "InputTagHelper",
Attributes = new[]
{
new TagHelperAttributeDescriptor
{
Name = "value",
PropertyName = "FooProp",
TypeName = "System.String"
}
}
}
};
var engine = RazorEngine.Create(b =>
{
b.AddTagHelpers(descriptors);
b.Features.Add(new DefaultInstrumentationPass());
});
var document = CreateCodeDocument();
// Act
engine.Process(document);
// Assert
AssertIRMatchesBaseline(document.GetIRDocument());
AssertCSharpDocumentMatchesBaseline(document.GetCSharpDocument());
}
}
}

View File

@ -88,6 +88,9 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
throw new XunitException($"The resource {sourceFilename} was not found.");
}
// This will ensure that we're not putting any randomly generated data in a baseline.
DefaultRazorRuntimeCSharpLoweringPhase.GenerateUniqueTagHelperId = "test";
return RazorCodeDocument.Create(TestRazorSourceDocument.CreateResource(sourceFilename));
}

View File

@ -1,8 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
@ -22,8 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
}
};
var engine = RazorEngine.Create(
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
var document = CreateCodeDocument();
// Act
@ -52,8 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
}
};
var engine = RazorEngine.Create(
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
var document = CreateCodeDocument();
// Act
@ -92,8 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
}
};
var engine = RazorEngine.Create(
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
var document = CreateCodeDocument();
// Act
@ -102,20 +97,5 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
// Assert
AssertIRMatchesBaseline(document.GetIRDocument());
}
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
{
private readonly IEnumerable<TagHelperDescriptor> _descriptors;
public TestTagHelperDescriptorResolver(IEnumerable<TagHelperDescriptor> descriptors)
{
_descriptors = descriptors;
}
public IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext)
{
return _descriptors;
}
}
}
}

View File

@ -145,7 +145,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
try
{
Assert.Equal(prefix, attributeValue.Prefix);
Children(attributeValue, n => CSharpExpression(expected, n));
}
catch (XunitException e)
@ -189,6 +188,32 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
}
}
public static void BeginInstrumentation(string expected, RazorIRNode node)
{
try
{
var beginNode = Assert.IsType<CSharpStatementIRNode>(node);
Assert.Equal($"Instrumentation.BeginContext({expected});", beginNode.Content);
}
catch (XunitException e)
{
throw new IRAssertException(node, node.Children, e.Message, e);
}
}
public static void EndInstrumentation(RazorIRNode node)
{
try
{
var endNode = Assert.IsType<CSharpStatementIRNode>(node);
Assert.Equal("Instrumentation.EndContext();", endNode.Content);
}
catch (XunitException e)
{
throw new IRAssertException(node, node.Children, e.Message, e);
}
}
internal static void TagHelperFieldDeclaration(RazorIRNode node, params string[] tagHelperTypes)
{
var declareTagHelperFields = Assert.IsType<DeclareTagHelperFieldsIRNode>(node);

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1;net451</TargetFrameworks>

View File

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Evolution
{
public static class RazorEngineBuilderExtensions
{
public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, params TagHelperDescriptor[] tagHelpers)
{
var resolver = (TestTagHelperDescriptorResolver)builder.Features.OfType<TagHelperFeature>().FirstOrDefault()?.Resolver;
if (resolver == null)
{
resolver = new TestTagHelperDescriptorResolver();
builder.Features.Add(new TagHelperFeature(resolver));
}
resolver.TagHelpers.AddRange(tagHelpers);
return builder;
}
private class TestTagHelperDescriptorResolver : ITagHelperDescriptorResolver
{
public List<TagHelperDescriptor> TagHelpers { get; } = new List<TagHelperDescriptor>();
public IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext)
{
return TagHelpers;
}
}
}
}

View File

@ -0,0 +1,89 @@
#pragma checksum "TestFiles/IntegrationTests/InstrumentationPassIntegrationTest/BasicTest.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "7e1ceb3e8ebe2125cd44bea5d9f4ac1acf9ec12b"
namespace
{
#line hidden
using System;
using System.Threading.Tasks;
class
{
private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute __tagHelperAttribute_0 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute("value", "Hello", global::Microsoft.AspNetCore.Razor.Evolution.Legacy.HtmlAttributeValueStyle.DoubleQuotes);
private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute __tagHelperAttribute_1 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute("type", new global::Microsoft.AspNetCore.Html.HtmlString("text"), global::Microsoft.AspNetCore.Razor.Evolution.Legacy.HtmlAttributeValueStyle.SingleQuotes);
private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute __tagHelperAttribute_2 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute("unbound", new global::Microsoft.AspNetCore.Html.HtmlString("foo"), global::Microsoft.AspNetCore.Razor.Evolution.Legacy.HtmlAttributeValueStyle.DoubleQuotes);
#line hidden
#pragma warning disable 0414
private string __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext = null;
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner();
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __backed__tagHelperScopeManager = null;
private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager
{
get
{
if (__backed__tagHelperScopeManager == null)
{
__backed__tagHelperScopeManager = new Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager(StartTagHelperWritingScope, EndTagHelperWritingScope);
}
return __backed__tagHelperScopeManager;
}
}
private global::FormTagHelper __FormTagHelper = null;
private global::InputTagHelper __InputTagHelper = null;
#pragma warning disable 1998
()
{
Instrumentation.BeginContext(31, 28, true);
WriteLiteral("<span someattr>Hola</span>\r\n");
Instrumentation.EndContext();
Instrumentation.BeginContext(61, 7, false);
#line 3 "TestFiles/IntegrationTests/InstrumentationPassIntegrationTest/BasicTest.cshtml"
Write("Hello");
#line default
#line hidden
Instrumentation.EndContext();
Instrumentation.BeginContext(69, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("form", global::Microsoft.AspNetCore.Razor.Evolution.TagMode.StartTagAndEndTag, "test", async() => {
Instrumentation.BeginContext(91, 6, true);
WriteLiteral("\r\n ");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", global::Microsoft.AspNetCore.Razor.Evolution.TagMode.SelfClosing, "test", async() => {
}
);
__InputTagHelper = CreateTagHelper<global::InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
__InputTagHelper.FooProp = (string)__tagHelperAttribute_0.Value;
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_0);
__tagHelperExecutionContext.AddHtmlAttribute(__tagHelperAttribute_1);
Instrumentation.BeginContext(97, 33, false);
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
if (!__tagHelperExecutionContext.Output.IsContentModified)
{
await __tagHelperExecutionContext.SetOutputContentAsync();
}
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.EndContext();
Instrumentation.BeginContext(130, 2, true);
WriteLiteral("\r\n");
Instrumentation.EndContext();
}
);
__FormTagHelper = CreateTagHelper<global::FormTagHelper>();
__tagHelperExecutionContext.Add(__FormTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute(__tagHelperAttribute_2);
Instrumentation.BeginContext(71, 68, false);
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
if (!__tagHelperExecutionContext.Output.IsContentModified)
{
await __tagHelperExecutionContext.SetOutputContentAsync();
}
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.EndContext();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,6 @@
@addTagHelper *, TestAssembly
<span someattr>Hola</span>
@("Hello")
<form unbound="foo">
<input value=Hello type='text' />
</form>

View File

@ -0,0 +1,42 @@
Document -
Checksum -
NamespaceDeclaration - -
UsingStatement - - System
UsingStatement - - System.Threading.Tasks
ClassDeclaration - - - - -
DeclarePreallocatedTagHelperAttribute - - __tagHelperAttribute_0 - value - Hello - HtmlAttributeValueStyle.DoubleQuotes
DeclarePreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_1 - type - text - HtmlAttributeValueStyle.SingleQuotes
DeclarePreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_2 - unbound - foo - HtmlAttributeValueStyle.DoubleQuotes
DeclareTagHelperFields - - FormTagHelper - InputTagHelper
RazorMethodDeclaration - - - - -
CSharpStatement - - Instrumentation.BeginContext(31, 28, true);
HtmlContent - (31:1,0 [28] BasicTest.cshtml) - <span someattr>Hola</span>\n
CSharpStatement - - Instrumentation.EndContext();
CSharpStatement - - Instrumentation.BeginContext(61, 7, false);
CSharpExpression - (61:2,2 [7] BasicTest.cshtml)
CSharpToken - (61:2,2 [7] BasicTest.cshtml) - "Hello"
CSharpStatement - - Instrumentation.EndContext();
CSharpStatement - - Instrumentation.BeginContext(69, 2, true);
HtmlContent - (69:2,10 [2] BasicTest.cshtml) - \n
CSharpStatement - - Instrumentation.EndContext();
TagHelper - (71:3,0 [68] BasicTest.cshtml)
InitializeTagHelperStructure - - form - TagMode.StartTagAndEndTag
CSharpStatement - - Instrumentation.BeginContext(91, 6, true);
HtmlContent - (91:3,20 [6] BasicTest.cshtml) - \n
CSharpStatement - - Instrumentation.EndContext();
TagHelper - (97:4,4 [33] BasicTest.cshtml)
InitializeTagHelperStructure - - input - TagMode.SelfClosing
CreateTagHelper - - InputTagHelper
SetPreallocatedTagHelperProperty - - __tagHelperAttribute_0 - value - FooProp
AddPreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_1
CSharpStatement - - Instrumentation.BeginContext(97, 33, false);
ExecuteTagHelpers -
CSharpStatement - - Instrumentation.EndContext();
CSharpStatement - - Instrumentation.BeginContext(130, 2, true);
HtmlContent - (130:4,37 [2] BasicTest.cshtml) - \n
CSharpStatement - - Instrumentation.EndContext();
CreateTagHelper - - FormTagHelper
AddPreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_2
CSharpStatement - - Instrumentation.BeginContext(71, 68, false);
ExecuteTagHelpers -
CSharpStatement - - Instrumentation.EndContext();

View File

@ -9,17 +9,17 @@ Document -
DeclarePreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_2 - unbound - foo - HtmlAttributeValueStyle.DoubleQuotes
DeclareTagHelperFields - - PTagHelper - FormTagHelper - InputTagHelper
RazorMethodDeclaration - - - - -
TagHelper -
TagHelper - (31:1,0 [20] NestedTagHelpers.cshtml)
InitializeTagHelperStructure - - p - TagMode.StartTagAndEndTag
HtmlContent - (43:1,12 [4] NestedTagHelpers.cshtml) - Hola
CreateTagHelper - - PTagHelper
AddTagHelperHtmlAttribute - - someattr - HtmlAttributeValueStyle.Minimized
ExecuteTagHelpers -
HtmlContent - (51:1,20 [2] NestedTagHelpers.cshtml) - \n
TagHelper -
TagHelper - (53:2,0 [68] NestedTagHelpers.cshtml)
InitializeTagHelperStructure - - form - TagMode.StartTagAndEndTag
HtmlContent - (73:2,20 [6] NestedTagHelpers.cshtml) - \n
TagHelper -
TagHelper - (79:3,4 [33] NestedTagHelpers.cshtml)
InitializeTagHelperStructure - - input - TagMode.SelfClosing
CreateTagHelper - - InputTagHelper
SetPreallocatedTagHelperProperty - - __tagHelperAttribute_0 - value - FooProp

View File

@ -9,7 +9,7 @@ Document -
DeclareTagHelperFields - - InputTagHelper
RazorMethodDeclaration - - - - -
HtmlContent - (31:1,0 [25] SimpleTagHelpers.cshtml) - <p>Hola</p>\n<form>\n
TagHelper -
TagHelper - (56:3,4 [35] SimpleTagHelpers.cshtml)
InitializeTagHelperStructure - - input - TagMode.SelfClosing
CreateTagHelper - - InputTagHelper
AddPreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_0

View File

@ -8,7 +8,7 @@ Document -
DeclareTagHelperFields - - InputTagHelper
RazorMethodDeclaration - - - - -
HtmlContent - (31:1,0 [12] TagHelpersWithBoundAttributes.cshtml) - <form>\n
TagHelper -
TagHelper - (43:2,4 [34] TagHelpersWithBoundAttributes.cshtml)
InitializeTagHelperStructure - - input - TagMode.SelfClosing
CreateTagHelper - - InputTagHelper
SetTagHelperProperty - (56:2,17 [6] TagHelpersWithBoundAttributes.cshtml) - bound - FooProp - HtmlAttributeValueStyle.DoubleQuotes