Adds Instrumentation support
Instrumentation is added as an optional pass that can be configured by MVC.
This commit is contained in:
parent
0324ac80dd
commit
ffd455b77e
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -299,7 +299,10 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
||||||
|
|
||||||
DeclareTagHelperFields(tagHelperBlock);
|
DeclareTagHelperFields(tagHelperBlock);
|
||||||
|
|
||||||
Builder.Push(new TagHelperIRNode());
|
Builder.Push(new TagHelperIRNode()
|
||||||
|
{
|
||||||
|
Source = BuildSourceRangeFromNode(block)
|
||||||
|
});
|
||||||
|
|
||||||
Builder.Push(new InitializeTagHelperStructureIRNode()
|
Builder.Push(new InitializeTagHelperStructureIRNode()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
|
|
|
||||||
|
|
@ -1419,7 +1419,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
{
|
{
|
||||||
builder.Features.Add(new ApiSetsIRTestAdapter());
|
builder.Features.Add(new ApiSetsIRTestAdapter());
|
||||||
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
|
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
|
||||||
DefaultRazorRuntimeCSharpLoweringPhase.GenerateUniqueTagHelperId = "test";
|
|
||||||
});
|
});
|
||||||
var document = CreateCodeDocument();
|
var document = CreateCodeDocument();
|
||||||
|
|
||||||
|
|
@ -1438,7 +1437,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
{
|
{
|
||||||
builder.Features.Add(new ApiSetsIRTestAdapter());
|
builder.Features.Add(new ApiSetsIRTestAdapter());
|
||||||
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
|
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
|
||||||
DefaultRazorRuntimeCSharpLoweringPhase.GenerateUniqueTagHelperId = "test";
|
|
||||||
});
|
});
|
||||||
var document = CreateCodeDocument();
|
var document = CreateCodeDocument();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -88,6 +88,9 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
throw new XunitException($"The resource {sourceFilename} was not found.");
|
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));
|
return RazorCodeDocument.Create(TestRazorSourceDocument.CreateResource(sourceFilename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
|
|
@ -22,8 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var engine = RazorEngine.Create(
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
|
||||||
var document = CreateCodeDocument();
|
var document = CreateCodeDocument();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -52,8 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var engine = RazorEngine.Create(
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
|
||||||
var document = CreateCodeDocument();
|
var document = CreateCodeDocument();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -92,8 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var engine = RazorEngine.Create(
|
var engine = RazorEngine.Create(builder => builder.AddTagHelpers(descriptors));
|
||||||
builder => builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors))));
|
|
||||||
var document = CreateCodeDocument();
|
var document = CreateCodeDocument();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -102,20 +97,5 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
|
||||||
// Assert
|
// Assert
|
||||||
AssertIRMatchesBaseline(document.GetIRDocument());
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,6 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Assert.Equal(prefix, attributeValue.Prefix);
|
Assert.Equal(prefix, attributeValue.Prefix);
|
||||||
|
|
||||||
Children(attributeValue, n => CSharpExpression(expected, n));
|
Children(attributeValue, n => CSharpExpression(expected, n));
|
||||||
}
|
}
|
||||||
catch (XunitException e)
|
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)
|
internal static void TagHelperFieldDeclaration(RazorIRNode node, params string[] tagHelperTypes)
|
||||||
{
|
{
|
||||||
var declareTagHelperFields = Assert.IsType<DeclareTagHelperFieldsIRNode>(node);
|
var declareTagHelperFields = Assert.IsType<DeclareTagHelperFieldsIRNode>(node);
|
||||||
|
|
|
||||||
|
|
@ -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" />
|
<Import Project="..\..\build\common.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp1.1;net451</TargetFrameworks>
|
<TargetFrameworks>netcoreapp1.1;net451</TargetFrameworks>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
@addTagHelper *, TestAssembly
|
||||||
|
<span someattr>Hola</span>
|
||||||
|
@("Hello")
|
||||||
|
<form unbound="foo">
|
||||||
|
<input value=Hello type='text' />
|
||||||
|
</form>
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -9,17 +9,17 @@ Document -
|
||||||
DeclarePreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_2 - unbound - foo - HtmlAttributeValueStyle.DoubleQuotes
|
DeclarePreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_2 - unbound - foo - HtmlAttributeValueStyle.DoubleQuotes
|
||||||
DeclareTagHelperFields - - PTagHelper - FormTagHelper - InputTagHelper
|
DeclareTagHelperFields - - PTagHelper - FormTagHelper - InputTagHelper
|
||||||
RazorMethodDeclaration - - - - -
|
RazorMethodDeclaration - - - - -
|
||||||
TagHelper -
|
TagHelper - (31:1,0 [20] NestedTagHelpers.cshtml)
|
||||||
InitializeTagHelperStructure - - p - TagMode.StartTagAndEndTag
|
InitializeTagHelperStructure - - p - TagMode.StartTagAndEndTag
|
||||||
HtmlContent - (43:1,12 [4] NestedTagHelpers.cshtml) - Hola
|
HtmlContent - (43:1,12 [4] NestedTagHelpers.cshtml) - Hola
|
||||||
CreateTagHelper - - PTagHelper
|
CreateTagHelper - - PTagHelper
|
||||||
AddTagHelperHtmlAttribute - - someattr - HtmlAttributeValueStyle.Minimized
|
AddTagHelperHtmlAttribute - - someattr - HtmlAttributeValueStyle.Minimized
|
||||||
ExecuteTagHelpers -
|
ExecuteTagHelpers -
|
||||||
HtmlContent - (51:1,20 [2] NestedTagHelpers.cshtml) - \n
|
HtmlContent - (51:1,20 [2] NestedTagHelpers.cshtml) - \n
|
||||||
TagHelper -
|
TagHelper - (53:2,0 [68] NestedTagHelpers.cshtml)
|
||||||
InitializeTagHelperStructure - - form - TagMode.StartTagAndEndTag
|
InitializeTagHelperStructure - - form - TagMode.StartTagAndEndTag
|
||||||
HtmlContent - (73:2,20 [6] NestedTagHelpers.cshtml) - \n
|
HtmlContent - (73:2,20 [6] NestedTagHelpers.cshtml) - \n
|
||||||
TagHelper -
|
TagHelper - (79:3,4 [33] NestedTagHelpers.cshtml)
|
||||||
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||||
CreateTagHelper - - InputTagHelper
|
CreateTagHelper - - InputTagHelper
|
||||||
SetPreallocatedTagHelperProperty - - __tagHelperAttribute_0 - value - FooProp
|
SetPreallocatedTagHelperProperty - - __tagHelperAttribute_0 - value - FooProp
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ Document -
|
||||||
DeclareTagHelperFields - - InputTagHelper
|
DeclareTagHelperFields - - InputTagHelper
|
||||||
RazorMethodDeclaration - - - - -
|
RazorMethodDeclaration - - - - -
|
||||||
HtmlContent - (31:1,0 [25] SimpleTagHelpers.cshtml) - <p>Hola</p>\n<form>\n
|
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
|
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||||
CreateTagHelper - - InputTagHelper
|
CreateTagHelper - - InputTagHelper
|
||||||
AddPreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_0
|
AddPreallocatedTagHelperHtmlAttribute - - __tagHelperAttribute_0
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ Document -
|
||||||
DeclareTagHelperFields - - InputTagHelper
|
DeclareTagHelperFields - - InputTagHelper
|
||||||
RazorMethodDeclaration - - - - -
|
RazorMethodDeclaration - - - - -
|
||||||
HtmlContent - (31:1,0 [12] TagHelpersWithBoundAttributes.cshtml) - <form>\n
|
HtmlContent - (31:1,0 [12] TagHelpersWithBoundAttributes.cshtml) - <form>\n
|
||||||
TagHelper -
|
TagHelper - (43:2,4 [34] TagHelpersWithBoundAttributes.cshtml)
|
||||||
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
InitializeTagHelperStructure - - input - TagMode.SelfClosing
|
||||||
CreateTagHelper - - InputTagHelper
|
CreateTagHelper - - InputTagHelper
|
||||||
SetTagHelperProperty - (56:2,17 [6] TagHelpersWithBoundAttributes.cshtml) - bound - FooProp - HtmlAttributeValueStyle.DoubleQuotes
|
SetTagHelperProperty - (56:2,17 [6] TagHelpersWithBoundAttributes.cshtml) - bound - FooProp - HtmlAttributeValueStyle.DoubleQuotes
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue