diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs deleted file mode 100644 index d80c2b9b68..0000000000 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/InstrumentationPass.cs +++ /dev/null @@ -1,125 +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 System.Collections.Generic; -using System.Globalization; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.Extensions; -using Microsoft.AspNetCore.Razor.Language.Intermediate; - -namespace Microsoft.AspNetCore.Mvc.Razor.Extensions -{ - public class InstrumentationPass : IntermediateNodePassBase, IRazorOptimizationPass - { - public override int Order => DefaultFeatureOrder; - - protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) - { - if (documentNode.Options.DesignTime) - { - return; - } - - var walker = new Visitor(); - walker.VisitDocument(documentNode); - - for (var i = 0; i < walker.Items.Count; i++) - { - var node = walker.Items[i]; - - AddInstrumentation(node); - } - } - - private static void AddInstrumentation(InstrumentationItem item) - { - var beginContextMethodName = "BeginContext"; // ORIGINAL: BeginContextMethodName - var endContextMethodName = "EndContext"; // ORIGINAL: EndContextMethodName - - var beginNode = new CSharpCodeIntermediateNode(); - beginNode.Children.Add(new IntermediateToken() - { - Kind = TokenKind.CSharp, - Content = string.Format("{0}({1}, {2}, {3});", - beginContextMethodName, - item.Source.AbsoluteIndex.ToString(CultureInfo.InvariantCulture), - item.Source.Length.ToString(CultureInfo.InvariantCulture), - item.IsLiteral ? "true" : "false") - }); - - var endNode = new CSharpCodeIntermediateNode(); - endNode.Children.Add(new IntermediateToken() - { - Kind = TokenKind.CSharp, - Content = string.Format("{0}();", endContextMethodName) - }); - - var nodeIndex = item.Parent.Children.IndexOf(item.Node); - item.Parent.Children.Insert(nodeIndex, beginNode); - item.Parent.Children.Insert(nodeIndex + 2, endNode); - } - - private struct InstrumentationItem - { - public InstrumentationItem(IntermediateNode node, IntermediateNode parent, bool isLiteral, SourceSpan source) - { - Node = node; - Parent = parent; - IsLiteral = isLiteral; - Source = source; - } - - public IntermediateNode Node { get; } - - public IntermediateNode Parent { get; } - - public bool IsLiteral { get; } - - public SourceSpan Source { get; } - } - - private class Visitor : IntermediateNodeWalker - { - public List Items { get; } = new List(); - - public override void VisitHtml(HtmlContentIntermediateNode node) - { - if (node.Source != null) - { - Items.Add(new InstrumentationItem(node, Parent, isLiteral: true, source: node.Source.Value)); - } - - VisitDefault(node); - } - - public override void VisitCSharpExpression(CSharpExpressionIntermediateNode node) - { - if (node.Source != null) - { - Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value)); - } - - VisitDefault(node); - } - - public override void VisitTagHelper(TagHelperIntermediateNode node) - { - if (node.Source != null) - { - Items.Add(new InstrumentationItem(node, Parent, isLiteral: false, source: node.Source.Value)); - } - - // Inside a tag helper we only want to visit inside of the body (skip all of the attributes and properties). - for (var i = 0; i < node.Children.Count; i++) - { - var child = node.Children[i]; - if (child is TagHelperBodyIntermediateNode || - child is DefaultTagHelperBodyIntermediateNode) - { - VisitDefault(child); - } - } - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorExtensions.cs index ff5fcaad68..08c44425a8 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/RazorExtensions.cs @@ -41,50 +41,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions builder.Features.Add(new RazorPageDocumentClassifierPass()); builder.Features.Add(new MvcViewDocumentClassifierPass()); builder.Features.Add(new AssemblyAttributeInjectionPass()); - builder.Features.Add(new InstrumentationPass()); builder.SetImportFeature(new MvcImportProjectFeature()); } - - #region Obsolete - [Obsolete("This method is obsolete and will be removed in a future version.")] - public static void Register(IRazorEngineBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - InjectDirective.Register(builder); - ModelDirective.Register(builder); - NamespaceDirective.Register(builder); - PageDirective.Register(builder); - - FunctionsDirective.Register(builder); - InheritsDirective.Register(builder); - SectionDirective.Register(builder); - - builder.Features.Add(new DefaultTagHelperDescriptorProvider()); - builder.Features.Add(new ViewComponentTagHelperDescriptorProvider()); - - builder.AddTargetExtension(new ViewComponentTagHelperTargetExtension()); - builder.AddTargetExtension(new TemplateTargetExtension() - { - TemplateTypeName = "global::Microsoft.AspNetCore.Mvc.Razor.HelperResult", - }); - - builder.Features.Add(new ModelExpressionPass()); - builder.Features.Add(new PagesPropertyInjectionPass()); - builder.Features.Add(new ViewComponentTagHelperPass()); - builder.Features.Add(new RazorPageDocumentClassifierPass()); - builder.Features.Add(new MvcViewDocumentClassifierPass()); - - if (!builder.DesignTime) - { - builder.Features.Add(new AssemblyAttributeInjectionPass()); - builder.Features.Add(new InstrumentationPass()); - } - } - #endregion } } diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netcore.json b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netcore.json new file mode 100644 index 0000000000..5f5b6444f6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netcore.json @@ -0,0 +1,11 @@ +[ + { + "TypeId": "public static class Microsoft.AspNetCore.Mvc.Razor.Extensions.RazorExtensions", + "MemberId": "public static System.Void Register(Microsoft.AspNetCore.Razor.Language.IRazorEngineBuilder builder)", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Extensions.InstrumentationPass : Microsoft.AspNetCore.Razor.Language.IntermediateNodePassBase, Microsoft.AspNetCore.Razor.Language.IRazorOptimizationPass", + "Kind": "Removal" + } +] diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netframework.json b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netframework.json new file mode 100644 index 0000000000..5f5b6444f6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/breakingchanges.netframework.json @@ -0,0 +1,11 @@ +[ + { + "TypeId": "public static class Microsoft.AspNetCore.Mvc.Razor.Extensions.RazorExtensions", + "MemberId": "public static System.Void Register(Microsoft.AspNetCore.Razor.Language.IRazorEngineBuilder builder)", + "Kind": "Removal" + }, + { + "TypeId": "public class Microsoft.AspNetCore.Mvc.Razor.Extensions.InstrumentationPass : Microsoft.AspNetCore.Razor.Language.IntermediateNodePassBase, Microsoft.AspNetCore.Razor.Language.IRazorOptimizationPass", + "Kind": "Removal" + } +] diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InstrumentationPassTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InstrumentationPassTest.cs deleted file mode 100644 index e9a1d5538a..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InstrumentationPassTest.cs +++ /dev/null @@ -1,348 +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.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.Intermediate; -using Xunit; -using static Microsoft.AspNetCore.Razor.Language.Intermediate.IntermediateNodeAssert; - -namespace Microsoft.AspNetCore.Mvc.Razor.Extensions -{ - public class InstrumentationPassTest - { - [Fact] - public void InstrumentationPass_NoOps_ForDesignTime() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDesignTimeDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new HtmlContentIntermediateNode()); - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.Html, - }); - builder.Pop(); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => IntermediateNodeAssert.Html("Hi", n)); - } - - [Fact] - public void InstrumentationPass_InstrumentsHtml() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - - builder.Push(new HtmlContentIntermediateNode() - { - Source = CreateSource(1), - }); - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.Html, - Source = CreateSource(1) - }); - builder.Pop(); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => BeginInstrumentation("1, 1, true", n), - n => IntermediateNodeAssert.Html("Hi", n), - n => EndInstrumentation(n)); - } - - [Fact] - public void InstrumentationPass_SkipsHtml_WithoutLocation() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new HtmlContentIntermediateNode()); - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.Html, - }); - builder.Pop(); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => IntermediateNodeAssert.Html("Hi", n)); - } - - [Fact] - public void InstrumentationPass_InstrumentsCSharpExpression() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new CSharpExpressionIntermediateNode() - { - Source = CreateSource(2), - }); - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.CSharp, - }); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => BeginInstrumentation("2, 2, false", n), - n => CSharpExpression("Hi", n), - n => EndInstrumentation(n)); - } - - [Fact] - public void InstrumentationPass_SkipsCSharpExpression_WithoutLocation() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new CSharpExpressionIntermediateNode()); - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.CSharp, - }); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => CSharpExpression("Hi", n)); - } - - [Fact] - public void InstrumentationPass_SkipsCSharpExpression_InsideTagHelperAttribute() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new TagHelperIntermediateNode()); - - builder.Push(new TagHelperHtmlAttributeIntermediateNode()); - - builder.Push(new CSharpExpressionIntermediateNode() - { - Source = CreateSource(5) - }); - - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.CSharp, - }); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => - { - Assert.IsType(n); - Children( - n, - c => - { - Assert.IsType(c); - Children( - c, - s => CSharpExpression("Hi", s)); - }); - }); - } - - [Fact] - public void InstrumentationPass_SkipsCSharpExpression_InsideTagHelperProperty() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new TagHelperIntermediateNode()); - - builder.Push(new TagHelperPropertyIntermediateNode()); - - builder.Push(new CSharpExpressionIntermediateNode() - { - Source = CreateSource(5) - }); - - builder.Add(new IntermediateToken() - { - Content = "Hi", - Kind = TokenKind.CSharp, - }); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => - { - Assert.IsType(n); - Children( - n, - c => - { - Assert.IsType(c); - Children( - c, - s => CSharpExpression("Hi", s)); - }); - }); - } - - [Fact] - public void InstrumentationPass_InstrumentsTagHelper() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Add(new TagHelperIntermediateNode() - { - Source = CreateSource(3), - }); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => BeginInstrumentation("3, 3, false", n), - n => Assert.IsType(n), - n => EndInstrumentation(n)); - } - - [Fact] - public void InstrumentationPass_SkipsTagHelper_WithoutLocation() - { - // Arrange - var document = new DocumentIntermediateNode() - { - Options = RazorCodeGenerationOptions.CreateDefault(), - }; - - var builder = IntermediateNodeBuilder.Create(document); - builder.Push(new TagHelperIntermediateNode()); - - var pass = new InstrumentationPass() - { - Engine = RazorProjectEngine.CreateEmpty().Engine, - }; - - // Act - pass.Execute(TestRazorCodeDocument.CreateEmpty(), document); - - // Assert - Children( - document, - n => Assert.IsType(n)); - } - - 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); - } - } -} diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/InstrumentationPassIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/InstrumentationPassIntegrationTest.cs deleted file mode 100644 index 2e312fa430..0000000000 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/InstrumentationPassIntegrationTest.cs +++ /dev/null @@ -1,92 +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 System; -using System.Collections.Generic; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.Extensions; -using Microsoft.AspNetCore.Razor.Language.IntegrationTests; -using Xunit; - -namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.IntegrationTests -{ - public class InstrumentationPassIntegrationTest : IntegrationTestBase - { - [Fact] - public void BasicTest() - { - // Arrange - var descriptors = new[] - { - CreateTagHelperDescriptor( - tagName: "p", - typeName: "PTagHelper", - assemblyName: "TestAssembly"), - CreateTagHelperDescriptor( - tagName: "form", - typeName: "FormTagHelper", - assemblyName: "TestAssembly"), - CreateTagHelperDescriptor( - tagName: "input", - typeName: "InputTagHelper", - assemblyName: "TestAssembly", - attributes: new Action[] - { - builder => builder - .Name("value") - .PropertyName("FooProp") - .TypeName("System.String"), // Gets preallocated - builder => builder - .Name("date") - .PropertyName("BarProp") - .TypeName("System.DateTime"), // Doesn't get preallocated - }) - }; - - var engine = CreateProjectEngine(b => - { - b.AddTagHelpers(descriptors); - b.Features.Add(new InstrumentationPass()); - - // This test includes templates - b.AddTargetExtension(new TemplateTargetExtension()); - }); - - var projectItem = CreateProjectItemFromFile(); - - // Act - var document = engine.Process(projectItem); - - // Assert - AssertDocumentNodeMatchesBaseline(document.GetDocumentIntermediateNode()); - - var csharpDocument = document.GetCSharpDocument(); - AssertCSharpDocumentMatchesBaseline(csharpDocument); - Assert.Empty(csharpDocument.Diagnostics); - } - - private static TagHelperDescriptor CreateTagHelperDescriptor( - string tagName, - string typeName, - string assemblyName, - IEnumerable> attributes = null) - { - var builder = TagHelperDescriptorBuilder.Create(typeName, assemblyName); - builder.TypeName(typeName); - - if (attributes != null) - { - foreach (var attributeBuilder in attributes) - { - builder.BoundAttributeDescriptor(attributeBuilder); - } - } - - builder.TagMatchingRuleDescriptor(ruleBuilder => ruleBuilder.RequireTagName(tagName)); - - var descriptor = builder.Build(); - - return descriptor; - } - } -} diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs index 8e6b1a7bd7..ec84263550 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_Runtime.codegen.cs @@ -19,9 +19,7 @@ namespace AspNetCore #pragma warning disable 1998 public async override global::System.Threading.Tasks.Task ExecuteAsync() { - BeginContext(0, 4, true); WriteLiteral("