From 80d1ed36ee190e56641500a6890874e427e5686a Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 11:30:02 -0700 Subject: [PATCH 01/24] Merge CodeRenderingContext and DefaultCodeRenderingContext --- .../DesignTimeNodeWriterTest.cs | 6 +- .../DefaultTagHelperTargetExtensionTest.cs | 2 +- ...reallocatedAttributeTargetExtensionTest.cs | 2 +- .../CodeGeneration/CodeRenderingContext.cs | 214 +++++++++++++++-- .../DefaultCodeRenderingContext.cs | 227 ------------------ .../CodeGeneration/DefaultDocumentWriter.cs | 8 +- .../TestCodeRenderingContext.cs | 4 +- 7 files changed, 207 insertions(+), 256 deletions(-) delete mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs index 1724a5ad318..cb41431080b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs @@ -58,7 +58,7 @@ public void WriteUsingDirective_WithSource_WritesContentWithLinePragmaAndMapping writer.WriteUsingDirective(context, node); // Assert - var mapping = Assert.Single(((DefaultCodeRenderingContext)context).SourceMappings); + var mapping = Assert.Single(context.SourceMappings); Assert.Equal(expectedSourceMapping, mapping); var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @@ -94,7 +94,7 @@ public void WriteUsingDirective_WithSourceAndLineDirectives_WritesContentWithLin writer.WriteUsingDirective(context, node); // Assert - var mapping = Assert.Single(((DefaultCodeRenderingContext)context).SourceMappings); + var mapping = Assert.Single(context.SourceMappings); Assert.Equal(expectedSourceMapping, mapping); var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @@ -587,7 +587,7 @@ public void LinePragma_Enhanced_Is_Adjusted_On_Windows(string fileName, string e csharp, ignoreLineEndingDifferences: true); - Assert.Single(((DefaultCodeRenderingContext)context).SourceMappings); + Assert.Single(context.SourceMappings); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs index b4db68fecc6..937e8ccbfbc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs @@ -1148,7 +1148,7 @@ public void GetDeterministicId_IsDeterministic() private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node) { - ((DefaultCodeRenderingContext)context).AncestorsInternal.Push(node); + context.AncestorsInternal.Push(node); } private static TagHelperDescriptor CreateTagHelperDescriptor( diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs index 4dc46aa39d1..f0ca482b667 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs @@ -273,6 +273,6 @@ public void WriteSetPreallocatedTagHelperProperty_IndexerAttribute_MultipleValue private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node) { - ((DefaultCodeRenderingContext)context).AncestorsInternal.Push(node); + context.AncestorsInternal.Push(node); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 4b005b08902..751c5cf9717 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -5,49 +5,227 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language.Intermediate; +using Microsoft.AspNetCore.Razor.PooledObjects; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; -public abstract class CodeRenderingContext : IDisposable +public sealed class CodeRenderingContext : IDisposable { internal static readonly object NewLineString = "NewLineString"; internal static readonly object SuppressUniqueIds = "SuppressUniqueIds"; - public abstract IEnumerable Ancestors { get; } + private readonly Stack _ancestors; + private readonly RazorCodeDocument _codeDocument; + private readonly DocumentIntermediateNode _documentNode; + private readonly List _scopes; - public abstract CodeWriter CodeWriter { get; } + private readonly PooledObject.Builder> _sourceMappingsBuilder; - public abstract RazorDiagnosticCollection Diagnostics { get; } + public CodeRenderingContext( + IntermediateNodeWriter nodeWriter, + RazorCodeDocument codeDocument, + DocumentIntermediateNode documentNode, + RazorCodeGenerationOptions options) + { + if (nodeWriter == null) + { + throw new ArgumentNullException(nameof(nodeWriter)); + } + + if (codeDocument == null) + { + throw new ArgumentNullException(nameof(codeDocument)); + } + + if (documentNode == null) + { + throw new ArgumentNullException(nameof(documentNode)); + } + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + _codeDocument = codeDocument; + _documentNode = documentNode; + Options = options; + + _ancestors = new Stack(); + Diagnostics = new RazorDiagnosticCollection(); + Items = new ItemCollection(); + _sourceMappingsBuilder = ArrayBuilderPool.GetPooledObject(); + LinePragmas = new List(); + + var diagnostics = _documentNode.GetAllDiagnostics(); + for (var i = 0; i < diagnostics.Count; i++) + { + Diagnostics.Add(diagnostics[i]); + } + + // Set new line character to a specific string regardless of platform, for testing purposes. + var newLineString = codeDocument.Items[NewLineString] as string ?? Environment.NewLine; + CodeWriter = new CodeWriter(newLineString, options); + + Items[NewLineString] = codeDocument.Items[NewLineString]; + Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; + + _scopes = new List(); + _scopes.Add(new ScopeInternal(nodeWriter)); + } + + // This will be initialized by the document writer when the context is 'live'. + public IntermediateNodeVisitor Visitor { get; set; } - public abstract string DocumentKind { get; } + public IEnumerable Ancestors => _ancestors; - public abstract ItemCollection Items { get; } + internal Stack AncestorsInternal => _ancestors; - public abstract IntermediateNodeWriter NodeWriter { get; } + public CodeWriter CodeWriter { get; } - public abstract RazorCodeGenerationOptions Options { get; } + public RazorDiagnosticCollection Diagnostics { get; } - public abstract IntermediateNode Parent { get; } + public string DocumentKind => _documentNode.DocumentKind; - public abstract RazorSourceDocument SourceDocument { get; } + public ItemCollection Items { get; } - public abstract void AddSourceMappingFor(IntermediateNode node); + public ImmutableArray.Builder SourceMappings => _sourceMappingsBuilder.Object; - public abstract void AddSourceMappingFor(SourceSpan node, int offset = 0); + internal List LinePragmas { get; } - public abstract void RenderNode(IntermediateNode node); + public IntermediateNodeWriter NodeWriter => Current.Writer; - public abstract void RenderNode(IntermediateNode node, IntermediateNodeWriter writer); + public RazorCodeGenerationOptions Options { get; } - public abstract void RenderChildren(IntermediateNode node); + public IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek(); - public abstract void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer); + public RazorSourceDocument SourceDocument => _codeDocument.Source; + + private ScopeInternal Current => _scopes[_scopes.Count - 1]; + + public void AddSourceMappingFor(IntermediateNode node) + { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + if (node.Source == null) + { + return; + } + + AddSourceMappingFor(node.Source.Value); + } + + public void AddSourceMappingFor(SourceSpan source, int offset = 0) + { + if (SourceDocument.FilePath != null && + !string.Equals(SourceDocument.FilePath, source.FilePath, StringComparison.OrdinalIgnoreCase)) + { + // We don't want to generate line mappings for imports. + return; + } + + var currentLocation = CodeWriter.Location with { AbsoluteIndex = CodeWriter.Location.AbsoluteIndex + offset, CharacterIndex = CodeWriter.Location.CharacterIndex + offset }; + + var generatedLocation = new SourceSpan(currentLocation, source.Length); + var sourceMapping = new SourceMapping(source, generatedLocation); + + SourceMappings.Add(sourceMapping); + } + + public void RenderChildren(IntermediateNode node) + { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + _ancestors.Push(node); + + for (var i = 0; i < node.Children.Count; i++) + { + Visitor.Visit(node.Children[i]); + } + + _ancestors.Pop(); + } - public virtual void AddLinePragma(LinePragma linePragma) + public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + _scopes.Add(new ScopeInternal(writer)); + _ancestors.Push(node); + + for (var i = 0; i < node.Children.Count; i++) + { + Visitor.Visit(node.Children[i]); + } + + _ancestors.Pop(); + _scopes.RemoveAt(_scopes.Count - 1); } - public abstract void Dispose(); + public void RenderNode(IntermediateNode node) + { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + Visitor.Visit(node); + } + + public void RenderNode(IntermediateNode node, IntermediateNodeWriter writer) + { + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + _scopes.Add(new ScopeInternal(writer)); + + Visitor.Visit(node); + + _scopes.RemoveAt(_scopes.Count - 1); + } + + public void AddLinePragma(LinePragma linePragma) + { + LinePragmas.Add(linePragma); + } + + public void Dispose() + { + _sourceMappingsBuilder.Dispose(); + CodeWriter.Dispose(); + } + + private struct ScopeInternal + { + public ScopeInternal(IntermediateNodeWriter writer) + { + Writer = writer; + } + + public IntermediateNodeWriter Writer { get; } + } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs deleted file mode 100644 index 0769b7045eb..00000000000 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultCodeRenderingContext.cs +++ /dev/null @@ -1,227 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using Microsoft.AspNetCore.Razor.Language.Intermediate; -using Microsoft.AspNetCore.Razor.PooledObjects; - -namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; - -internal class DefaultCodeRenderingContext : CodeRenderingContext -{ - private readonly Stack _ancestors; - private readonly RazorCodeDocument _codeDocument; - private readonly DocumentIntermediateNode _documentNode; - private readonly List _scopes; - - private readonly PooledObject.Builder> _sourceMappingsBuilder; - - public DefaultCodeRenderingContext( - IntermediateNodeWriter nodeWriter, - RazorCodeDocument codeDocument, - DocumentIntermediateNode documentNode, - RazorCodeGenerationOptions options) - { - if (nodeWriter == null) - { - throw new ArgumentNullException(nameof(nodeWriter)); - } - - if (codeDocument == null) - { - throw new ArgumentNullException(nameof(codeDocument)); - } - - if (documentNode == null) - { - throw new ArgumentNullException(nameof(documentNode)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - _codeDocument = codeDocument; - _documentNode = documentNode; - Options = options; - - _ancestors = new Stack(); - Diagnostics = new RazorDiagnosticCollection(); - Items = new ItemCollection(); - _sourceMappingsBuilder = ArrayBuilderPool.GetPooledObject(); - LinePragmas = new List(); - - var diagnostics = _documentNode.GetAllDiagnostics(); - for (var i = 0; i < diagnostics.Count; i++) - { - Diagnostics.Add(diagnostics[i]); - } - - // Set new line character to a specific string regardless of platform, for testing purposes. - var newLineString = codeDocument.Items[NewLineString] as string ?? Environment.NewLine; - CodeWriter = new CodeWriter(newLineString, options); - - Items[NewLineString] = codeDocument.Items[NewLineString]; - Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; - - _scopes = new List(); - _scopes.Add(new ScopeInternal(nodeWriter)); - } - - // This will be initialized by the document writer when the context is 'live'. - public IntermediateNodeVisitor Visitor { get; set; } - - public override IEnumerable Ancestors => _ancestors; - - internal Stack AncestorsInternal => _ancestors; - - public override CodeWriter CodeWriter { get; } - - public override RazorDiagnosticCollection Diagnostics { get; } - - public override string DocumentKind => _documentNode.DocumentKind; - - public override ItemCollection Items { get; } - - public ImmutableArray.Builder SourceMappings => _sourceMappingsBuilder.Object; - - internal List LinePragmas { get; } - - public override IntermediateNodeWriter NodeWriter => Current.Writer; - - public override RazorCodeGenerationOptions Options { get; } - - public override IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek(); - - public override RazorSourceDocument SourceDocument => _codeDocument.Source; - - private ScopeInternal Current => _scopes[_scopes.Count - 1]; - - public override void AddSourceMappingFor(IntermediateNode node) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (node.Source == null) - { - return; - } - - AddSourceMappingFor(node.Source.Value); - } - - public override void AddSourceMappingFor(SourceSpan source, int offset = 0) - { - if (SourceDocument.FilePath != null && - !string.Equals(SourceDocument.FilePath, source.FilePath, StringComparison.OrdinalIgnoreCase)) - { - // We don't want to generate line mappings for imports. - return; - } - - var currentLocation = CodeWriter.Location with { AbsoluteIndex = CodeWriter.Location.AbsoluteIndex + offset, CharacterIndex = CodeWriter.Location.CharacterIndex + offset }; - - var generatedLocation = new SourceSpan(currentLocation, source.Length); - var sourceMapping = new SourceMapping(source, generatedLocation); - - SourceMappings.Add(sourceMapping); - } - - public override void RenderChildren(IntermediateNode node) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - _ancestors.Push(node); - - for (var i = 0; i < node.Children.Count; i++) - { - Visitor.Visit(node.Children[i]); - } - - _ancestors.Pop(); - } - - public override void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - _scopes.Add(new ScopeInternal(writer)); - _ancestors.Push(node); - - for (var i = 0; i < node.Children.Count; i++) - { - Visitor.Visit(node.Children[i]); - } - - _ancestors.Pop(); - _scopes.RemoveAt(_scopes.Count - 1); - } - - public override void RenderNode(IntermediateNode node) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - Visitor.Visit(node); - } - - public override void RenderNode(IntermediateNode node, IntermediateNodeWriter writer) - { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - _scopes.Add(new ScopeInternal(writer)); - - Visitor.Visit(node); - - _scopes.RemoveAt(_scopes.Count - 1); - } - - public override void AddLinePragma(LinePragma linePragma) - { - LinePragmas.Add(linePragma); - } - - public override void Dispose() - { - _sourceMappingsBuilder.Dispose(); - CodeWriter.Dispose(); - } - - private struct ScopeInternal - { - public ScopeInternal(IntermediateNodeWriter writer) - { - Writer = writer; - } - - public IntermediateNodeWriter Writer { get; } - } -} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 72c3b39d0f1..0e21d769dcf 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -33,7 +33,7 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument throw new ArgumentNullException(nameof(documentNode)); } - using var context = new DefaultCodeRenderingContext( + using var context = new CodeRenderingContext( _codeTarget.CreateNodeWriter(), codeDocument, documentNode, @@ -56,16 +56,16 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument private class Visitor : IntermediateNodeVisitor { - private readonly DefaultCodeRenderingContext _context; + private readonly CodeRenderingContext _context; private readonly CodeTarget _target; - public Visitor(CodeTarget target, DefaultCodeRenderingContext context) + public Visitor(CodeTarget target, CodeRenderingContext context) { _target = target; _context = context; } - private DefaultCodeRenderingContext Context => _context; + private CodeRenderingContext Context => _context; public override void VisitDocument(DocumentIntermediateNode node) { diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index e4f695cc133..f665107bcdd 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -39,7 +39,7 @@ public static CodeRenderingContext CreateDesignTime( nodeWriter = new DesignTimeNodeWriter(); } - var context = new DefaultCodeRenderingContext(nodeWriter, codeDocument, documentNode, options); + var context = new CodeRenderingContext(nodeWriter, codeDocument, documentNode, options); context.Visitor = new RenderChildrenVisitor(context); return context; @@ -75,7 +75,7 @@ public static CodeRenderingContext CreateRuntime( nodeWriter = new RuntimeNodeWriter(); } - var context = new DefaultCodeRenderingContext(nodeWriter, codeDocument, documentNode, options); + var context = new CodeRenderingContext(nodeWriter, codeDocument, documentNode, options); context.Visitor = new RenderChildrenVisitor(context); return context; From 0e1774a4ee13fe1e62a8b43000857467ef758c9a Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 11:37:13 -0700 Subject: [PATCH 02/24] Clean up CodeRenderingContext a bit --- .../CodeGeneration/CodeRenderingContext.cs | 99 +++++-------------- 1 file changed, 24 insertions(+), 75 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 751c5cf9717..a077c33699f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -13,10 +13,18 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; public sealed class CodeRenderingContext : IDisposable { + private readonly record struct ScopeInternal(IntermediateNodeWriter Writer); + internal static readonly object NewLineString = "NewLineString"; internal static readonly object SuppressUniqueIds = "SuppressUniqueIds"; + public RazorCodeGenerationOptions Options { get; } + public CodeWriter CodeWriter { get; } + public RazorDiagnosticCollection Diagnostics { get; } + internal List LinePragmas { get; } + public ItemCollection Items { get; } + private readonly Stack _ancestors; private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; @@ -30,35 +38,20 @@ public CodeRenderingContext( DocumentIntermediateNode documentNode, RazorCodeGenerationOptions options) { - if (nodeWriter == null) - { - throw new ArgumentNullException(nameof(nodeWriter)); - } - - if (codeDocument == null) - { - throw new ArgumentNullException(nameof(codeDocument)); - } - - if (documentNode == null) - { - throw new ArgumentNullException(nameof(documentNode)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } + ArgHelper.ThrowIfNull(nodeWriter); + ArgHelper.ThrowIfNull(codeDocument); + ArgHelper.ThrowIfNull(documentNode); + ArgHelper.ThrowIfNull(options); _codeDocument = codeDocument; _documentNode = documentNode; Options = options; _ancestors = new Stack(); - Diagnostics = new RazorDiagnosticCollection(); - Items = new ItemCollection(); + Diagnostics = []; + Items = []; _sourceMappingsBuilder = ArrayBuilderPool.GetPooledObject(); - LinePragmas = new List(); + LinePragmas = []; var diagnostics = _documentNode.GetAllDiagnostics(); for (var i = 0; i < diagnostics.Count; i++) @@ -73,8 +66,7 @@ public CodeRenderingContext( Items[NewLineString] = codeDocument.Items[NewLineString]; Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; - _scopes = new List(); - _scopes.Add(new ScopeInternal(nodeWriter)); + _scopes = [new(nodeWriter)]; } // This will be initialized by the document writer when the context is 'live'. @@ -84,34 +76,21 @@ public CodeRenderingContext( internal Stack AncestorsInternal => _ancestors; - public CodeWriter CodeWriter { get; } - - public RazorDiagnosticCollection Diagnostics { get; } - public string DocumentKind => _documentNode.DocumentKind; - public ItemCollection Items { get; } - public ImmutableArray.Builder SourceMappings => _sourceMappingsBuilder.Object; - internal List LinePragmas { get; } - public IntermediateNodeWriter NodeWriter => Current.Writer; - public RazorCodeGenerationOptions Options { get; } - public IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek(); public RazorSourceDocument SourceDocument => _codeDocument.Source; - private ScopeInternal Current => _scopes[_scopes.Count - 1]; + private ScopeInternal Current => _scopes[^1]; public void AddSourceMappingFor(IntermediateNode node) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } + ArgHelper.ThrowIfNull(node); if (node.Source == null) { @@ -140,10 +119,7 @@ public void AddSourceMappingFor(SourceSpan source, int offset = 0) public void RenderChildren(IntermediateNode node) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } + ArgHelper.ThrowIfNull(node); _ancestors.Push(node); @@ -157,15 +133,8 @@ public void RenderChildren(IntermediateNode node) public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } + ArgHelper.ThrowIfNull(node); + ArgHelper.ThrowIfNull(writer); _scopes.Add(new ScopeInternal(writer)); _ancestors.Push(node); @@ -181,25 +150,15 @@ public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) public void RenderNode(IntermediateNode node) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } + ArgHelper.ThrowIfNull(node); Visitor.Visit(node); } public void RenderNode(IntermediateNode node, IntermediateNodeWriter writer) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } + ArgHelper.ThrowIfNull(node); + ArgHelper.ThrowIfNull(writer); _scopes.Add(new ScopeInternal(writer)); @@ -218,14 +177,4 @@ public void Dispose() _sourceMappingsBuilder.Dispose(); CodeWriter.Dispose(); } - - private struct ScopeInternal - { - public ScopeInternal(IntermediateNodeWriter writer) - { - Writer = writer; - } - - public IntermediateNodeWriter Writer { get; } - } } From 86e05ee42caa7ac34ead0e07205e0f57a594c636 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 11:46:01 -0700 Subject: [PATCH 03/24] Pool scope stack in CodeRenderingContext --- .../CodeGeneration/CodeRenderingContext.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index a077c33699f..d76312144ec 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -28,9 +28,9 @@ public sealed class CodeRenderingContext : IDisposable private readonly Stack _ancestors; private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; - private readonly List _scopes; - private readonly PooledObject.Builder> _sourceMappingsBuilder; + private readonly PooledObject> _pooledScopeStack; + private readonly PooledObject.Builder> _pooledSourceMappings; public CodeRenderingContext( IntermediateNodeWriter nodeWriter, @@ -50,7 +50,7 @@ public CodeRenderingContext( _ancestors = new Stack(); Diagnostics = []; Items = []; - _sourceMappingsBuilder = ArrayBuilderPool.GetPooledObject(); + _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); LinePragmas = []; var diagnostics = _documentNode.GetAllDiagnostics(); @@ -66,7 +66,8 @@ public CodeRenderingContext( Items[NewLineString] = codeDocument.Items[NewLineString]; Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; - _scopes = [new(nodeWriter)]; + _pooledScopeStack = StackPool.GetPooledObject(out var scopeStack); + scopeStack.Push(new(nodeWriter)); } // This will be initialized by the document writer when the context is 'live'. @@ -78,7 +79,7 @@ public CodeRenderingContext( public string DocumentKind => _documentNode.DocumentKind; - public ImmutableArray.Builder SourceMappings => _sourceMappingsBuilder.Object; + public ImmutableArray.Builder SourceMappings => _pooledSourceMappings.Object; public IntermediateNodeWriter NodeWriter => Current.Writer; @@ -86,7 +87,8 @@ public CodeRenderingContext( public RazorSourceDocument SourceDocument => _codeDocument.Source; - private ScopeInternal Current => _scopes[^1]; + private Stack ScopeStack => _pooledScopeStack.Object; + private ScopeInternal Current => ScopeStack.Peek(); public void AddSourceMappingFor(IntermediateNode node) { @@ -136,7 +138,7 @@ public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) ArgHelper.ThrowIfNull(node); ArgHelper.ThrowIfNull(writer); - _scopes.Add(new ScopeInternal(writer)); + ScopeStack.Push(new ScopeInternal(writer)); _ancestors.Push(node); for (var i = 0; i < node.Children.Count; i++) @@ -145,7 +147,7 @@ public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) } _ancestors.Pop(); - _scopes.RemoveAt(_scopes.Count - 1); + ScopeStack.Pop(); } public void RenderNode(IntermediateNode node) @@ -160,11 +162,11 @@ public void RenderNode(IntermediateNode node, IntermediateNodeWriter writer) ArgHelper.ThrowIfNull(node); ArgHelper.ThrowIfNull(writer); - _scopes.Add(new ScopeInternal(writer)); + ScopeStack.Push(new ScopeInternal(writer)); Visitor.Visit(node); - _scopes.RemoveAt(_scopes.Count - 1); + ScopeStack.Pop(); } public void AddLinePragma(LinePragma linePragma) @@ -174,7 +176,8 @@ public void AddLinePragma(LinePragma linePragma) public void Dispose() { - _sourceMappingsBuilder.Dispose(); + _pooledScopeStack.Dispose(); + _pooledSourceMappings.Dispose(); CodeWriter.Dispose(); } } From 635695fefb2d648af7bd41c8186ba188fafb4776 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 13:08:59 -0700 Subject: [PATCH 04/24] Pool line pragmas in CodeRenderingContext --- .../src/Language/CodeGeneration/CodeRenderingContext.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index d76312144ec..e8484c3e2ca 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -22,7 +22,6 @@ public sealed class CodeRenderingContext : IDisposable public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } public RazorDiagnosticCollection Diagnostics { get; } - internal List LinePragmas { get; } public ItemCollection Items { get; } private readonly Stack _ancestors; @@ -31,6 +30,7 @@ public sealed class CodeRenderingContext : IDisposable private readonly PooledObject> _pooledScopeStack; private readonly PooledObject.Builder> _pooledSourceMappings; + private readonly PooledObject> _pooledLinePragmas; public CodeRenderingContext( IntermediateNodeWriter nodeWriter, @@ -51,7 +51,7 @@ public CodeRenderingContext( Diagnostics = []; Items = []; _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); - LinePragmas = []; + _pooledLinePragmas = ListPool.GetPooledObject(); var diagnostics = _documentNode.GetAllDiagnostics(); for (var i = 0; i < diagnostics.Count; i++) @@ -81,6 +81,8 @@ public CodeRenderingContext( public ImmutableArray.Builder SourceMappings => _pooledSourceMappings.Object; + internal List LinePragmas => _pooledLinePragmas.Object; + public IntermediateNodeWriter NodeWriter => Current.Writer; public IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek(); @@ -176,6 +178,7 @@ public void AddLinePragma(LinePragma linePragma) public void Dispose() { + _pooledLinePragmas.Dispose(); _pooledScopeStack.Dispose(); _pooledSourceMappings.Dispose(); CodeWriter.Dispose(); From 7ba41799a581693ce7be2093efe4620e26d40244 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 13:13:50 -0700 Subject: [PATCH 05/24] Pool ancestor stack in CodeRenderingContext --- .../CodeGeneration/CodeRenderingContext.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index e8484c3e2ca..cff81d39bc2 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -24,10 +24,10 @@ public sealed class CodeRenderingContext : IDisposable public RazorDiagnosticCollection Diagnostics { get; } public ItemCollection Items { get; } - private readonly Stack _ancestors; private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; + private readonly PooledObject> _pooledAncestors; private readonly PooledObject> _pooledScopeStack; private readonly PooledObject.Builder> _pooledSourceMappings; private readonly PooledObject> _pooledLinePragmas; @@ -47,7 +47,7 @@ public CodeRenderingContext( _documentNode = documentNode; Options = options; - _ancestors = new Stack(); + _pooledAncestors = StackPool.GetPooledObject(); Diagnostics = []; Items = []; _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); @@ -73,9 +73,9 @@ public CodeRenderingContext( // This will be initialized by the document writer when the context is 'live'. public IntermediateNodeVisitor Visitor { get; set; } - public IEnumerable Ancestors => _ancestors; + public IEnumerable Ancestors => _pooledAncestors.Object; - internal Stack AncestorsInternal => _ancestors; + internal Stack AncestorsInternal => _pooledAncestors.Object; public string DocumentKind => _documentNode.DocumentKind; @@ -85,7 +85,7 @@ public CodeRenderingContext( public IntermediateNodeWriter NodeWriter => Current.Writer; - public IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek(); + public IntermediateNode Parent => AncestorsInternal.Count == 0 ? null : AncestorsInternal.Peek(); public RazorSourceDocument SourceDocument => _codeDocument.Source; @@ -125,14 +125,14 @@ public void RenderChildren(IntermediateNode node) { ArgHelper.ThrowIfNull(node); - _ancestors.Push(node); + AncestorsInternal.Push(node); for (var i = 0; i < node.Children.Count; i++) { Visitor.Visit(node.Children[i]); } - _ancestors.Pop(); + AncestorsInternal.Pop(); } public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) @@ -141,14 +141,14 @@ public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) ArgHelper.ThrowIfNull(writer); ScopeStack.Push(new ScopeInternal(writer)); - _ancestors.Push(node); + AncestorsInternal.Push(node); for (var i = 0; i < node.Children.Count; i++) { Visitor.Visit(node.Children[i]); } - _ancestors.Pop(); + AncestorsInternal.Pop(); ScopeStack.Pop(); } @@ -178,6 +178,7 @@ public void AddLinePragma(LinePragma linePragma) public void Dispose() { + _pooledAncestors.Dispose(); _pooledLinePragmas.Dispose(); _pooledScopeStack.Dispose(); _pooledSourceMappings.Dispose(); From 25acc07be27fa2086ebedb6859a71314989f872e Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 13:27:56 -0700 Subject: [PATCH 06/24] Merge RazorCSharpDocument and DefaultRazorCSharpDocument --- .../CodeGeneration/DefaultDocumentWriter.cs | 2 +- .../Language/DefaultRazorCSharpDocument.cs | 60 ------------- .../src/Language/RazorCSharpDocument.cs | 90 ++++++++----------- 3 files changed, 39 insertions(+), 113 deletions(-) delete mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCSharpDocument.cs diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 0e21d769dcf..3de9fb44296 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -45,7 +45,7 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument var cSharp = context.CodeWriter.GenerateCode(); var allOrderedDiagnostics = context.Diagnostics.OrderBy(diagnostic => diagnostic.Span.AbsoluteIndex); - return new DefaultRazorCSharpDocument( + return new RazorCSharpDocument( codeDocument, cSharp, _options, diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCSharpDocument.cs deleted file mode 100644 index 381a092eba7..00000000000 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCSharpDocument.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; - -namespace Microsoft.AspNetCore.Razor.Language; - -internal class DefaultRazorCSharpDocument : RazorCSharpDocument -{ - private readonly string _generatedCode; - private readonly RazorDiagnostic[] _diagnostics; - private readonly ImmutableArray _sourceMappings; - private readonly LinePragma[] _linePragmas; - private readonly RazorCodeGenerationOptions _options; - private readonly RazorCodeDocument _codeDocument; - - public DefaultRazorCSharpDocument( - RazorCodeDocument codeDocument, - string generatedCode, - RazorCodeGenerationOptions options, - RazorDiagnostic[] diagnostics, - ImmutableArray sourceMappings, - LinePragma[] linePragmas) - { - if (generatedCode == null) - { - throw new ArgumentNullException(nameof(generatedCode)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - _codeDocument = codeDocument; - _generatedCode = generatedCode; - _options = options; - - _diagnostics = diagnostics ?? Array.Empty(); - _sourceMappings = sourceMappings; - _linePragmas = linePragmas ?? Array.Empty(); - } - - public override IReadOnlyList Diagnostics => _diagnostics; - - public override string GeneratedCode => _generatedCode; - - public override ImmutableArray SourceMappings => _sourceMappings; - - internal override IReadOnlyList LinePragmas => _linePragmas; - - public override RazorCodeGenerationOptions Options => _options; - - public override RazorCodeDocument CodeDocument => _codeDocument; -} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs index fc16701d2f7..ade80932a0d 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -11,46 +8,46 @@ namespace Microsoft.AspNetCore.Razor.Language; -public abstract class RazorCSharpDocument : IRazorGeneratedDocument +public sealed class RazorCSharpDocument : IRazorGeneratedDocument { - public abstract string GeneratedCode { get; } - - public abstract ImmutableArray SourceMappings { get; } - - public abstract IReadOnlyList Diagnostics { get; } - - public abstract RazorCodeGenerationOptions Options { get; } - - public abstract RazorCodeDocument CodeDocument { get; } - - internal virtual IReadOnlyList LinePragmas { get; } + public RazorCodeDocument CodeDocument { get; } + public string GeneratedCode { get; } + public RazorCodeGenerationOptions Options { get; } + public IReadOnlyList Diagnostics { get; } + public ImmutableArray SourceMappings { get; } + internal IReadOnlyList LinePragmas { get; } + + public RazorCSharpDocument( + RazorCodeDocument codeDocument, + string generatedCode, + RazorCodeGenerationOptions options, + RazorDiagnostic[] diagnostics, + ImmutableArray sourceMappings, + LinePragma[] linePragmas) + { + ArgHelper.ThrowIfNull(codeDocument); + ArgHelper.ThrowIfNull(generatedCode); - [Obsolete("For backwards compatibility only. Use the overload that takes a RazorCodeDocument")] - public static RazorCSharpDocument Create(string generatedCode, RazorCodeGenerationOptions options, IEnumerable diagnostics) - => Create(codeDocument: null, generatedCode, options, diagnostics); + CodeDocument = codeDocument; + GeneratedCode = generatedCode; + Options = options; - [Obsolete("For backwards compatibility only. Use the overload that takes a RazorCodeDocument")] - public static RazorCSharpDocument Create(string generatedCode, RazorCodeGenerationOptions options, IEnumerable diagnostics, ImmutableArray sourceMappings, IEnumerable linePragmas) - => Create(codeDocument: null, generatedCode, options, diagnostics, sourceMappings, linePragmas); + Diagnostics = diagnostics ?? []; + SourceMappings = sourceMappings; + LinePragmas = linePragmas ?? []; + } - public static RazorCSharpDocument Create(RazorCodeDocument codeDocument, string generatedCode, RazorCodeGenerationOptions options, IEnumerable diagnostics) + public static RazorCSharpDocument Create( + RazorCodeDocument codeDocument, + string generatedCode, + RazorCodeGenerationOptions options, + IEnumerable diagnostics) { - if (generatedCode == null) - { - throw new ArgumentNullException(nameof(generatedCode)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - if (diagnostics == null) - { - throw new ArgumentNullException(nameof(diagnostics)); - } + ArgHelper.ThrowIfNull(generatedCode); + ArgHelper.ThrowIfNull(options); + ArgHelper.ThrowIfNull(diagnostics); - return new DefaultRazorCSharpDocument(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings: ImmutableArray.Empty, linePragmas: null); + return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings: [], linePragmas: []); } public static RazorCSharpDocument Create( @@ -61,21 +58,10 @@ public static RazorCSharpDocument Create( ImmutableArray sourceMappings, IEnumerable linePragmas) { - if (generatedCode == null) - { - throw new ArgumentNullException(nameof(generatedCode)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - if (diagnostics == null) - { - throw new ArgumentNullException(nameof(diagnostics)); - } + ArgHelper.ThrowIfNull(generatedCode); + ArgHelper.ThrowIfNull(options); + ArgHelper.ThrowIfNull(diagnostics); - return new DefaultRazorCSharpDocument(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings, linePragmas.ToArray()); + return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings, linePragmas.ToArray()); } } From d00b1ffab8c4a5a348d2020f8394e8f921b45402 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 13:44:53 -0700 Subject: [PATCH 07/24] Switch CodeRenderingContext.LinePragmas to an ImmutableArray --- .../Language/CodeGeneration/CodeRenderingContext.cs | 6 +++--- .../Language/CodeGeneration/DefaultDocumentWriter.cs | 2 +- .../src/Language/RazorCSharpDocument.cs | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index cff81d39bc2..b3517e1055f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -30,7 +30,7 @@ public sealed class CodeRenderingContext : IDisposable private readonly PooledObject> _pooledAncestors; private readonly PooledObject> _pooledScopeStack; private readonly PooledObject.Builder> _pooledSourceMappings; - private readonly PooledObject> _pooledLinePragmas; + private readonly PooledObject.Builder> _pooledLinePragmas; public CodeRenderingContext( IntermediateNodeWriter nodeWriter, @@ -51,7 +51,7 @@ public CodeRenderingContext( Diagnostics = []; Items = []; _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); - _pooledLinePragmas = ListPool.GetPooledObject(); + _pooledLinePragmas = ArrayBuilderPool.GetPooledObject(); var diagnostics = _documentNode.GetAllDiagnostics(); for (var i = 0; i < diagnostics.Count; i++) @@ -81,7 +81,7 @@ public CodeRenderingContext( public ImmutableArray.Builder SourceMappings => _pooledSourceMappings.Object; - internal List LinePragmas => _pooledLinePragmas.Object; + internal ImmutableArray.Builder LinePragmas => _pooledLinePragmas.Object; public IntermediateNodeWriter NodeWriter => Current.Writer; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 3de9fb44296..92c8a3ca94d 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -51,7 +51,7 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument _options, allOrderedDiagnostics.ToArray(), context.SourceMappings.DrainToImmutable(), - context.LinePragmas.ToArray()); + context.LinePragmas.DrainToImmutable()); } private class Visitor : IntermediateNodeVisitor diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs index ade80932a0d..20baddcb80b 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs @@ -15,7 +15,7 @@ public sealed class RazorCSharpDocument : IRazorGeneratedDocument public RazorCodeGenerationOptions Options { get; } public IReadOnlyList Diagnostics { get; } public ImmutableArray SourceMappings { get; } - internal IReadOnlyList LinePragmas { get; } + internal ImmutableArray LinePragmas { get; } public RazorCSharpDocument( RazorCodeDocument codeDocument, @@ -23,7 +23,7 @@ public RazorCSharpDocument( RazorCodeGenerationOptions options, RazorDiagnostic[] diagnostics, ImmutableArray sourceMappings, - LinePragma[] linePragmas) + ImmutableArray linePragmas) { ArgHelper.ThrowIfNull(codeDocument); ArgHelper.ThrowIfNull(generatedCode); @@ -33,8 +33,8 @@ public RazorCSharpDocument( Options = options; Diagnostics = diagnostics ?? []; - SourceMappings = sourceMappings; - LinePragmas = linePragmas ?? []; + SourceMappings = sourceMappings.NullToEmpty(); + LinePragmas = linePragmas.NullToEmpty(); } public static RazorCSharpDocument Create( @@ -56,12 +56,12 @@ public static RazorCSharpDocument Create( RazorCodeGenerationOptions options, IEnumerable diagnostics, ImmutableArray sourceMappings, - IEnumerable linePragmas) + ImmutableArray linePragmas) { ArgHelper.ThrowIfNull(generatedCode); ArgHelper.ThrowIfNull(options); ArgHelper.ThrowIfNull(diagnostics); - return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings, linePragmas.ToArray()); + return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings, linePragmas); } } From 89204d4acfe3c41d503c6a234916e8500f3e7c14 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 14:16:14 -0700 Subject: [PATCH 08/24] Clean up callers of RazorCSharpDocument.Create(...) --- .../test/RazorCodeDocumentExtensionsTest.cs | 4 +- .../RazorDiagnosticsBenchmark.cs | 6 +- .../UnsupportedCSharpLoweringPhase.cs | 3 +- .../DefaultCSharpCodeActionProviderTest.cs | 6 +- ...TypeAccessibilityCodeActionProviderTest.cs | 6 +- ...nentAccessibilityCodeActionProviderTest.cs | 6 +- .../RazorDiagnosticsPublisherTest.cs | 6 +- .../DocumentOnTypeFormattingEndpointTest.cs | 15 +- .../FormattingLanguageServerTestBase.cs | 5 +- .../Mapping/RazorLanguageQueryEndpointTest.cs | 25 +- .../RazorMapToDocumentRangesEndpointTest.cs | 54 +-- .../RazorDocumentMappingServiceTest.cs | 357 ++++++++---------- 12 files changed, 208 insertions(+), 285 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs index 8c73fda2e9e..51eb9b03956 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs @@ -113,7 +113,7 @@ public void GetCSharpDocument_ReturnsCSharpDocument() // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), Array.Empty()); + var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); codeDocument.Items[typeof(RazorCSharpDocument)] = expected; // Act @@ -129,7 +129,7 @@ public void SetCSharpDocument_SetsCSharpDocument() // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), Array.Empty()); + var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); // Act codeDocument.SetCSharpDocument(expected); diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs index 9e50156d7f5..0c49b8c5865 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs @@ -10,7 +10,6 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics; using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; @@ -62,10 +61,9 @@ public void Setup() mockRazorCodeDocument.Object, GeneratedCode, RazorCodeGenerationOptions.CreateDesignTimeDefault(), - Array.Empty(), + diagnostics: [], SourceMappings, - new List() - ); + linePragmas: []); var itemCollection = new ItemCollection(); itemCollection[typeof(RazorCSharpDocument)] = mockRazorCSharpDocument; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs index 53905d716e8..c709d943666 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Linq; using Microsoft.AspNetCore.Razor.Language; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; @@ -19,7 +18,7 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) codeDocument, UnsupportedDisclaimer, documentNode.Options, - Enumerable.Empty()); + diagnostics: []); codeDocument.SetCSharpDocument(cSharpDocument); codeDocument.SetUnsupported(); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs index 335e5df5f48..fb1bd67fc0b 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs @@ -326,11 +326,11 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( var projectEngine = RazorProjectEngine.Create(builder => builder.AddTagHelpers(tagHelpers)); var codeDocument = projectEngine.ProcessDesignTime(sourceDocument, FileKinds.Component, importSources: default, tagHelpers); - var cSharpDocument = codeDocument.GetCSharpDocument(); + var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var cSharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, cSharpDocument.GeneratedCode, cSharpDocument.Options, new[] { diagnostic }); - codeDocument.SetCSharpDocument(cSharpDocumentWithDiagnostic); + var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => document.GetGeneratedOutputAsync() == Task.FromResult(codeDocument) && diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs index 7c3c0afff5d..5b48f7c4293 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs @@ -457,11 +457,11 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( }); var codeDocument = projectEngine.ProcessDesignTime(sourceDocument, FileKinds.Component, importSources: default, tagHelpers); - var cSharpDocument = codeDocument.GetCSharpDocument(); + var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var cSharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, cSharpDocument.GeneratedCode, cSharpDocument.Options, [diagnostic]); - codeDocument.SetCSharpDocument(cSharpDocumentWithDiagnostic); + var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => document.GetGeneratedOutputAsync() == Task.FromResult(codeDocument) && diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index 7d4ca269ff6..e9e6fd617ac 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -457,11 +457,11 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var projectEngine = RazorProjectEngine.Create(builder => builder.AddTagHelpers(tagHelpers)); var codeDocument = projectEngine.ProcessDesignTime(sourceDocument, FileKinds.Component, importSources: default, tagHelpers); - var cSharpDocument = codeDocument.GetCSharpDocument(); + var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var cSharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, cSharpDocument.GeneratedCode, cSharpDocument.Options, new[] { diagnostic }); - codeDocument.SetCSharpDocument(cSharpDocumentWithDiagnostic); + var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => document.GetGeneratedOutputAsync() == Task.FromResult(codeDocument) && diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs index 4cdbc79137d..31587d73146 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -523,10 +525,10 @@ public void ClearClosedDocuments_RestartsTimerIfDocumentsStillOpen() Assert.True(publisherAccessor.IsWaitingToClearClosedDocuments); } - private static RazorCodeDocument CreateCodeDocument(RazorDiagnostic[] diagnostics) + private static RazorCodeDocument CreateCodeDocument(IEnumerable diagnostics) { var codeDocument = TestRazorCodeDocument.Create("hello"); - var razorCSharpDocument = RazorCSharpDocument.Create(codeDocument, "hello", RazorCodeGenerationOptions.CreateDefault(), diagnostics); + var razorCSharpDocument = RazorCSharpDocument.Create(codeDocument, "hello", RazorCodeGenerationOptions.CreateDefault(), diagnostics.ToImmutableArray()); codeDocument.SetCSharpDocument(razorCSharpDocument); return codeDocument; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentOnTypeFormattingEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentOnTypeFormattingEndpointTest.cs index 17177a8e49c..086ac0c7c2a 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentOnTypeFormattingEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentOnTypeFormattingEndpointTest.cs @@ -47,8 +47,7 @@ public async Task Handle_OnTypeFormatting_DocumentNotFound_ReturnsNull() @{ if(true){} }"; - var sourceMappings = new List { new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0)) }; - var codeDocument = CreateCodeDocument(content, sourceMappings); + var codeDocument = CreateCodeDocument(content, sourceMappings: [new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0))]); var uri = new Uri("file://path/test.razor"); var documentContext = CreateDocumentContext(new Uri("file://path/testDifferentFile.razor"), codeDocument); @@ -82,8 +81,7 @@ public async Task Handle_OnTypeFormatting_RemapFailed_ReturnsNull() @{ if(true){} }"; - var sourceMappings = new List { }; - var codeDocument = CreateCodeDocument(content, sourceMappings); + var codeDocument = CreateCodeDocument(content, sourceMappings: []); var uri = new Uri("file://path/test.razor"); var documentContext = CreateDocumentContext(uri, codeDocument); @@ -117,8 +115,7 @@ public async Task Handle_OnTypeFormatting_HtmlLanguageKind_ReturnsNull() @{ if(true){} }"; - var sourceMappings = new List { new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0)) }; - var codeDocument = CreateCodeDocument(content, sourceMappings); + var codeDocument = CreateCodeDocument(content, sourceMappings: [new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0))]); var uri = new Uri("file://path/test.razor"); var documentContext = CreateDocumentContext(uri, codeDocument); @@ -153,8 +150,7 @@ public async Task Handle_OnTypeFormatting_RazorLanguageKind_ReturnsNull() @{ if(true){} }"; - var sourceMappings = new List { new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0)) }; - var codeDocument = CreateCodeDocument(content, sourceMappings); + var codeDocument = CreateCodeDocument(content, sourceMappings: [new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0))]); var uri = new Uri("file://path/test.razor"); var documentContext = CreateDocumentContext(uri, codeDocument); @@ -189,8 +185,7 @@ public async Task Handle_OnTypeFormatting_UnexpectedTriggerCharacter_ReturnsNull @{ if(true){} }"; - var sourceMappings = new List { new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0)) }; - var codeDocument = CreateCodeDocument(content, sourceMappings); + var codeDocument = CreateCodeDocument(content, [new SourceMapping(new SourceSpan(17, 0), new SourceSpan(17, 0))]); var uri = new Uri("file://path/test.razor"); var documentContextFactory = CreateDocumentContextFactory(uri, codeDocument); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs index 25a4ba44e63..7e924e88a2a 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.AspNetCore.Razor.Threading; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -20,13 +19,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; public abstract class FormattingLanguageServerTestBase(ITestOutputHelper testOutput) : LanguageServerTestBase(testOutput) { - internal static RazorCodeDocument CreateCodeDocument(string content, IReadOnlyList sourceMappings) + internal static RazorCodeDocument CreateCodeDocument(string content, ImmutableArray sourceMappings) { var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument, RazorParserOptions.CreateDefault()); var razorCSharpDocument = RazorCSharpDocument.Create( - codeDocument, content, RazorCodeGenerationOptions.CreateDefault(), Array.Empty(), sourceMappings.ToImmutableArray(), Array.Empty()); + codeDocument, content, RazorCodeGenerationOptions.CreateDefault(), diagnostics: [], sourceMappings, linePragmas: []); codeDocument.SetSyntaxTree(syntaxTree); codeDocument.SetCSharpDocument(razorCSharpDocument); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs index 4d52de66276..eb3985c14be 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs @@ -2,12 +2,9 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Protocol; @@ -90,9 +87,9 @@ public async Task Handle_ResolvesLanguageRequest_CSharp() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "@", - "/* CSharp */", - new[] { new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 12)) }); + razorSource: "@", + projectedCSharpSource: "/* CSharp */", + sourceMappings: [new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 12))]); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorLanguageQueryEndpoint(_documentMappingService, LoggerFactory); var request = new RazorLanguageQueryParams() @@ -120,9 +117,9 @@ public async Task Handle_Unsupported_ResolvesLanguageRequest_Html() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "@", - "/* CSharp */", - new[] { new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 12)) }); + razorSource: "@", + projectedCSharpSource: "/* CSharp */", + sourceMappings: [new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 12))]); codeDocument.SetUnsupported(); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorLanguageQueryEndpoint(_documentMappingService, LoggerFactory); @@ -145,16 +142,16 @@ public async Task Handle_Unsupported_ResolvesLanguageRequest_Html() Assert.Equal(1337, response.HostDocumentVersion); } - private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, IEnumerable sourceMappings) + private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, ImmutableArray sourceMappings) { - var codeDocument = CreateCodeDocument(razorSource, ImmutableArray.Empty); + var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); var csharpDocument = RazorCSharpDocument.Create( codeDocument, projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), - Enumerable.Empty(), - sourceMappings.ToImmutableArray(), - Enumerable.Empty()); + diagnostics: [], + sourceMappings, + linePragmas: []); codeDocument.SetCSharpDocument(csharpDocument); return codeDocument; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs index 271ebda9975..b9a3f275cc3 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs @@ -36,13 +36,9 @@ public async Task Handle_MapToDocumentRanges_CSharp() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "var __o = DateTime.Now", - [ - new SourceMapping( - new SourceSpan(4, 12), - new SourceSpan(10, 12)) - ]); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "var __o = DateTime.Now", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(10, 12))]); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorMapToDocumentRangesEndpoint(_documentMappingService); var request = new RazorMapToDocumentRangesParams() @@ -70,13 +66,9 @@ public async Task Handle_MapToDocumentRanges_CSharp_Unmapped() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "var __o = DateTime.Now", - [ - new SourceMapping( - new SourceSpan(4, 12), - new SourceSpan(10, 12)) - ]); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "var __o = DateTime.Now", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(10, 12))]); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorMapToDocumentRangesEndpoint(_documentMappingService); var request = new RazorMapToDocumentRangesParams() @@ -103,13 +95,9 @@ public async Task Handle_MapToDocumentRanges_CSharp_LeadingOverlapsUnmapped() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "var __o = DateTime.Now", - [ - new SourceMapping( - new SourceSpan(4, 12), - new SourceSpan(10, 12)) - ]); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "var __o = DateTime.Now", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(10, 12))]); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorMapToDocumentRangesEndpoint(_documentMappingService); var request = new RazorMapToDocumentRangesParams() @@ -136,13 +124,9 @@ public async Task Handle_MapToDocumentRanges_CSharp_TrailingOverlapsUnmapped() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "var __o = DateTime.Now", - [ - new SourceMapping( - new SourceSpan(4, 12), - new SourceSpan(10, 12)) - ]); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "var __o = DateTime.Now", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(10, 12))]); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorMapToDocumentRangesEndpoint(_documentMappingService); var request = new RazorMapToDocumentRangesParams() @@ -221,13 +205,9 @@ public async Task Handle_MapToDocumentRanges_Unsupported() // Arrange var documentPath = new Uri("C:/path/to/document.cshtml"); var codeDocument = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "var __o = DateTime.Now", - [ - new SourceMapping( - new SourceSpan(4, 12), - new SourceSpan(10, 12)) - ]); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "var __o = DateTime.Now", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(10, 12))]); codeDocument.SetUnsupported(); var documentContext = CreateDocumentContext(documentPath, codeDocument); var languageEndpoint = new RazorMapToDocumentRangesEndpoint(_documentMappingService); @@ -249,7 +229,7 @@ public async Task Handle_MapToDocumentRanges_Unsupported() Assert.Equal(1337, response.HostDocumentVersion); } - private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, IEnumerable sourceMappings) + private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, ImmutableArray sourceMappings) { var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); var csharpDocument = RazorCSharpDocument.Create( @@ -257,7 +237,7 @@ private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string r projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), diagnostics: [], - sourceMappings.ToImmutableArray(), + sourceMappings, linePragmas: []); codeDocument.SetCSharpDocument(csharpDocument); return codeDocument; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs index 8bd5c180295..533abcd0638 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; @@ -21,15 +19,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -public class RazorDocumentMappingServiceTest : ToolingTestBase +public class RazorDocumentMappingServiceTest(ITestOutputHelper testOutput) : ToolingTestBase(testOutput) { - private readonly IFilePathService _filePathService; - - public RazorDocumentMappingServiceTest(ITestOutputHelper testOutput) - : base(testOutput) - { - _filePathService = new LSPFilePathService(TestLanguageServerFeatureOptions.Instance); - } + private readonly IFilePathService _filePathService = new LSPFilePathService(TestLanguageServerFeatureOptions.Instance); [Fact] public void TryMapToHostDocumentRange_Strict_StartOnlyMaps_ReturnsFalse() @@ -37,9 +29,9 @@ public void TryMapToHostDocumentRange_Strict_StartOnlyMaps_ReturnsFalse() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 19)); // Act @@ -60,9 +52,9 @@ public void TryMapToHostDocumentRange_Strict_EndOnlyMaps_ReturnsFalse() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 12)); // Act @@ -83,9 +75,9 @@ public void TryMapToHostDocumentRange_Strict_StartAndEndMap_ReturnsTrue() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 6), new LinePosition(0, 18)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -107,9 +99,9 @@ public void TryMapToHostDocumentRange_Inclusive_DirectlyMaps_ReturnsTrue() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 6), new LinePosition(0, 18)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -131,9 +123,9 @@ public void TryMapToHostDocumentRange_Inclusive_StartSinglyIntersects_ReturnsTru // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 19)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -155,9 +147,9 @@ public void TryMapToHostDocumentRange_Inclusive_EndSinglyIntersects_ReturnsTrue( // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 10)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -179,13 +171,12 @@ public void TryMapToHostDocumentRange_Inclusive_StartDoublyIntersects_ReturnsFal // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] - { + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [ new SourceMapping(new SourceSpan(4, 8), new SourceSpan(6, 8)), // DateTime new SourceMapping(new SourceSpan(12, 4), new SourceSpan(14, 4)) // .Now - }); + ]); var projectedRange = new LinePositionSpan(new LinePosition(0, 14), new LinePosition(0, 19)); // Act @@ -206,13 +197,12 @@ public void TryMapToHostDocumentRange_Inclusive_EndDoublyIntersects_ReturnsFalse // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] - { + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [ new SourceMapping(new SourceSpan(4, 8), new SourceSpan(6, 8)), // DateTime new SourceMapping(new SourceSpan(12, 4), new SourceSpan(14, 4)) // .Now - }); + ]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 14)); // Act @@ -233,9 +223,9 @@ public void TryMapToHostDocumentRange_Inclusive_OverlapsSingleMapping_ReturnsTru // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 19)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -257,13 +247,12 @@ public void TryMapToHostDocumentRange_Inclusive_OverlapsTwoMappings_ReturnsFalse // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] - { + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [ new SourceMapping(new SourceSpan(4, 8), new SourceSpan(6, 8)), // DateTime new SourceMapping(new SourceSpan(12, 4), new SourceSpan(14, 4)) // .Now - }); + ]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 19)); // Act @@ -284,9 +273,9 @@ public void TryMapToHostDocumentRange_Inferred_DirectlyMaps_ReturnsTrue() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "

@DateTime.Now

", - "__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12)) }); + razorSource: "

@DateTime.Now

", + projectedCSharpSource: "__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(4, 12), new SourceSpan(6, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 6), new LinePosition(0, 18)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 4), new LinePosition(0, 16)); @@ -308,9 +297,9 @@ public void TryMapToHostDocumentRange_Inferred_BeginningOfDocAndProjection_Retur // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "@

@DateTime.Now

", - "(__builder) => { };__o = DateTime.Now;", - new[] { new SourceMapping(new SourceSpan(26, 12), new SourceSpan(25, 12)) }); + razorSource: "@

@DateTime.Now

", + projectedCSharpSource: "(__builder) => { };__o = DateTime.Now;", + sourceMappings: [new SourceMapping(new SourceSpan(26, 12), new SourceSpan(25, 12))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 19)); // Act @@ -326,17 +315,17 @@ public void TryMapToHostDocumentRange_Inferred_BeginningOfDocAndProjection_Retur } [Fact] - public void TryMapToHostDocumentRange_Inferred_InbetweenProjections_ReturnsTrue() + public void TryMapToHostDocumentRange_Inferred_InBetweenProjections_ReturnsTrue() { // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "@{ var abc = @ }", - " var abc = (__builder) => { } ", - new[] { + razorSource: "@{ var abc = @ }", + projectedCSharpSource: " var abc = (__builder) => { } ", + sourceMappings: [ new SourceMapping(new SourceSpan(2, 11), new SourceSpan(0, 11)), - new SourceMapping(new SourceSpan(35, 1), new SourceSpan(30, 1)), - }); + new SourceMapping(new SourceSpan(35, 1), new SourceSpan(30, 1)) + ]); var projectedRange = new LinePositionSpan(new LinePosition(0, 12), new LinePosition(0, 29)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 13), new LinePosition(0, 35)); @@ -353,14 +342,14 @@ public void TryMapToHostDocumentRange_Inferred_InbetweenProjections_ReturnsTrue( } [Fact] - public void TryMapToHostDocumentRange_Inferred_InbetweenProjectionAndEndOfDoc_ReturnsTrue() + public void TryMapToHostDocumentRange_Inferred_InBetweenProjectionAndEndOfDoc_ReturnsTrue() { // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "@{ var abc = @", - " var abc = (__builder) => { }", - new[] { new SourceMapping(new SourceSpan(2, 11), new SourceSpan(0, 11)), }); + razorSource: "@{ var abc = @", + projectedCSharpSource: " var abc = (__builder) => { }", + sourceMappings: [new SourceMapping(new SourceSpan(2, 11), new SourceSpan(0, 11))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 12), new LinePosition(0, 29)); var expectedOriginalRange = new LinePositionSpan(new LinePosition(0, 13), new LinePosition(0, 35)); @@ -382,9 +371,9 @@ public void TryMapToHostDocumentRange_Inferred_OutsideDoc_ReturnsFalse() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "@{ var abc = @", - " var abc = (__builder) => { }", - new[] { new SourceMapping(new SourceSpan(2, 11), new SourceSpan(0, 11)), }); + razorSource: "@{ var abc = @", + projectedCSharpSource: " var abc = (__builder) => { }", + sourceMappings: [new SourceMapping(new SourceSpan(2, 11), new SourceSpan(0, 11))]); var projectedRange = new LinePositionSpan(new LinePosition(2, 12), new LinePosition(2, 29)); // Act @@ -392,14 +381,14 @@ public void TryMapToHostDocumentRange_Inferred_OutsideDoc_ReturnsFalse() codeDoc.GetCSharpDocument(), projectedRange, MappingBehavior.Inferred, - out var originalRange); + out _); // Assert Assert.False(result); } [Fact] - public void TryMapToHostDocumentRange_Inferred_OutOfOrderMappings_DoesntThrow() + public void TryMapToHostDocumentRange_Inferred_OutOfOrderMappings_DoesNotThrow() { // Real world repo is something like: // @@ -418,9 +407,9 @@ public void TryMapToHostDocumentRange_Inferred_OutOfOrderMappings_DoesntThrow() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "@{ var abc = @", - " var abc = (__builder) => { }", - new SourceMapping[] { new(new(30, 1), new (2, 1)), new(new(28, 2), new(30, 2)), }); + razorSource: "@{ var abc = @", + projectedCSharpSource: " var abc = (__builder) => { }", + sourceMappings: [new(new(30, 1), new(2, 1)), new(new(28, 2), new(30, 2))]); var projectedRange = new LinePositionSpan(new LinePosition(0, 25), new LinePosition(0, 25)); // Act @@ -431,7 +420,7 @@ public void TryMapToHostDocumentRange_Inferred_OutOfOrderMappings_DoesntThrow() out var originalRange); // Assert - // We're really just happy this doesn't throw an exception. The behaviour is to map to the end of the file + // We're really just happy this doesn't throw an exception. The behavior is to map to the end of the file Assert.True(result); Assert.Equal(0, originalRange.Start.Line); Assert.Equal(31, originalRange.Start.Character); @@ -445,21 +434,19 @@ public void TryMapToGeneratedDocumentPosition_NotMatchingAnyMapping() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "test razor source", - "test C# source", - new[] { new SourceMapping(new SourceSpan(2, 100), new SourceSpan(0, 100)) }); + razorSource: "test razor source", + projectedCSharpSource: "test C# source", + sourceMappings: [new SourceMapping(new SourceSpan(2, 100), new SourceSpan(0, 100))]); // Act var result = service.TryMapToGeneratedDocumentPosition( codeDoc.GetCSharpDocument(), - 1, - out var projectedPosition, - out var projectedPositionIndex); + hostDocumentIndex: 1, + out _, + out _); // Assert Assert.False(result); - Assert.Equal(default, projectedPosition); - Assert.Equal(default, projectedPositionIndex); } [Fact] @@ -468,28 +455,24 @@ public void TryMapToGeneratedDocumentPosition_CSharp_OnLeadingEdge() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "Line 1\nLine 2 @{ var abc;\nvar def; }", - "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", + projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act - if (service.TryMapToGeneratedDocumentPosition( + var result = service.TryMapToGeneratedDocumentPosition( codeDoc.GetCSharpDocument(), - 16, + hostDocumentIndex: 16, out var projectedPosition, - out var projectedPositionIndex)) - { - Assert.Equal(2, projectedPosition.Line); - Assert.Equal(0, projectedPosition.Character); - Assert.Equal(11, projectedPositionIndex); - } - else - { - Assert.Fail($"{nameof(service.TryMapToGeneratedDocumentPosition)} should have returned true"); - } + out var projectedPositionIndex); + + Assert.True(result); + Assert.Equal(2, projectedPosition.Line); + Assert.Equal(0, projectedPosition.Character); + Assert.Equal(11, projectedPositionIndex); } [Fact] @@ -498,28 +481,24 @@ public void TryMapToGeneratedDocumentPosition_CSharp_InMiddle() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "Line 1\nLine 2 @{ var abc;\nvar def; }", - "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", + projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act & Assert - if (service.TryMapToGeneratedDocumentPosition( + var result = service.TryMapToGeneratedDocumentPosition( codeDoc.GetCSharpDocument(), - 28, + hostDocumentIndex: 28, out var projectedPosition, - out var projectedPositionIndex)) - { - Assert.Equal(3, projectedPosition.Line); - Assert.Equal(2, projectedPosition.Character); - Assert.Equal(23, projectedPositionIndex); - } - else - { - Assert.Fail("TryMapToGeneratedDocumentPosition should have been true"); - } + out var projectedPositionIndex); + + Assert.True(result); + Assert.Equal(3, projectedPosition.Line); + Assert.Equal(2, projectedPosition.Character); + Assert.Equal(23, projectedPositionIndex); } [Fact] @@ -528,28 +507,24 @@ public void TryMapToGeneratedDocumentPosition_CSharp_OnTrailingEdge() // Arrange var service = new LspDocumentMappingService(_filePathService, new TestDocumentContextFactory(), LoggerFactory); var codeDoc = CreateCodeDocumentWithCSharpProjection( - "Line 1\nLine 2 @{ var abc;\nvar def; }", - "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", + projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act & Assert - if (service.TryMapToGeneratedDocumentPosition( + var result = service.TryMapToGeneratedDocumentPosition( codeDoc.GetCSharpDocument(), - 35, + hostDocumentIndex: 35, out var projectedPosition, - out var projectedPositionIndex)) - { - Assert.Equal(3, projectedPosition.Line); - Assert.Equal(9, projectedPosition.Character); - Assert.Equal(30, projectedPositionIndex); - } - else - { - Assert.Fail("TryMapToGeneratedDocumentPosition should have returned true"); - } + out var projectedPositionIndex); + + Assert.True(result); + Assert.Equal(3, projectedPosition.Line); + Assert.Equal(9, projectedPosition.Character); + Assert.Equal(30, projectedPositionIndex); } [Fact] @@ -560,19 +535,17 @@ public void TryMapToHostDocumentPosition_NotMatchingAnyMapping() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "test razor source", projectedCSharpSource: "projectedCSharpSource: test C# source", - new[] { new SourceMapping(new SourceSpan(2, 100), new SourceSpan(2, 100)) }); + sourceMappings: [new SourceMapping(new SourceSpan(2, 100), new SourceSpan(2, 100))]); // Act var result = service.TryMapToHostDocumentPosition( codeDoc.GetCSharpDocument(), - 1, - out var hostDocumentPosition, - out var hostDocumentIndex); + generatedDocumentIndex: 1, + out _, + out _); // Assert Assert.False(result); - Assert.Equal(default, hostDocumentPosition); - Assert.Equal(default, hostDocumentIndex); } [Fact] @@ -583,26 +556,22 @@ public void TryMapToHostDocumentPosition_CSharp_OnLeadingEdge() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act & Assert - if (service.TryMapToHostDocumentPosition( + var result = service.TryMapToHostDocumentPosition( codeDoc.GetCSharpDocument(), - 11, // @{| + generatedDocumentIndex: 11, // @{| out var hostDocumentPosition, - out var hostDocumentIndex)) - { - Assert.Equal(1, hostDocumentPosition.Line); - Assert.Equal(9, hostDocumentPosition.Character); - Assert.Equal(16, hostDocumentIndex); - } - else - { - Assert.Fail($"{nameof(service.TryMapToHostDocumentPosition)} should have returned true"); - } + out var hostDocumentIndex); + + Assert.True(result); + Assert.Equal(1, hostDocumentPosition.Line); + Assert.Equal(9, hostDocumentPosition.Character); + Assert.Equal(16, hostDocumentIndex); } [Fact] @@ -613,26 +582,22 @@ public void TryMapToHostDocumentPosition_CSharp_InMiddle() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act & Assert - if (service.TryMapToHostDocumentPosition( + var result = service.TryMapToHostDocumentPosition( codeDoc.GetCSharpDocument(), - 21, // |var def + generatedDocumentIndex: 21, // |var def out var hostDocumentPosition, - out var hostDocumentIndex)) - { - Assert.Equal(2, hostDocumentPosition.Line); - Assert.Equal(0, hostDocumentPosition.Character); - Assert.Equal(26, hostDocumentIndex); - } - else - { - Assert.Fail($"{nameof(service.TryMapToHostDocumentPosition)} should have returned true"); - } + out var hostDocumentIndex); + + Assert.True(result); + Assert.Equal(2, hostDocumentPosition.Line); + Assert.Equal(0, hostDocumentPosition.Character); + Assert.Equal(26, hostDocumentIndex); } [Fact] @@ -643,26 +608,22 @@ public void TryMapToHostDocumentPosition_CSharp_OnTrailingEdge() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); // Act & Assert - if (service.TryMapToHostDocumentPosition( + var result = service.TryMapToHostDocumentPosition( codeDoc.GetCSharpDocument(), - 30, // def; |} + generatedDocumentIndex: 30, // def; |} out var hostDocumentPosition, - out var hostDocumentIndex)) - { - Assert.Equal(2, hostDocumentPosition.Line); - Assert.Equal(9, hostDocumentPosition.Character); - Assert.Equal(35, hostDocumentIndex); - } - else - { - Assert.Fail($"{nameof(service.TryMapToHostDocumentPosition)} should have returned true"); - } + out var hostDocumentIndex); + + Assert.True(result); + Assert.Equal(2, hostDocumentPosition.Line); + Assert.Equal(9, hostDocumentPosition.Character); + Assert.Equal(35, hostDocumentIndex); } [Fact] @@ -673,27 +634,23 @@ public void TryMapToGeneratedDocumentRange_CSharp() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 19), new SourceSpan(11, 19)) - }); + ]); var range = new LinePositionSpan(new LinePosition(1, 10), new LinePosition(1, 13)); // Act & Assert - if (service.TryMapToGeneratedDocumentRange( + var result = service.TryMapToGeneratedDocumentRange( codeDoc.GetCSharpDocument(), range, // |var| abc - out var projectedRange)) - { - Assert.Equal(2, projectedRange.Start.Line); - Assert.Equal(1, projectedRange.Start.Character); - Assert.Equal(2, projectedRange.End.Line); - Assert.Equal(4, projectedRange.End.Character); - } - else - { - Assert.Fail($"{nameof(service.TryMapToGeneratedDocumentRange)} should have returned true"); - } + out var projectedRange); + + Assert.True(result); + Assert.Equal(2, projectedRange.Start.Line); + Assert.Equal(1, projectedRange.Start.Character); + Assert.Equal(2, projectedRange.End.Line); + Assert.Equal(4, projectedRange.End.Character); } [Fact] @@ -704,20 +661,17 @@ public void TryMapToGeneratedDocumentRange_CSharp_MissingSourceMappings() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { - new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), - }); + sourceMappings: [new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1))]); var range = new LinePositionSpan(new LinePosition(1, 10), new LinePosition(1, 13)); // Act var result = service.TryMapToGeneratedDocumentRange( codeDoc.GetCSharpDocument(), range, // |var| abc - out var projectedRange); + out _); // Assert Assert.False(result); - Assert.Equal(default, projectedRange); } [Fact] @@ -728,22 +682,21 @@ public void TryMapToGeneratedDocumentRange_CSharp_End_LessThan_Start() var codeDoc = CreateCodeDocumentWithCSharpProjection( razorSource: "Line 1\nLine 2 @{ var abc;\nvar def; }", projectedCSharpSource: "\n// Prefix\n var abc;\nvar def; \n// Suffix", - new[] { + sourceMappings: [ new SourceMapping(new SourceSpan(0, 1), new SourceSpan(0, 1)), new SourceMapping(new SourceSpan(16, 3), new SourceSpan(11, 3)), new SourceMapping(new SourceSpan(19, 10), new SourceSpan(5, 10)) - }); + ]); var range = new LinePositionSpan(new LinePosition(1, 10), new LinePosition(1, 13)); // Act var result = service.TryMapToGeneratedDocumentRange( codeDoc.GetCSharpDocument(), range, // |var| abc - out var projectedRange); + out _); // Assert Assert.False(result); - Assert.Equal(default, projectedRange); } [Fact] @@ -1076,16 +1029,16 @@ private static RazorCodeDocument CreateCodeDocument(string text, IReadOnlyList sourceMappings) + private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, ImmutableArray sourceMappings) { - var codeDocument = CreateCodeDocument(razorSource, Array.Empty()); + var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); var csharpDocument = RazorCSharpDocument.Create( codeDocument, projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), - Enumerable.Empty(), + diagnostics: [], sourceMappings.ToImmutableArray(), - Enumerable.Empty()); + linePragmas: []); codeDocument.SetCSharpDocument(csharpDocument); return codeDocument; } From c755804389e0d364d0a446dddd5ef3faa8b07d89 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 14:20:46 -0700 Subject: [PATCH 09/24] Swap RazorCSharpDocument.Create methods for constructors --- .../test/RazorCodeDocumentExtensionsTest.cs | 4 +-- .../src/Language/RazorCSharpDocument.cs | 34 ++----------------- .../RazorDiagnosticsBenchmark.cs | 2 +- .../UnsupportedCSharpLoweringPhase.cs | 8 ++--- .../DefaultCSharpCodeActionProviderTest.cs | 2 +- ...TypeAccessibilityCodeActionProviderTest.cs | 2 +- ...nentAccessibilityCodeActionProviderTest.cs | 2 +- .../RazorDiagnosticsPublisherTest.cs | 2 +- .../FormattingLanguageServerTestBase.cs | 4 +-- .../Mapping/RazorLanguageQueryEndpointTest.cs | 2 +- .../RazorMapToDocumentRangesEndpointTest.cs | 3 +- .../RazorDocumentMappingServiceTest.cs | 4 +-- 12 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs index 51eb9b03956..c1fafa832a2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs @@ -113,7 +113,7 @@ public void GetCSharpDocument_ReturnsCSharpDocument() // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); + var expected = new RazorCSharpDocument(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); codeDocument.Items[typeof(RazorCSharpDocument)] = expected; // Act @@ -129,7 +129,7 @@ public void SetCSharpDocument_SetsCSharpDocument() // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var expected = RazorCSharpDocument.Create(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); + var expected = new RazorCSharpDocument(codeDocument, "", RazorCodeGenerationOptions.CreateDefault(), diagnostics: []); // Act codeDocument.SetCSharpDocument(expected); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs index 20baddcb80b..f31792488e2 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; namespace Microsoft.AspNetCore.Razor.Language; @@ -22,11 +21,12 @@ public RazorCSharpDocument( string generatedCode, RazorCodeGenerationOptions options, RazorDiagnostic[] diagnostics, - ImmutableArray sourceMappings, - ImmutableArray linePragmas) + ImmutableArray sourceMappings = default, + ImmutableArray linePragmas = default) { ArgHelper.ThrowIfNull(codeDocument); ArgHelper.ThrowIfNull(generatedCode); + ArgHelper.ThrowIfNull(options); CodeDocument = codeDocument; GeneratedCode = generatedCode; @@ -36,32 +36,4 @@ public RazorCSharpDocument( SourceMappings = sourceMappings.NullToEmpty(); LinePragmas = linePragmas.NullToEmpty(); } - - public static RazorCSharpDocument Create( - RazorCodeDocument codeDocument, - string generatedCode, - RazorCodeGenerationOptions options, - IEnumerable diagnostics) - { - ArgHelper.ThrowIfNull(generatedCode); - ArgHelper.ThrowIfNull(options); - ArgHelper.ThrowIfNull(diagnostics); - - return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings: [], linePragmas: []); - } - - public static RazorCSharpDocument Create( - RazorCodeDocument codeDocument, - string generatedCode, - RazorCodeGenerationOptions options, - IEnumerable diagnostics, - ImmutableArray sourceMappings, - ImmutableArray linePragmas) - { - ArgHelper.ThrowIfNull(generatedCode); - ArgHelper.ThrowIfNull(options); - ArgHelper.ThrowIfNull(diagnostics); - - return new(codeDocument, generatedCode, options, diagnostics.ToArray(), sourceMappings, linePragmas); - } } diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs index 0c49b8c5865..b07988f16c3 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs @@ -57,7 +57,7 @@ public void Setup() var stringSourceDocument = RazorSourceDocument.Create(GetFileContents(), UTF8Encoding.UTF8, RazorSourceDocumentProperties.Default); var mockRazorCodeDocument = new Mock(MockBehavior.Strict); - var mockRazorCSharpDocument = RazorCSharpDocument.Create( + var mockRazorCSharpDocument = new RazorCSharpDocument( mockRazorCodeDocument.Object, GeneratedCode, RazorCodeGenerationOptions.CreateDesignTimeDefault(), diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs index c709d943666..606a35ef44b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/UnsupportedCSharpLoweringPhase.cs @@ -14,12 +14,8 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument) var documentNode = codeDocument.GetDocumentIntermediateNode(); ThrowForMissingDocumentDependency(documentNode); - var cSharpDocument = RazorCSharpDocument.Create( - codeDocument, - UnsupportedDisclaimer, - documentNode.Options, - diagnostics: []); - codeDocument.SetCSharpDocument(cSharpDocument); + var csharpDocument = new RazorCSharpDocument(codeDocument, UnsupportedDisclaimer, documentNode.Options, diagnostics: []); + codeDocument.SetCSharpDocument(csharpDocument); codeDocument.SetUnsupported(); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs index fb1bd67fc0b..bd93514e88f 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/DefaultCSharpCodeActionProviderTest.cs @@ -329,7 +329,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + var csharpDocumentWithDiagnostic = new RazorCSharpDocument(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs index 5b48f7c4293..610e0462269 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs @@ -460,7 +460,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + var csharpDocumentWithDiagnostic = new RazorCSharpDocument(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index e9e6fd617ac..56874c402da 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -460,7 +460,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var csharpDocument = codeDocument.GetCSharpDocument(); var diagnosticDescriptor = new RazorDiagnosticDescriptor("RZ10012", "diagnostic", RazorDiagnosticSeverity.Error); var diagnostic = RazorDiagnostic.Create(diagnosticDescriptor, componentSourceSpan); - var csharpDocumentWithDiagnostic = RazorCSharpDocument.Create(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); + var csharpDocumentWithDiagnostic = new RazorCSharpDocument(codeDocument, csharpDocument.GeneratedCode, csharpDocument.Options, [diagnostic]); codeDocument.SetCSharpDocument(csharpDocumentWithDiagnostic); var documentSnapshot = Mock.Of(document => diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs index 31587d73146..58e03d3d2bc 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs @@ -528,7 +528,7 @@ public void ClearClosedDocuments_RestartsTimerIfDocumentsStillOpen() private static RazorCodeDocument CreateCodeDocument(IEnumerable diagnostics) { var codeDocument = TestRazorCodeDocument.Create("hello"); - var razorCSharpDocument = RazorCSharpDocument.Create(codeDocument, "hello", RazorCodeGenerationOptions.CreateDefault(), diagnostics.ToImmutableArray()); + var razorCSharpDocument = new RazorCSharpDocument(codeDocument, "hello", RazorCodeGenerationOptions.CreateDefault(), diagnostics.ToImmutableArray()); codeDocument.SetCSharpDocument(razorCSharpDocument); return codeDocument; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs index 7e924e88a2a..70ad34fc7a9 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -24,7 +22,7 @@ internal static RazorCodeDocument CreateCodeDocument(string content, ImmutableAr var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument, RazorParserOptions.CreateDefault()); - var razorCSharpDocument = RazorCSharpDocument.Create( + var razorCSharpDocument = new RazorCSharpDocument( codeDocument, content, RazorCodeGenerationOptions.CreateDefault(), diagnostics: [], sourceMappings, linePragmas: []); codeDocument.SetSyntaxTree(syntaxTree); codeDocument.SetCSharpDocument(razorCSharpDocument); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs index eb3985c14be..406250585c4 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs @@ -145,7 +145,7 @@ public async Task Handle_Unsupported_ResolvesLanguageRequest_Html() private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, ImmutableArray sourceMappings) { var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); - var csharpDocument = RazorCSharpDocument.Create( + var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs index b9a3f275cc3..bda6189e8e6 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; @@ -232,7 +231,7 @@ public async Task Handle_MapToDocumentRanges_Unsupported() private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string razorSource, string projectedCSharpSource, ImmutableArray sourceMappings) { var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); - var csharpDocument = RazorCSharpDocument.Create( + var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs index 533abcd0638..ec594997150 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs @@ -1032,12 +1032,12 @@ private static RazorCodeDocument CreateCodeDocument(string text, IReadOnlyList sourceMappings) { var codeDocument = CreateCodeDocument(razorSource, tagHelpers: []); - var csharpDocument = RazorCSharpDocument.Create( + var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, RazorCodeGenerationOptions.CreateDefault(), diagnostics: [], - sourceMappings.ToImmutableArray(), + sourceMappings, linePragmas: []); codeDocument.SetCSharpDocument(csharpDocument); return codeDocument; From ff63a4e603f8692cda7d3a6174d72d24da15f8a6 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 15:31:44 -0700 Subject: [PATCH 10/24] Use pooled ImmutableArray builder for CodeRenderingContext diagnostics --- .../CodeGeneration/CodeRenderingContext.cs | 30 ++++++++++--------- .../CodeGeneration/DefaultDocumentWriter.cs | 8 ++--- .../src/Language/RazorCSharpDocument.cs | 4 +-- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index b3517e1055f..4741616f544 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -21,13 +21,13 @@ public sealed class CodeRenderingContext : IDisposable public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } - public RazorDiagnosticCollection Diagnostics { get; } public ItemCollection Items { get; } private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; private readonly PooledObject> _pooledAncestors; + private readonly PooledObject.Builder> _pooledDiagnostics; private readonly PooledObject> _pooledScopeStack; private readonly PooledObject.Builder> _pooledSourceMappings; private readonly PooledObject.Builder> _pooledLinePragmas; @@ -48,15 +48,14 @@ public CodeRenderingContext( Options = options; _pooledAncestors = StackPool.GetPooledObject(); - Diagnostics = []; + _pooledDiagnostics = ArrayBuilderPool.GetPooledObject(); Items = []; _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); _pooledLinePragmas = ArrayBuilderPool.GetPooledObject(); - var diagnostics = _documentNode.GetAllDiagnostics(); - for (var i = 0; i < diagnostics.Count; i++) + foreach (var diagnostic in _documentNode.GetAllDiagnostics().AsEnumerable()) { - Diagnostics.Add(diagnostics[i]); + Diagnostics.Add(diagnostic); } // Set new line character to a specific string regardless of platform, for testing purposes. @@ -70,6 +69,16 @@ public CodeRenderingContext( scopeStack.Push(new(nodeWriter)); } + public void Dispose() + { + _pooledAncestors.Dispose(); + _pooledDiagnostics.Dispose(); + _pooledLinePragmas.Dispose(); + _pooledScopeStack.Dispose(); + _pooledSourceMappings.Dispose(); + CodeWriter.Dispose(); + } + // This will be initialized by the document writer when the context is 'live'. public IntermediateNodeVisitor Visitor { get; set; } @@ -77,6 +86,8 @@ public CodeRenderingContext( internal Stack AncestorsInternal => _pooledAncestors.Object; + public ImmutableArray.Builder Diagnostics => _pooledDiagnostics.Object; + public string DocumentKind => _documentNode.DocumentKind; public ImmutableArray.Builder SourceMappings => _pooledSourceMappings.Object; @@ -175,13 +186,4 @@ public void AddLinePragma(LinePragma linePragma) { LinePragmas.Add(linePragma); } - - public void Dispose() - { - _pooledAncestors.Dispose(); - _pooledLinePragmas.Dispose(); - _pooledScopeStack.Dispose(); - _pooledSourceMappings.Dispose(); - CodeWriter.Dispose(); - } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 92c8a3ca94d..e85abc5cdec 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Collections.Immutable; using System.Linq; using System.Security.Cryptography; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -42,14 +43,13 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument context.Visitor.VisitDocument(documentNode); - var cSharp = context.CodeWriter.GenerateCode(); + var csharp = context.CodeWriter.GenerateCode(); - var allOrderedDiagnostics = context.Diagnostics.OrderBy(diagnostic => diagnostic.Span.AbsoluteIndex); return new RazorCSharpDocument( codeDocument, - cSharp, + csharp, _options, - allOrderedDiagnostics.ToArray(), + context.Diagnostics.ToImmutableOrderedBy(static d => d.Span.AbsoluteIndex), context.SourceMappings.DrainToImmutable(), context.LinePragmas.DrainToImmutable()); } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs index f31792488e2..c80197d42fc 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs @@ -20,7 +20,7 @@ public RazorCSharpDocument( RazorCodeDocument codeDocument, string generatedCode, RazorCodeGenerationOptions options, - RazorDiagnostic[] diagnostics, + ImmutableArray diagnostics, ImmutableArray sourceMappings = default, ImmutableArray linePragmas = default) { @@ -32,7 +32,7 @@ public RazorCSharpDocument( GeneratedCode = generatedCode; Options = options; - Diagnostics = diagnostics ?? []; + Diagnostics = diagnostics.NullToEmpty(); SourceMappings = sourceMappings.NullToEmpty(); LinePragmas = linePragmas.NullToEmpty(); } From 90f90ef875f705837c23484de64f372a717ce537 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 15:38:38 -0700 Subject: [PATCH 11/24] Switch RazorCSharpDocument.Diagnostics to an ImmutableArray --- .../CodeGenerationIntegrationTest.cs | 2 +- .../CodeGenerationIntegrationTest.cs | 4 ++-- .../CodeGenerationIntegrationTest.cs | 4 ++-- .../src/Language/RazorCSharpDocument.cs | 5 ++--- .../SourceGenerators/RazorSourceGenerator.cs | 5 ++--- .../CodeGenerationBenchmark.cs | 4 ++-- .../RazorWrapperFactory.cs | 20 ------------------- .../DocumentPullDiagnosticsEndpoint.cs | 2 +- 8 files changed, 12 insertions(+), 34 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs index 045fc2ee3af..0e1e4627bb0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -66,7 +66,7 @@ public class MyService AssertSourceMappingsMatchBaseline(compiled.CodeDocument); // We expect this test to generate a bunch of errors. - Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Count > 0); + Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics); } [Fact] diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs index bc3aa19c9c1..4f0c1e71fab 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -85,7 +85,7 @@ public class MyService AssertCSharpDocumentMatchesBaseline(compiled.CodeDocument.GetCSharpDocument()); // We expect this test to generate a bunch of errors. - Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Count > 0); + Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics); } [Fact] @@ -536,7 +536,7 @@ public class MyService AssertSourceMappingsMatchBaseline(compiled.CodeDocument); // We expect this test to generate a bunch of errors. - Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Count > 0); + Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics); } [Fact] diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/IntegrationTests/CodeGenerationIntegrationTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/IntegrationTests/CodeGenerationIntegrationTest.cs index de4dd521d8e..36a5ecf0f63 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -92,7 +92,7 @@ public class MyService AssertLinePragmas(compiled.CodeDocument, designTime: false); // We expect this test to generate a bunch of errors. - Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Count > 0); + Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics); } [Fact] @@ -949,7 +949,7 @@ public class MyService AssertSourceMappingsMatchBaseline(compiled.CodeDocument); // We expect this test to generate a bunch of errors. - Assert.True(compiled.CodeDocument.GetCSharpDocument().Diagnostics.Count > 0); + Assert.NotEmpty(compiled.CodeDocument.GetCSharpDocument().Diagnostics); } [Fact] diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs index c80197d42fc..2a00090ac94 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCSharpDocument.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; @@ -12,9 +11,9 @@ public sealed class RazorCSharpDocument : IRazorGeneratedDocument public RazorCodeDocument CodeDocument { get; } public string GeneratedCode { get; } public RazorCodeGenerationOptions Options { get; } - public IReadOnlyList Diagnostics { get; } + public ImmutableArray Diagnostics { get; } public ImmutableArray SourceMappings { get; } - internal ImmutableArray LinePragmas { get; } + public ImmutableArray LinePragmas { get; } public RazorCSharpDocument( RazorCodeDocument codeDocument, diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs index f7bdfb0310e..0fe65e3eb60 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs @@ -313,7 +313,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) }) .WithLambdaComparer(static (a, b) => { - if (a.csharpDocument.Diagnostics.Count > 0 || b.csharpDocument.Diagnostics.Count > 0) + if (a.csharpDocument.Diagnostics.Length > 0 || b.csharpDocument.Diagnostics.Length > 0) { // if there are any diagnostics, treat the documents as unequal and force RegisterSourceOutput to be called uncached. return false; @@ -339,9 +339,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var hintName = GetIdentifierFromPath(filePath) + ".g.cs"; RazorSourceGeneratorEventSource.Log.AddSyntaxTrees(hintName); - for (var i = 0; i < csharpDocument.Diagnostics.Count; i++) + foreach (var razorDiagnostic in csharpDocument.Diagnostics) { - var razorDiagnostic = csharpDocument.Diagnostics[i]; var csharpDiagnostic = razorDiagnostic.AsDiagnostic(); context.ReportDiagnostic(csharpDiagnostic); } diff --git a/src/Compiler/perf/Microbenchmarks/CodeGenerationBenchmark.cs b/src/Compiler/perf/Microbenchmarks/CodeGenerationBenchmark.cs index 42bf5b84580..90a85e481e8 100644 --- a/src/Compiler/perf/Microbenchmarks/CodeGenerationBenchmark.cs +++ b/src/Compiler/perf/Microbenchmarks/CodeGenerationBenchmark.cs @@ -39,7 +39,7 @@ public void CodeGeneration_DesignTime_LargeStaticFile() var codeDocument = ProjectEngine.ProcessDesignTime(MSN); var generated = codeDocument.GetCSharpDocument(); - if (generated.Diagnostics.Count != 0) + if (generated.Diagnostics.Length > 0) { throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics)); } @@ -51,7 +51,7 @@ public void CodeGeneration_Runtime_LargeStaticFile() var codeDocument = ProjectEngine.Process(MSN); var generated = codeDocument.GetCSharpDocument(); - if (generated.Diagnostics.Count != 0) + if (generated.Diagnostics.Length > 0) { throw new Exception("Error!" + Environment.NewLine + string.Join(Environment.NewLine, generated.Diagnostics)); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.LegacyEditor/RazorWrapperFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.LegacyEditor/RazorWrapperFactory.cs index 216ffd6c9ca..e2014f4b761 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.LegacyEditor/RazorWrapperFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.LegacyEditor/RazorWrapperFactory.cs @@ -58,26 +58,6 @@ private static ImmutableArray WrapAll(ImmutableArray WrapAll(IReadOnlyList list, Func createWrapper) - where TInner : class - where TResult : class - { - var count = list.Count; - if (count == 0) - { - return ImmutableArray.Empty; - } - - using var builder = new PooledArrayBuilder(capacity: count); - - for (var i = 0; i < count; i++) - { - builder.Add(createWrapper(list[i])); - } - - return builder.DrainToImmutable(); - } - private static ImmutableArray WrapAll(IEnumerable items, Func createWrapper) where TInner : class where TResult : class diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/DocumentPullDiagnosticsEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/DocumentPullDiagnosticsEndpoint.cs index 68d893f9b24..5550bd39c40 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/DocumentPullDiagnosticsEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/DocumentPullDiagnosticsEndpoint.cs @@ -128,7 +128,7 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSInternalDocumentDiagno var csharpDocument = codeDocument.GetCSharpDocument(); var diagnostics = csharpDocument.Diagnostics; - if (diagnostics.Count == 0) + if (diagnostics.Length == 0) { return null; } From 5072db43b563009c0192ed3eddce2aed11d6a955 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 16:00:20 -0700 Subject: [PATCH 12/24] Clean up pooled objects in CodeRenderingContext --- .../DesignTimeNodeWriterTest.cs | 6 +- .../DefaultTagHelperTargetExtensionTest.cs | 8 +- ...reallocatedAttributeTargetExtensionTest.cs | 2 +- .../CodeGeneration/CodeRenderingContext.cs | 108 ++++++++++-------- .../CodeGeneration/DefaultDocumentWriter.cs | 6 +- .../Components/ComponentNodeWriter.cs | 2 +- .../DefaultTagHelperTargetExtension.cs | 4 +- .../Intermediate/ExtensionIntermediateNode.cs | 2 +- 8 files changed, 76 insertions(+), 62 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs index cb41431080b..d34c08ea4b9 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DesignTimeNodeWriterTest.cs @@ -58,7 +58,7 @@ public void WriteUsingDirective_WithSource_WritesContentWithLinePragmaAndMapping writer.WriteUsingDirective(context, node); // Assert - var mapping = Assert.Single(context.SourceMappings); + var mapping = Assert.Single(context.GetSourceMappings()); Assert.Equal(expectedSourceMapping, mapping); var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @@ -94,7 +94,7 @@ public void WriteUsingDirective_WithSourceAndLineDirectives_WritesContentWithLin writer.WriteUsingDirective(context, node); // Assert - var mapping = Assert.Single(context.SourceMappings); + var mapping = Assert.Single(context.GetSourceMappings()); Assert.Equal(expectedSourceMapping, mapping); var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @@ -587,7 +587,7 @@ public void LinePragma_Enhanced_Is_Adjusted_On_Windows(string fileName, string e csharp, ignoreLineEndingDifferences: true); - Assert.Single(context.SourceMappings); + Assert.Single(context.GetSourceMappings()); } diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs index 937e8ccbfbc..b7095e5c7dc 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/DefaultTagHelperTargetExtensionTest.cs @@ -370,7 +370,7 @@ public void RenderTagHelperAttributeInline_NonString_StatementInAttribute_Errors extension.RenderTagHelperAttributeInline(context, node, new CSharpCodeIntermediateNode(), expectedLocation); // Assert - var diagnostic = Assert.Single(context.Diagnostics); + var diagnostic = Assert.Single(context.GetDiagnostics()); Assert.Equal(expectedDiagnostic, diagnostic); } @@ -392,7 +392,7 @@ public void RenderTagHelperAttributeInline_NonStringIndexerMatch_TemplateInAttri extension.RenderTagHelperAttributeInline(context, node, new TemplateIntermediateNode(), expectedLocation); // Assert - var diagnostic = Assert.Single(context.Diagnostics); + var diagnostic = Assert.Single(context.GetDiagnostics()); Assert.Equal(expectedDiagnostic, diagnostic); } @@ -416,7 +416,7 @@ public void RenderTagHelperAttributeInline_NonString_TemplateInAttribute_Errors( extension.RenderTagHelperAttributeInline(context, node, new TemplateIntermediateNode(), expectedLocation); // Assert - var diagnostic = Assert.Single(context.Diagnostics); + var diagnostic = Assert.Single(context.GetDiagnostics()); Assert.Equal(expectedDiagnostic, diagnostic); } @@ -1148,7 +1148,7 @@ public void GetDeterministicId_IsDeterministic() private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node) { - context.AncestorsInternal.Push(node); + context.PushAncestor(node); } private static TagHelperDescriptor CreateTagHelperDescriptor( diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs index f0ca482b667..6981ece7703 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Extensions/PreallocatedAttributeTargetExtensionTest.cs @@ -273,6 +273,6 @@ public void WriteSetPreallocatedTagHelperProperty_IndexerAttribute_MultipleValue private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node) { - context.AncestorsInternal.Push(node); + context.PushAncestor(node); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 4741616f544..36e78e38a95 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -26,11 +26,15 @@ public sealed class CodeRenderingContext : IDisposable private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; - private readonly PooledObject> _pooledAncestors; - private readonly PooledObject.Builder> _pooledDiagnostics; - private readonly PooledObject> _pooledScopeStack; - private readonly PooledObject.Builder> _pooledSourceMappings; - private readonly PooledObject.Builder> _pooledLinePragmas; + private readonly Stack _ancestorStack; + private readonly Stack _scopeStack; + + private readonly ImmutableArray.Builder _diagnostics; + private readonly ImmutableArray.Builder _sourceMappings; + private readonly ImmutableArray.Builder _linePragmas; + + public string DocumentKind => _documentNode.DocumentKind; + public RazorSourceDocument SourceDocument => _codeDocument.Source; public CodeRenderingContext( IntermediateNodeWriter nodeWriter, @@ -47,61 +51,56 @@ public CodeRenderingContext( _documentNode = documentNode; Options = options; - _pooledAncestors = StackPool.GetPooledObject(); - _pooledDiagnostics = ArrayBuilderPool.GetPooledObject(); - Items = []; - _pooledSourceMappings = ArrayBuilderPool.GetPooledObject(); - _pooledLinePragmas = ArrayBuilderPool.GetPooledObject(); + _ancestorStack = StackPool.Default.Get(); + _scopeStack = StackPool.Default.Get(); + _scopeStack.Push(new(nodeWriter)); + + _diagnostics = ArrayBuilderPool.Default.Get(); foreach (var diagnostic in _documentNode.GetAllDiagnostics().AsEnumerable()) { - Diagnostics.Add(diagnostic); + _diagnostics.Add(diagnostic); } + _linePragmas = ArrayBuilderPool.Default.Get(); + _sourceMappings = ArrayBuilderPool.Default.Get(); + + Items = []; + // Set new line character to a specific string regardless of platform, for testing purposes. var newLineString = codeDocument.Items[NewLineString] as string ?? Environment.NewLine; CodeWriter = new CodeWriter(newLineString, options); Items[NewLineString] = codeDocument.Items[NewLineString]; Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; - - _pooledScopeStack = StackPool.GetPooledObject(out var scopeStack); - scopeStack.Push(new(nodeWriter)); } public void Dispose() { - _pooledAncestors.Dispose(); - _pooledDiagnostics.Dispose(); - _pooledLinePragmas.Dispose(); - _pooledScopeStack.Dispose(); - _pooledSourceMappings.Dispose(); + StackPool.Default.Return(_ancestorStack); + StackPool.Default.Return(_scopeStack); + + ArrayBuilderPool.Default.Return(_diagnostics); + ArrayBuilderPool.Default.Return(_linePragmas); + ArrayBuilderPool.Default.Return(_sourceMappings); + CodeWriter.Dispose(); } // This will be initialized by the document writer when the context is 'live'. public IntermediateNodeVisitor Visitor { get; set; } - public IEnumerable Ancestors => _pooledAncestors.Object; - - internal Stack AncestorsInternal => _pooledAncestors.Object; - - public ImmutableArray.Builder Diagnostics => _pooledDiagnostics.Object; + public IntermediateNodeWriter NodeWriter => _scopeStack.Peek().Writer; - public string DocumentKind => _documentNode.DocumentKind; - - public ImmutableArray.Builder SourceMappings => _pooledSourceMappings.Object; - - internal ImmutableArray.Builder LinePragmas => _pooledLinePragmas.Object; - - public IntermediateNodeWriter NodeWriter => Current.Writer; + public IntermediateNode Parent => _ancestorStack.Count == 0 ? null : _ancestorStack.Peek(); - public IntermediateNode Parent => AncestorsInternal.Count == 0 ? null : AncestorsInternal.Peek(); - - public RazorSourceDocument SourceDocument => _codeDocument.Source; + public void AddDiagnostic(RazorDiagnostic diagnostic) + { + _diagnostics.Add(diagnostic); + } - private Stack ScopeStack => _pooledScopeStack.Object; - private ScopeInternal Current => ScopeStack.Peek(); + public ImmutableArray GetDiagnostics() + => _diagnostics.ToImmutableOrderedBy(static d => d.Span.AbsoluteIndex); public void AddSourceMappingFor(IntermediateNode node) { @@ -124,26 +123,33 @@ public void AddSourceMappingFor(SourceSpan source, int offset = 0) return; } - var currentLocation = CodeWriter.Location with { AbsoluteIndex = CodeWriter.Location.AbsoluteIndex + offset, CharacterIndex = CodeWriter.Location.CharacterIndex + offset }; + var currentLocation = CodeWriter.Location with + { + AbsoluteIndex = CodeWriter.Location.AbsoluteIndex + offset, + CharacterIndex = CodeWriter.Location.CharacterIndex + offset + }; var generatedLocation = new SourceSpan(currentLocation, source.Length); var sourceMapping = new SourceMapping(source, generatedLocation); - SourceMappings.Add(sourceMapping); + _sourceMappings.Add(sourceMapping); } + public ImmutableArray GetSourceMappings() + => _sourceMappings.DrainToImmutable(); + public void RenderChildren(IntermediateNode node) { ArgHelper.ThrowIfNull(node); - AncestorsInternal.Push(node); + _ancestorStack.Push(node); for (var i = 0; i < node.Children.Count; i++) { Visitor.Visit(node.Children[i]); } - AncestorsInternal.Pop(); + _ancestorStack.Pop(); } public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) @@ -151,16 +157,16 @@ public void RenderChildren(IntermediateNode node, IntermediateNodeWriter writer) ArgHelper.ThrowIfNull(node); ArgHelper.ThrowIfNull(writer); - ScopeStack.Push(new ScopeInternal(writer)); - AncestorsInternal.Push(node); + _scopeStack.Push(new ScopeInternal(writer)); + _ancestorStack.Push(node); for (var i = 0; i < node.Children.Count; i++) { Visitor.Visit(node.Children[i]); } - AncestorsInternal.Pop(); - ScopeStack.Pop(); + _ancestorStack.Pop(); + _scopeStack.Pop(); } public void RenderNode(IntermediateNode node) @@ -175,15 +181,23 @@ public void RenderNode(IntermediateNode node, IntermediateNodeWriter writer) ArgHelper.ThrowIfNull(node); ArgHelper.ThrowIfNull(writer); - ScopeStack.Push(new ScopeInternal(writer)); + _scopeStack.Push(new ScopeInternal(writer)); Visitor.Visit(node); - ScopeStack.Pop(); + _scopeStack.Pop(); } public void AddLinePragma(LinePragma linePragma) { - LinePragmas.Add(linePragma); + _linePragmas.Add(linePragma); + } + + public ImmutableArray GetLinePragmas() + => _linePragmas.DrainToImmutable(); + + public void PushAncestor(IntermediateNode node) + { + _ancestorStack.Push(node); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index e85abc5cdec..cd9a8ab0833 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -49,9 +49,9 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument codeDocument, csharp, _options, - context.Diagnostics.ToImmutableOrderedBy(static d => d.Span.AbsoluteIndex), - context.SourceMappings.DrainToImmutable(), - context.LinePragmas.DrainToImmutable()); + context.GetDiagnostics(), + context.GetSourceMappings(), + context.GetLinePragmas()); } private class Visitor : IntermediateNodeVisitor diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs index 01fc235d3ed..9e924a6b382 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs @@ -58,7 +58,7 @@ public sealed override void WriteCSharpCodeAttributeValue(CodeRenderingContext c // // We provide an error for this case just to be friendly. var content = string.Join("", node.Children.OfType().Select(t => t.Content)); - context.Diagnostics.Add(ComponentDiagnosticFactory.Create_CodeBlockInAttribute(node.Source, content)); + context.AddDiagnostic(ComponentDiagnosticFactory.Create_CodeBlockInAttribute(node.Source, content)); return; } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs index 59c1dcc7619..6cac602ba7b 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs @@ -584,13 +584,13 @@ internal void RenderTagHelperAttributeInline( else if (node is CSharpCodeIntermediateNode) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_CodeBlocksNotSupportedInAttributes(span); - context.Diagnostics.Add(diagnostic); + context.AddDiagnostic(diagnostic); } else if (node is TemplateIntermediateNode) { var expectedTypeName = property.IsIndexerNameMatch ? property.BoundAttribute.IndexerTypeName : property.BoundAttribute.TypeName; var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InlineMarkupBlocksNotSupportedInAttributes(span, expectedTypeName); - context.Diagnostics.Add(diagnostic); + context.AddDiagnostic(diagnostic); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/ExtensionIntermediateNode.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/ExtensionIntermediateNode.cs index df5d210c550..7495f8e2995 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/ExtensionIntermediateNode.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/ExtensionIntermediateNode.cs @@ -34,7 +34,7 @@ protected void ReportMissingCodeTargetExtension(CodeRenderingContex } var documentKind = context.DocumentKind ?? string.Empty; - context.Diagnostics.Add( + context.AddDiagnostic( RazorDiagnosticFactory.CreateCodeTarget_UnsupportedExtension( documentKind, typeof(TDependency))); From 34507da4436794ac3a0f359252c5bb576a92abb8 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 9 Aug 2024 17:24:16 -0700 Subject: [PATCH 13/24] Avoid extra allocations in IntermediateNodeExtensions.GetAllDiagnostics --- ...entDuplicateAttributeDiagnosticPassTest.cs | 2 +- .../CodeGeneration/CodeRenderingContext.cs | 2 +- .../IntermediateNodeExtensions.cs | 44 ++++++++----------- .../PooledObjects/PooledHashSet`1.cs | 7 ++- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Components/ComponentDuplicateAttributeDiagnosticPassTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Components/ComponentDuplicateAttributeDiagnosticPassTest.cs index 34743b31272..c542ab950b2 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Components/ComponentDuplicateAttributeDiagnosticPassTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/Components/ComponentDuplicateAttributeDiagnosticPassTest.cs @@ -141,7 +141,7 @@ public void Execute_FindDuplicate_Multiple() var diagnostics = documentNode.GetAllDiagnostics(); var nodes = documentNode.FindDescendantNodes().Where(n => n.HasDiagnostics).ToArray(); - Assert.Equal(2, diagnostics.Count); + Assert.Equal(2, diagnostics.Length); Assert.Equal(2, nodes.Length); for (var i = 0; i < 2; i++) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 36e78e38a95..1016f7d2d05 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -57,7 +57,7 @@ public CodeRenderingContext( _diagnostics = ArrayBuilderPool.Default.Get(); - foreach (var diagnostic in _documentNode.GetAllDiagnostics().AsEnumerable()) + foreach (var diagnostic in _documentNode.GetAllDiagnostics()) { _diagnostics.Add(diagnostic); } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/IntermediateNodeExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/IntermediateNodeExtensions.cs index 72516dd6dcb..8cc6a373a85 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/IntermediateNodeExtensions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Intermediate/IntermediateNodeExtensions.cs @@ -3,17 +3,15 @@ #nullable disable -using System; using System.Collections.Generic; -using System.Linq; +using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language.Components; +using Microsoft.AspNetCore.Razor.PooledObjects; namespace Microsoft.AspNetCore.Razor.Language.Intermediate; public static class IntermediateNodeExtensions { - private static readonly IReadOnlyList EmptyDiagnostics = Array.Empty(); - public static bool IsImported(this IntermediateNode node) { return ReferenceEquals(node.Annotations[CommonAnnotations.Imported], CommonAnnotations.Imported); @@ -26,36 +24,32 @@ public static bool IsDesignTimePropertyAccessHelper(this IntermediateNode tagHel result; } - public static IReadOnlyList GetAllDiagnostics(this IntermediateNode node) + public static ImmutableArray GetAllDiagnostics(this IntermediateNode node) { - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - - HashSet diagnostics = null; - - AddAllDiagnostics(node); + ArgHelper.ThrowIfNull(node); - var allOrderedDiagnostics = diagnostics?.OrderBy(diagnostic => diagnostic.Span.AbsoluteIndex); + var diagnostics = new PooledHashSet(); + try + { + CollectDiagnostics(node, ref diagnostics); - return allOrderedDiagnostics?.ToList() ?? EmptyDiagnostics; + return diagnostics.OrderByAsArray(static d => d.Span.AbsoluteIndex); + } + finally + { + diagnostics.ClearAndFree(); + } - void AddAllDiagnostics(IntermediateNode n) + static void CollectDiagnostics(IntermediateNode node, ref PooledHashSet diagnostics) { - if (n.HasDiagnostics) + if (node.HasDiagnostics) { - if (diagnostics == null) - { - diagnostics = new HashSet(); - } - - diagnostics.UnionWith(n.Diagnostics); + diagnostics.UnionWith(node.Diagnostics); } - for (var i = 0; i < n.Children.Count; i++) + foreach (var childNode in node.Children) { - AddAllDiagnostics(n.Children[i]); + CollectDiagnostics(childNode, ref diagnostics); } } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledHashSet`1.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledHashSet`1.cs index c5ac61e1248..ff006967ea4 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledHashSet`1.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledHashSet`1.cs @@ -67,10 +67,13 @@ public readonly bool Contains(T item) => _set?.Contains(item) ?? false; public readonly T[] ToArray() - => _set?.ToArray() ?? Array.Empty(); + => _set?.ToArray() ?? []; public readonly ImmutableArray ToImmutableArray() - => _set?.ToImmutableArray() ?? ImmutableArray.Empty; + => _set?.ToImmutableArray() ?? []; + + public readonly ImmutableArray OrderByAsArray(Func keySelector) + => _set?.OrderByAsArray(keySelector) ?? []; public void UnionWith(IList? other) { From 7ac711be8cdbd155c8db0d4dd4a2f483684247d9 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Mon, 12 Aug 2024 15:52:51 -0700 Subject: [PATCH 14/24] Remove ItemCollection from CodeRenderingContext --- .../Language/CodeGeneration/CodeRenderingContext.cs | 13 +++++-------- .../Extensions/DefaultTagHelperTargetExtension.cs | 2 +- .../RazorToolingIntegrationTestBase.cs | 4 +--- .../CodeGeneration/TestCodeRenderingContext.cs | 8 ++++---- .../IntegrationTests/IntegrationTestBase.cs | 4 ++-- .../IntegrationTests/RazorIntegrationTestBase.cs | 5 +---- 6 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 1016f7d2d05..045be588210 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -15,13 +15,13 @@ public sealed class CodeRenderingContext : IDisposable { private readonly record struct ScopeInternal(IntermediateNodeWriter Writer); - internal static readonly object NewLineString = "NewLineString"; + internal static readonly object NewLineStringKey = "NewLineString"; - internal static readonly object SuppressUniqueIds = "SuppressUniqueIds"; + internal static readonly object SuppressUniqueIdsKey = "SuppressUniqueIds"; public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } - public ItemCollection Items { get; } + public string SuppressUniqueIds { get; } private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; @@ -65,14 +65,11 @@ public CodeRenderingContext( _linePragmas = ArrayBuilderPool.Default.Get(); _sourceMappings = ArrayBuilderPool.Default.Get(); - Items = []; - // Set new line character to a specific string regardless of platform, for testing purposes. - var newLineString = codeDocument.Items[NewLineString] as string ?? Environment.NewLine; + var newLineString = codeDocument.Items[NewLineStringKey] as string ?? Environment.NewLine; CodeWriter = new CodeWriter(newLineString, options); - Items[NewLineString] = codeDocument.Items[NewLineString]; - Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds] ?? options.SuppressUniqueIds; + SuppressUniqueIds = codeDocument.Items[SuppressUniqueIdsKey] as string ?? options.SuppressUniqueIds; } public void Dispose() diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs index 6cac602ba7b..9509bb6cd61 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs @@ -101,7 +101,7 @@ public void WriteTagHelperBody(CodeRenderingContext context, DefaultTagHelperBod // Assign a unique ID for this instance of the source HTML tag. This must be unique // per call site, e.g. if the tag is on the view twice, there should be two IDs. - var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds]; + var uniqueId = context.SuppressUniqueIds; if (uniqueId == null) { uniqueId = GetDeterministicId(context); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs index d473acb5ccc..f51221d8a55 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs @@ -441,9 +441,7 @@ public ForceLineEndingPhase(string lineEnding) 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; + codeDocument.Items[CodeRenderingContext.NewLineStringKey] = LineEnding; } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index f665107bcdd..9a524babdc5 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -26,12 +26,12 @@ public static CodeRenderingContext CreateDesignTime( var codeDocument = RazorCodeDocument.Create(source); if (newLineString != null) { - codeDocument.Items[CodeRenderingContext.NewLineString] = newLineString; + codeDocument.Items[CodeRenderingContext.NewLineStringKey] = newLineString; } if (suppressUniqueIds != null) { - codeDocument.Items[CodeRenderingContext.SuppressUniqueIds] = suppressUniqueIds; + codeDocument.Items[CodeRenderingContext.SuppressUniqueIdsKey] = suppressUniqueIds; } if (nodeWriter == null) @@ -62,12 +62,12 @@ public static CodeRenderingContext CreateRuntime( var codeDocument = RazorCodeDocument.Create(source); if (newLineString != null) { - codeDocument.Items[CodeRenderingContext.NewLineString] = newLineString; + codeDocument.Items[CodeRenderingContext.NewLineStringKey] = newLineString; } if (suppressUniqueIds != null) { - codeDocument.Items[CodeRenderingContext.SuppressUniqueIds] = suppressUniqueIds; + codeDocument.Items[CodeRenderingContext.SuppressUniqueIdsKey] = suppressUniqueIds; } if (nodeWriter == null) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs index ae9ba577a3b..0a1312c9404 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs @@ -793,8 +793,8 @@ public ConfigureCodeRenderingPhase(string lineEnding) protected override void ExecuteCore(RazorCodeDocument codeDocument) { - codeDocument.Items[CodeRenderingContext.SuppressUniqueIds] = "test"; - codeDocument.Items[CodeRenderingContext.NewLineString] = LineEnding; + codeDocument.Items[CodeRenderingContext.SuppressUniqueIdsKey] = "test"; + codeDocument.Items[CodeRenderingContext.NewLineStringKey] = LineEnding; } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs index 2335670b3b5..8927dd3a578 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs @@ -8,7 +8,6 @@ using System.Collections.Immutable; using System.IO; using System.Linq; -using System.Reflection; using System.Runtime.InteropServices; using System.Text; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; @@ -500,9 +499,7 @@ public ForceLineEndingPhase(string lineEnding) 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; + codeDocument.Items[CodeRenderingContext.NewLineStringKey] = LineEnding; } } From 03e2d074c0f2406f663133837b9c309302c8e648 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 08:45:19 -0700 Subject: [PATCH 15/24] Merge RazorCodeGenerationOptionsBuilder and DefaultRazorCodeGenerationOptionsBuilder --- .../DefaultDocumentWriterTest.cs | 2 +- ...efaultRazorCodeGenerationOptionsBuilder.cs | 76 ------------------- ...eGenerationOptionsFactoryProjectFeature.cs | 2 +- .../Language/RazorCodeGenerationOptions.cs | 4 +- .../RazorCodeGenerationOptionsBuilder.cs | 72 +++++++++++++----- 5 files changed, 57 insertions(+), 99 deletions(-) delete mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsBuilder.cs diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs index 1351dc789ff..ed4f43234c1 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs @@ -110,7 +110,7 @@ public void WriteDocument_Empty_SuppressChecksumTrue_DoesnotWriteChecksum() var document = new DocumentIntermediateNode(); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var optionsBuilder = new DefaultRazorCodeGenerationOptionsBuilder(designTime: false) + var optionsBuilder = new RazorCodeGenerationOptionsBuilder(designTime: false) { SuppressChecksum = true }; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsBuilder.cs deleted file mode 100644 index 12816f28a9a..00000000000 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsBuilder.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -using System; - -namespace Microsoft.AspNetCore.Razor.Language; - -internal class DefaultRazorCodeGenerationOptionsBuilder : RazorCodeGenerationOptionsBuilder -{ - private bool _designTime; - - public DefaultRazorCodeGenerationOptionsBuilder(RazorConfiguration configuration, string fileKind) - { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } - - Configuration = configuration; - FileKind = fileKind; - } - - public DefaultRazorCodeGenerationOptionsBuilder(bool designTime) - { - _designTime = designTime; - } - - public override RazorConfiguration Configuration { get; } - - public override bool DesignTime => _designTime; - - public override string FileKind { get; } - - public override int IndentSize { get; set; } = 4; - - public override bool IndentWithTabs { get; set; } - - public override bool SuppressChecksum { get; set; } - - public override bool SuppressNullabilityEnforcement { get; set; } - - public override bool OmitMinimizedComponentAttributeValues { get; set; } - - public override bool SupportLocalizedComponentNames { get; set; } - - public override bool UseEnhancedLinePragma { get; set; } - - public override RazorCodeGenerationOptions Build() - { - return new DefaultRazorCodeGenerationOptions( - IndentWithTabs, - IndentSize, - DesignTime, - RootNamespace, - SuppressChecksum, - SuppressMetadataAttributes, - SuppressPrimaryMethodBody, - SuppressNullabilityEnforcement, - OmitMinimizedComponentAttributeValues, - SupportLocalizedComponentNames, - UseEnhancedLinePragma, - SuppressUniqueIds, - SuppressAddComponentParameter, - RemapLinePragmaPathsOnWindows) - { - SuppressMetadataSourceChecksumAttributes = SuppressMetadataSourceChecksumAttributes, - }; - } - - public override void SetDesignTime(bool designTime) - { - _designTime = designTime; - } -} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsFactoryProjectFeature.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsFactoryProjectFeature.cs index feeb5b3a12b..759821593db 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsFactoryProjectFeature.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptionsFactoryProjectFeature.cs @@ -19,7 +19,7 @@ protected override void OnInitialized() public RazorCodeGenerationOptions Create(string fileKind, Action configure) { - var builder = new DefaultRazorCodeGenerationOptionsBuilder(ProjectEngine.Configuration, fileKind); + var builder = new RazorCodeGenerationOptionsBuilder(ProjectEngine.Configuration, fileKind); configure?.Invoke(builder); for (var i = 0; i < _configureOptions.Length; i++) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index a055dddf6e8..889ad9697c5 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -54,7 +54,7 @@ public static RazorCodeGenerationOptions Create(Action null; + private bool _designTime; + + public RazorConfiguration? Configuration { get; } - public abstract bool DesignTime { get; } + public bool DesignTime => _designTime; - public virtual string FileKind => null; + public string? FileKind { get; } - public abstract int IndentSize { get; set; } + public int IndentSize { get; set; } = 4; - public abstract bool IndentWithTabs { get; set; } + public bool IndentWithTabs { get; set; } /// /// Gets or sets the root namespace of the generated code. /// - public virtual string RootNamespace { get; set; } + public string? RootNamespace { get; set; } /// /// Gets or sets a value that indicates whether to suppress the default #pragma checksum directive in the @@ -31,7 +31,7 @@ public abstract class RazorCodeGenerationOptionsBuilder /// The #pragma checksum is required to enable debugging and should only be suppressed for testing /// purposes. /// - public abstract bool SuppressChecksum { get; set; } + public bool SuppressChecksum { get; set; } /// /// Gets or sets a value that indicates whether to suppress the default metadata attributes in the generated @@ -49,7 +49,7 @@ public abstract class RazorCodeGenerationOptionsBuilder /// a reference to Microsoft.AspNetCore.Razor.Runtime, or for testing purposes. /// /// - public virtual bool SuppressMetadataAttributes { get; set; } + public bool SuppressMetadataAttributes { get; set; } /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -63,32 +63,32 @@ public abstract class RazorCodeGenerationOptionsBuilder /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// - public virtual bool SuppressPrimaryMethodBody { get; set; } + public bool SuppressPrimaryMethodBody { get; set; } /// /// Gets or sets a value that determines if nullability type enforcement should be suppressed for user code. /// - public virtual bool SuppressNullabilityEnforcement { get; set; } + public bool SuppressNullabilityEnforcement { get; set; } /// /// Gets or sets a value that determines if the components code writer may omit values for minimized attributes. /// - public virtual bool OmitMinimizedComponentAttributeValues { get; set; } + public bool OmitMinimizedComponentAttributeValues { get; set; } /// /// Gets or sets a value that determines if localized component names are to be supported. /// - public virtual bool SupportLocalizedComponentNames { get; set; } + public bool SupportLocalizedComponentNames { get; set; } /// /// Gets or sets a value that determines if enhanced line pragmas are to be utilized. /// - public virtual bool UseEnhancedLinePragma { get; set; } + public bool UseEnhancedLinePragma { get; set; } /// /// Gets or sets a value that determines if unique ids are suppressed for testing. /// - internal string SuppressUniqueIds { get; set; } + internal string? SuppressUniqueIds { get; set; } /// /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. @@ -100,9 +100,43 @@ public abstract class RazorCodeGenerationOptionsBuilder /// internal bool RemapLinePragmaPathsOnWindows { get; set; } - public abstract RazorCodeGenerationOptions Build(); + public RazorCodeGenerationOptionsBuilder(RazorConfiguration configuration, string fileKind) + { + ArgHelper.ThrowIfNull(configuration); + + Configuration = configuration; + FileKind = fileKind; + } + + public RazorCodeGenerationOptionsBuilder(bool designTime) + { + _designTime = designTime; + } + + public RazorCodeGenerationOptions Build() + { + return new DefaultRazorCodeGenerationOptions( + IndentWithTabs, + IndentSize, + DesignTime, + RootNamespace, + SuppressChecksum, + SuppressMetadataAttributes, + SuppressPrimaryMethodBody, + SuppressNullabilityEnforcement, + OmitMinimizedComponentAttributeValues, + SupportLocalizedComponentNames, + UseEnhancedLinePragma, + SuppressUniqueIds, + SuppressAddComponentParameter, + RemapLinePragmaPathsOnWindows) + { + SuppressMetadataSourceChecksumAttributes = SuppressMetadataSourceChecksumAttributes, + }; + } - public virtual void SetDesignTime(bool designTime) + public void SetDesignTime(bool designTime) { + _designTime = designTime; } } From 972691bc1ea2a9b559299288f6b75d3da3d5b7d1 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 08:55:05 -0700 Subject: [PATCH 16/24] Merge RazorCodeGenerationOptions and DefaultRazorCodeGenerationOptions --- .../DefaultRazorCodeGenerationOptions.cs | 57 ----- .../Language/RazorCodeGenerationOptions.cs | 198 ++++++++++-------- .../RazorCodeGenerationOptionsBuilder.cs | 2 +- 3 files changed, 112 insertions(+), 145 deletions(-) delete mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptions.cs diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptions.cs deleted file mode 100644 index 76fe6018dd7..00000000000 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorCodeGenerationOptions.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable - -namespace Microsoft.AspNetCore.Razor.Language; - -internal class DefaultRazorCodeGenerationOptions : RazorCodeGenerationOptions -{ - public DefaultRazorCodeGenerationOptions( - bool indentWithTabs, - int indentSize, - bool designTime, - string rootNamespace, - bool suppressChecksum, - bool suppressMetadataAttributes, - bool suppressPrimaryMethodBody, - bool suppressNullabilityEnforcement, - bool omitMinimizedComponentAttributeValues, - bool supportLocalizedComponentNames, - bool useEnhancedLinePragma, - string suppressUniqueIds, - bool suppressAddComponentParameter, - bool remapLinePragmaPathsOnWindows) - { - IndentWithTabs = indentWithTabs; - IndentSize = indentSize; - DesignTime = designTime; - RootNamespace = rootNamespace; - SuppressChecksum = suppressChecksum; - SuppressMetadataAttributes = suppressMetadataAttributes; - SuppressPrimaryMethodBody = suppressPrimaryMethodBody; - SuppressNullabilityEnforcement = suppressNullabilityEnforcement; - OmitMinimizedComponentAttributeValues = omitMinimizedComponentAttributeValues; - SupportLocalizedComponentNames = supportLocalizedComponentNames; - UseEnhancedLinePragma = useEnhancedLinePragma; - SuppressUniqueIds = suppressUniqueIds; - SuppressAddComponentParameter = suppressAddComponentParameter; - RemapLinePragmaPathsOnWindows = remapLinePragmaPathsOnWindows; - } - - public override bool DesignTime { get; } - - public override bool IndentWithTabs { get; } - - public override int IndentSize { get; } - - public override string RootNamespace { get; } - - public override bool SuppressChecksum { get; } - - public override bool SuppressNullabilityEnforcement { get; } - - public override bool OmitMinimizedComponentAttributeValues { get; } - - public override bool UseEnhancedLinePragma { get; } -} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index 889ad9697c5..ceda7b6499a 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -1,94 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - using System; namespace Microsoft.AspNetCore.Razor.Language; -public abstract class RazorCodeGenerationOptions +public sealed class RazorCodeGenerationOptions { - public static RazorCodeGenerationOptions CreateDefault() - { - return new DefaultRazorCodeGenerationOptions( - indentWithTabs: false, - indentSize: 4, - designTime: false, - suppressChecksum: false, - rootNamespace: null, - suppressMetadataAttributes: false, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: false); - } - - public static RazorCodeGenerationOptions CreateDesignTimeDefault() - { - return new DefaultRazorCodeGenerationOptions( - indentWithTabs: false, - indentSize: 4, - designTime: true, - rootNamespace: null, - suppressChecksum: false, - suppressMetadataAttributes: true, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: true); - } - - public static RazorCodeGenerationOptions Create(Action configure) - { - if (configure == null) - { - throw new ArgumentNullException(nameof(configure)); - } - - var builder = new RazorCodeGenerationOptionsBuilder(designTime: false); - configure(builder); - var options = builder.Build(); - - return options; - } - - public static RazorCodeGenerationOptions CreateDesignTime(Action configure) - { - if (configure == null) - { - throw new ArgumentNullException(nameof(configure)); - } - - var builder = new RazorCodeGenerationOptionsBuilder(designTime: true) - { - SuppressMetadataAttributes = true, - }; - - configure(builder); - var options = builder.Build(); - - return options; - } - - public abstract bool DesignTime { get; } + public bool DesignTime { get; } - public abstract bool IndentWithTabs { get; } + public bool IndentWithTabs { get; } - public abstract int IndentSize { get; } + public int IndentSize { get; } /// /// Gets the root namespace for the generated code. /// - public virtual string RootNamespace { get; } + public string? RootNamespace { get; } /// /// Gets a value that indicates whether to suppress the default #pragma checksum directive in the @@ -99,7 +27,7 @@ public static RazorCodeGenerationOptions CreateDesignTime(Action#pragma checksum is required to enable debugging and should only be suppressed for testing /// purposes. /// - public abstract bool SuppressChecksum { get; } + public bool SuppressChecksum { get; } /// /// Gets a value that indicates whether to suppress the default metadata attributes in the generated @@ -117,7 +45,7 @@ public static RazorCodeGenerationOptions CreateDesignTime(ActionMicrosoft.AspNetCore.Razor.Runtime, or for testing purposes. /// /// - public virtual bool SuppressMetadataAttributes { get; protected set; } + public bool SuppressMetadataAttributes { get; } /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -131,40 +59,136 @@ public static RazorCodeGenerationOptions CreateDesignTime(Action /// Gets or sets a value that determines if an empty body is generated for the primary method. /// - public virtual bool SuppressPrimaryMethodBody { get; protected set; } + public bool SuppressPrimaryMethodBody { get; } /// /// Gets a value that determines if nullability type enforcement should be suppressed for user code. /// - public virtual bool SuppressNullabilityEnforcement { get; } + public bool SuppressNullabilityEnforcement { get; } /// /// Gets a value that determines if the components code writer may omit values for minimized attributes. /// - public virtual bool OmitMinimizedComponentAttributeValues { get; } + public bool OmitMinimizedComponentAttributeValues { get; } /// /// Gets a value that determines if localized component names are to be supported. /// - public virtual bool SupportLocalizedComponentNames { get; set; } + public bool SupportLocalizedComponentNames { get; set; } /// /// Gets a value that determines if enhanced line pragmas are to be utilized. /// - public virtual bool UseEnhancedLinePragma { get; } + public bool UseEnhancedLinePragma { get; } /// /// Gets a value used for unique ids for testing purposes. Null for unique ids. /// - internal string SuppressUniqueIds { get; private protected init; } + internal string? SuppressUniqueIds { get; } /// /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. /// - internal bool SuppressAddComponentParameter { get; private protected init; } + internal bool SuppressAddComponentParameter { get; } /// /// Determines if the file paths emitted as part of line pragmas should be mapped back to a valid path on windows. /// - public bool RemapLinePragmaPathsOnWindows { get; private protected init; } + public bool RemapLinePragmaPathsOnWindows { get; } + + public RazorCodeGenerationOptions( + bool indentWithTabs, + int indentSize, + bool designTime, + string? rootNamespace, + bool suppressChecksum, + bool suppressMetadataAttributes, + bool suppressPrimaryMethodBody, + bool suppressNullabilityEnforcement, + bool omitMinimizedComponentAttributeValues, + bool supportLocalizedComponentNames, + bool useEnhancedLinePragma, + string? suppressUniqueIds, + bool suppressAddComponentParameter, + bool remapLinePragmaPathsOnWindows) + { + IndentWithTabs = indentWithTabs; + IndentSize = indentSize; + DesignTime = designTime; + RootNamespace = rootNamespace; + SuppressChecksum = suppressChecksum; + SuppressMetadataAttributes = suppressMetadataAttributes; + SuppressPrimaryMethodBody = suppressPrimaryMethodBody; + SuppressNullabilityEnforcement = suppressNullabilityEnforcement; + OmitMinimizedComponentAttributeValues = omitMinimizedComponentAttributeValues; + SupportLocalizedComponentNames = supportLocalizedComponentNames; + UseEnhancedLinePragma = useEnhancedLinePragma; + SuppressUniqueIds = suppressUniqueIds; + SuppressAddComponentParameter = suppressAddComponentParameter; + RemapLinePragmaPathsOnWindows = remapLinePragmaPathsOnWindows; + } + + public static RazorCodeGenerationOptions CreateDefault() + { + return new RazorCodeGenerationOptions( + indentWithTabs: false, + indentSize: 4, + designTime: false, + suppressChecksum: false, + rootNamespace: null, + suppressMetadataAttributes: false, + suppressPrimaryMethodBody: false, + suppressNullabilityEnforcement: false, + omitMinimizedComponentAttributeValues: false, + supportLocalizedComponentNames: false, + useEnhancedLinePragma: true, + suppressUniqueIds: null, + suppressAddComponentParameter: false, + remapLinePragmaPathsOnWindows: false); + } + + public static RazorCodeGenerationOptions CreateDesignTimeDefault() + { + return new RazorCodeGenerationOptions( + indentWithTabs: false, + indentSize: 4, + designTime: true, + rootNamespace: null, + suppressChecksum: false, + suppressMetadataAttributes: true, + suppressPrimaryMethodBody: false, + suppressNullabilityEnforcement: false, + omitMinimizedComponentAttributeValues: false, + supportLocalizedComponentNames: false, + useEnhancedLinePragma: true, + suppressUniqueIds: null, + suppressAddComponentParameter: false, + remapLinePragmaPathsOnWindows: true); + } + + public static RazorCodeGenerationOptions Create(Action configure) + { + ArgHelper.ThrowIfNull(configure); + + var builder = new RazorCodeGenerationOptionsBuilder(designTime: false); + configure(builder); + var options = builder.Build(); + + return options; + } + + public static RazorCodeGenerationOptions CreateDesignTime(Action configure) + { + ArgHelper.ThrowIfNull(configure); + + var builder = new RazorCodeGenerationOptionsBuilder(designTime: true) + { + SuppressMetadataAttributes = true, + }; + + configure(builder); + var options = builder.Build(); + + return options; + } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs index 1849298b08a..ebaacf58b8f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs @@ -115,7 +115,7 @@ public RazorCodeGenerationOptionsBuilder(bool designTime) public RazorCodeGenerationOptions Build() { - return new DefaultRazorCodeGenerationOptions( + return new RazorCodeGenerationOptions( IndentWithTabs, IndentSize, DesignTime, From dd11c5e0dbd01e910c512fb97d94d80b838ccbcb Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 09:39:47 -0700 Subject: [PATCH 17/24] Clean up RazorCodeGenerationOptions a bit --- .../AssemblyAttributeInjectionPassTest.cs | 20 +-- .../test/InstrumentationPassTest.cs | 18 +-- .../test/CodeGeneration/CodeTargetTest.cs | 8 +- .../DefaultCodeTargetBuilderTest.cs | 2 +- .../CodeGeneration/DefaultCodeTargetTest.cs | 16 +- .../DefaultDocumentWriterTest.cs | 20 +-- .../test/DefaultDocumentClassifierPassTest.cs | 4 +- .../DefaultRazorCSharpLoweringPhaseTest.cs | 2 +- ...tRazorIntermediateNodeLoweringPhaseTest.cs | 2 +- .../test/DocumentClassifierPassBaseTest.cs | 16 +- .../test/RazorCodeDocumentExtensionsTest.cs | 8 +- .../src/Language/CodeGeneration/CodeWriter.cs | 2 +- ...eGenerationOptionsFactoryProjectFeature.cs | 4 +- ...eGenerationOptionsFactoryProjectFeature.cs | 2 +- .../Language/RazorCodeGenerationOptions.cs | 153 ++++++++---------- .../RazorCodeGenerationOptionsBuilder.cs | 15 +- .../src/Language/RazorProjectEngine.cs | 4 +- .../RazorDiagnosticsBenchmark.cs | 2 +- .../RazorDiagnosticsPublisherTest.cs | 2 +- .../FormattingLanguageServerTestBase.cs | 2 +- .../Mapping/RazorLanguageQueryEndpointTest.cs | 2 +- .../RazorMapToDocumentRangesEndpointTest.cs | 2 +- .../RazorDocumentMappingServiceTest.cs | 2 +- .../TestCodeRenderingContext.cs | 4 +- 24 files changed, 141 insertions(+), 171 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/AssemblyAttributeInjectionPassTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/AssemblyAttributeInjectionPassTest.cs index 7ea5db9a39c..431c1ffef9a 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/AssemblyAttributeInjectionPassTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/AssemblyAttributeInjectionPassTest.cs @@ -19,7 +19,7 @@ public void Execute_NoOps_IfNamespaceNodeIsMissing() // Arrange var irDocument = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var pass = new AssemblyAttributeInjectionPass @@ -40,7 +40,7 @@ public void Execute_NoOps_IfNamespaceNodeHasEmptyContent() // Arrange var irDocument = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode() { Content = string.Empty }; @@ -66,7 +66,7 @@ public void Execute_NoOps_IfClassNameNodeIsMissing() // Arrange var irDocument = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); @@ -93,7 +93,7 @@ public void Execute_NoOps_IfClassNameIsEmpty() // Arrange var irDocument = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode @@ -134,7 +134,7 @@ public void Execute_NoOps_IfDocumentIsNotViewOrPage() var irDocument = new DocumentIntermediateNode { DocumentKind = "Default", - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode() { Content = "SomeNamespace" }; @@ -170,7 +170,7 @@ public void Execute_NoOps_ForDesignTime() var irDocument = new DocumentIntermediateNode { DocumentKind = MvcViewDocumentClassifierPass.MvcViewDocumentKind, - Options = RazorCodeGenerationOptions.CreateDesignTimeDefault(), + Options = RazorCodeGenerationOptions.DesignTimeDefault, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode @@ -217,7 +217,7 @@ public void Execute_AddsRazorViewAttribute_ToViews() var irDocument = new DocumentIntermediateNode { DocumentKind = MvcViewDocumentClassifierPass.MvcViewDocumentKind, - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode @@ -270,7 +270,7 @@ public void Execute_EscapesViewPathWhenAddingAttributeToViews() var irDocument = new DocumentIntermediateNode { DocumentKind = MvcViewDocumentClassifierPass.MvcViewDocumentKind, - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode @@ -323,7 +323,7 @@ public void Execute_AddsRazorPagettribute_ToPage() var irDocument = new DocumentIntermediateNode { DocumentKind = RazorPageDocumentClassifierPass.RazorPageDocumentKind, - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var pageDirective = new DirectiveIntermediateNode @@ -383,7 +383,7 @@ public void Execute_EscapesViewPathAndRouteWhenAddingAttributeToPage() var irDocument = new DocumentIntermediateNode { DocumentKind = MvcViewDocumentClassifierPass.MvcViewDocumentKind, - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(irDocument); var @namespace = new NamespaceDeclarationIntermediateNode diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/InstrumentationPassTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/InstrumentationPassTest.cs index d5ac8364cc5..40723f0f28f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/InstrumentationPassTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/InstrumentationPassTest.cs @@ -18,7 +18,7 @@ public void InstrumentationPass_NoOps_ForDesignTime() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDesignTimeDefault(), + Options = RazorCodeGenerationOptions.DesignTimeDefault, }; var builder = IntermediateNodeBuilder.Create(document); @@ -50,7 +50,7 @@ public void InstrumentationPass_InstrumentsHtml() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -89,7 +89,7 @@ public void InstrumentationPass_SkipsHtml_WithoutLocation() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -121,7 +121,7 @@ public void InstrumentationPass_InstrumentsCSharpExpression() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -157,7 +157,7 @@ public void InstrumentationPass_SkipsCSharpExpression_WithoutLocation() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -188,7 +188,7 @@ public void InstrumentationPass_SkipsCSharpExpression_InsideTagHelperAttribute() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -239,7 +239,7 @@ public void InstrumentationPass_SkipsCSharpExpression_InsideTagHelperProperty() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -290,7 +290,7 @@ public void InstrumentationPass_InstrumentsTagHelper() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); @@ -321,7 +321,7 @@ public void InstrumentationPass_SkipsTagHelper_WithoutLocation() // Arrange var document = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var builder = IntermediateNodeBuilder.Create(document); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CodeTargetTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CodeTargetTest.cs index 8d6f8d7f170..29ffd24e1f8 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CodeTargetTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CodeTargetTest.cs @@ -15,7 +15,7 @@ public void CreateDefault_CreatesDefaultCodeTarget() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; // Act var target = CodeTarget.CreateDefault(codeDocument, options); @@ -32,7 +32,7 @@ public void CreateDefault_CallsDelegate() Action @delegate = (b) => { wasCalled = true; }; var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; // Act CodeTarget.CreateDefault(codeDocument, options, @delegate); @@ -46,7 +46,7 @@ public void CreateDefault_AllowsNullDelegate() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; // Act CodeTarget.CreateDefault(codeDocument, options, configure: null); @@ -59,7 +59,7 @@ public void CreateEmpty_AllowsNullDelegate() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; // Act CodeTarget.CreateDefault(codeDocument, options, configure: null); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetBuilderTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetBuilderTest.cs index c2fc301395f..654d44608a0 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetBuilderTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetBuilderTest.cs @@ -14,7 +14,7 @@ public void Build_CreatesDefaultCodeTarget() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var builder = new DefaultCodeTargetBuilder(codeDocument, options); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetTest.cs index 50624d004e4..a8dbc432063 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultCodeTargetTest.cs @@ -14,7 +14,7 @@ public class DefaultCodeTargetTest public void Constructor_CreatesDefensiveCopy() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { @@ -33,7 +33,7 @@ public void Constructor_CreatesDefensiveCopy() public void CreateWriter_DesignTime_CreatesDesignTimeNodeWriter() { // Arrange - var options = RazorCodeGenerationOptions.CreateDesignTimeDefault(); + var options = RazorCodeGenerationOptions.DesignTimeDefault; var target = new DefaultCodeTarget(options, Enumerable.Empty()); // Act @@ -47,7 +47,7 @@ public void CreateWriter_DesignTime_CreatesDesignTimeNodeWriter() public void CreateWriter_Runtime_CreatesRuntimeNodeWriter() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = new DefaultCodeTarget(options, Enumerable.Empty()); // Act @@ -61,7 +61,7 @@ public void CreateWriter_Runtime_CreatesRuntimeNodeWriter() public void HasExtension_ReturnsTrue_WhenExtensionFound() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { @@ -82,7 +82,7 @@ public void HasExtension_ReturnsTrue_WhenExtensionFound() public void HasExtension_ReturnsFalse_WhenExtensionNotFound() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { @@ -103,7 +103,7 @@ public void HasExtension_ReturnsFalse_WhenExtensionNotFound() public void GetExtension_ReturnsExtension_WhenExtensionFound() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { @@ -124,7 +124,7 @@ public void GetExtension_ReturnsExtension_WhenExtensionFound() public void GetExtension_ReturnsFirstMatch_WhenExtensionFound() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { @@ -148,7 +148,7 @@ public void GetExtension_ReturnsFirstMatch_WhenExtensionFound() public void GetExtension_ReturnsNull_WhenExtensionNotFound() { // Arrange - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var extensions = new ICodeTargetExtension[] { diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs index ed4f43234c1..9a9ad5d22b3 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/DefaultDocumentWriterTest.cs @@ -20,7 +20,7 @@ public void WriteDocument_EndToEnd_WritesChecksumAndMarksAutoGenerated() var document = new DocumentIntermediateNode(); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -51,7 +51,7 @@ public void WriteDocument_SHA1_WritesChecksumAndMarksAutoGenerated() var document = new DocumentIntermediateNode(); var codeDocument = RazorCodeDocument.Create(sourceDocument); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -82,7 +82,7 @@ public void WriteDocument_SHA256_WritesChecksumAndMarksAutoGenerated() var document = new DocumentIntermediateNode(); var codeDocument = RazorCodeDocument.Create(sourceDocument); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -144,7 +144,7 @@ public void WriteDocument_WritesNamespace() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -192,7 +192,7 @@ public void WriteDocument_WritesClass() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -243,7 +243,7 @@ public void WriteDocument_WithNullableContext_WritesClass() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -292,7 +292,7 @@ public void WriteDocument_WritesClass_ConstrainedGenericTypeParameters() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -355,7 +355,7 @@ public void WriteDocument_WritesMethod() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -399,7 +399,7 @@ public void WriteDocument_WritesField() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); @@ -439,7 +439,7 @@ public void WriteDocument_WritesProperty() }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; var target = CodeTarget.CreateDefault(codeDocument, options); var writer = new DefaultDocumentWriter(target, options); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultDocumentClassifierPassTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultDocumentClassifierPassTest.cs index 6936b9451e1..2b1a4822e1d 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultDocumentClassifierPassTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultDocumentClassifierPassTest.cs @@ -23,7 +23,7 @@ public void Execute_IgnoresDocumentsWithDocumentKind() var documentNode = new DocumentIntermediateNode() { DocumentKind = "ignore", - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var pass = new DefaultDocumentClassifierPass(); @@ -43,7 +43,7 @@ public void Execute_CreatesClassStructure() // Arrange var documentNode = new DocumentIntermediateNode() { - Options = RazorCodeGenerationOptions.CreateDefault(), + Options = RazorCodeGenerationOptions.Default, }; var pass = new DefaultDocumentClassifierPass(); diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorCSharpLoweringPhaseTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorCSharpLoweringPhaseTest.cs index 4a535879206..b8efdb27514 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorCSharpLoweringPhaseTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorCSharpLoweringPhaseTest.cs @@ -66,7 +66,7 @@ public void Execute_CollatesIRDocumentDiagnosticsFromSourceDocument() var phase = new DefaultRazorCSharpLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => b.Phases.Add(phase)); var codeDocument = TestRazorCodeDocument.Create("

().ToArray(); } - public RazorCodeGenerationOptions Create(string fileKind, Action configure) + public RazorCodeGenerationOptions Create(Action configure) { - var builder = new RazorCodeGenerationOptionsBuilder(ProjectEngine.Configuration, fileKind); + var builder = new RazorCodeGenerationOptionsBuilder(ProjectEngine.Configuration); configure?.Invoke(builder); for (var i = 0; i < _configureOptions.Length; i++) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/IRazorCodeGenerationOptionsFactoryProjectFeature.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/IRazorCodeGenerationOptionsFactoryProjectFeature.cs index 9865f4d792c..3c42ef62a00 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/IRazorCodeGenerationOptionsFactoryProjectFeature.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/IRazorCodeGenerationOptionsFactoryProjectFeature.cs @@ -9,5 +9,5 @@ namespace Microsoft.AspNetCore.Razor.Language; internal interface IRazorCodeGenerationOptionsFactoryProjectFeature : IRazorProjectEngineFeature { - RazorCodeGenerationOptions Create(string fileKind, Action configure); + RazorCodeGenerationOptions Create(Action configure); } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index ceda7b6499a..af2aa5e8a8c 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -5,18 +5,31 @@ namespace Microsoft.AspNetCore.Razor.Language; -public sealed class RazorCodeGenerationOptions +public sealed class RazorCodeGenerationOptions( + bool indentWithTabs, + int indentSize, + bool designTime, + string? rootNamespace, + bool suppressChecksum, + bool suppressMetadataAttributes, + bool suppressMetadataSourceChecksumAttributes, + bool suppressPrimaryMethodBody, + bool suppressNullabilityEnforcement, + bool omitMinimizedComponentAttributeValues, + bool supportLocalizedComponentNames, + bool useEnhancedLinePragma, + string? suppressUniqueIds, + bool suppressAddComponentParameter, + bool remapLinePragmaPathsOnWindows) { - public bool DesignTime { get; } - - public bool IndentWithTabs { get; } - - public int IndentSize { get; } + public bool DesignTime { get; } = designTime; + public bool IndentWithTabs { get; } = indentWithTabs; + public int IndentSize { get; } = indentSize; ///

/// Gets the root namespace for the generated code. /// - public string? RootNamespace { get; } + public string? RootNamespace { get; } = rootNamespace; /// /// Gets a value that indicates whether to suppress the default #pragma checksum directive in the @@ -27,7 +40,7 @@ public sealed class RazorCodeGenerationOptions /// The #pragma checksum is required to enable debugging and should only be suppressed for testing /// purposes. /// - public bool SuppressChecksum { get; } + public bool SuppressChecksum { get; } = suppressChecksum; /// /// Gets a value that indicates whether to suppress the default metadata attributes in the generated @@ -45,7 +58,7 @@ public sealed class RazorCodeGenerationOptions /// a reference to Microsoft.AspNetCore.Razor.Runtime, or for testing purposes. /// /// - public bool SuppressMetadataAttributes { get; } + public bool SuppressMetadataAttributes { get; } = suppressMetadataAttributes; /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -54,117 +67,81 @@ public sealed class RazorCodeGenerationOptions /// edit are treated as rude edits by hot reload. /// /// - internal bool SuppressMetadataSourceChecksumAttributes { get; set; } + public bool SuppressMetadataSourceChecksumAttributes { get; } = suppressMetadataSourceChecksumAttributes; /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// - public bool SuppressPrimaryMethodBody { get; } + public bool SuppressPrimaryMethodBody { get; } = suppressPrimaryMethodBody; /// /// Gets a value that determines if nullability type enforcement should be suppressed for user code. /// - public bool SuppressNullabilityEnforcement { get; } + public bool SuppressNullabilityEnforcement { get; } = suppressNullabilityEnforcement; /// /// Gets a value that determines if the components code writer may omit values for minimized attributes. /// - public bool OmitMinimizedComponentAttributeValues { get; } + public bool OmitMinimizedComponentAttributeValues { get; } = omitMinimizedComponentAttributeValues; /// /// Gets a value that determines if localized component names are to be supported. /// - public bool SupportLocalizedComponentNames { get; set; } + public bool SupportLocalizedComponentNames { get; set; } = supportLocalizedComponentNames; /// /// Gets a value that determines if enhanced line pragmas are to be utilized. /// - public bool UseEnhancedLinePragma { get; } + public bool UseEnhancedLinePragma { get; } = useEnhancedLinePragma; /// /// Gets a value used for unique ids for testing purposes. Null for unique ids. /// - internal string? SuppressUniqueIds { get; } + public string? SuppressUniqueIds { get; } = suppressUniqueIds; /// /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. /// - internal bool SuppressAddComponentParameter { get; } + public bool SuppressAddComponentParameter { get; } = suppressAddComponentParameter; /// /// Determines if the file paths emitted as part of line pragmas should be mapped back to a valid path on windows. /// - public bool RemapLinePragmaPathsOnWindows { get; } - - public RazorCodeGenerationOptions( - bool indentWithTabs, - int indentSize, - bool designTime, - string? rootNamespace, - bool suppressChecksum, - bool suppressMetadataAttributes, - bool suppressPrimaryMethodBody, - bool suppressNullabilityEnforcement, - bool omitMinimizedComponentAttributeValues, - bool supportLocalizedComponentNames, - bool useEnhancedLinePragma, - string? suppressUniqueIds, - bool suppressAddComponentParameter, - bool remapLinePragmaPathsOnWindows) - { - IndentWithTabs = indentWithTabs; - IndentSize = indentSize; - DesignTime = designTime; - RootNamespace = rootNamespace; - SuppressChecksum = suppressChecksum; - SuppressMetadataAttributes = suppressMetadataAttributes; - SuppressPrimaryMethodBody = suppressPrimaryMethodBody; - SuppressNullabilityEnforcement = suppressNullabilityEnforcement; - OmitMinimizedComponentAttributeValues = omitMinimizedComponentAttributeValues; - SupportLocalizedComponentNames = supportLocalizedComponentNames; - UseEnhancedLinePragma = useEnhancedLinePragma; - SuppressUniqueIds = suppressUniqueIds; - SuppressAddComponentParameter = suppressAddComponentParameter; - RemapLinePragmaPathsOnWindows = remapLinePragmaPathsOnWindows; - } - - public static RazorCodeGenerationOptions CreateDefault() - { - return new RazorCodeGenerationOptions( - indentWithTabs: false, - indentSize: 4, - designTime: false, - suppressChecksum: false, - rootNamespace: null, - suppressMetadataAttributes: false, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: false); - } - - public static RazorCodeGenerationOptions CreateDesignTimeDefault() - { - return new RazorCodeGenerationOptions( - indentWithTabs: false, - indentSize: 4, - designTime: true, - rootNamespace: null, - suppressChecksum: false, - suppressMetadataAttributes: true, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: true); - } + public bool RemapLinePragmaPathsOnWindows { get; } = remapLinePragmaPathsOnWindows; + + public static RazorCodeGenerationOptions Default { get; } = new RazorCodeGenerationOptions( + indentWithTabs: false, + indentSize: 4, + designTime: false, + suppressChecksum: false, + rootNamespace: null, + suppressMetadataAttributes: false, + suppressMetadataSourceChecksumAttributes: false, + suppressPrimaryMethodBody: false, + suppressNullabilityEnforcement: false, + omitMinimizedComponentAttributeValues: false, + supportLocalizedComponentNames: false, + useEnhancedLinePragma: true, + suppressUniqueIds: null, + suppressAddComponentParameter: false, + remapLinePragmaPathsOnWindows: false); + + public static RazorCodeGenerationOptions DesignTimeDefault { get; } = new RazorCodeGenerationOptions( + indentWithTabs: false, + indentSize: 4, + designTime: true, + rootNamespace: null, + suppressChecksum: false, + suppressMetadataAttributes: true, + suppressMetadataSourceChecksumAttributes: false, + suppressPrimaryMethodBody: false, + suppressNullabilityEnforcement: false, + omitMinimizedComponentAttributeValues: false, + supportLocalizedComponentNames: false, + useEnhancedLinePragma: true, + suppressUniqueIds: null, + suppressAddComponentParameter: false, + remapLinePragmaPathsOnWindows: true); public static RazorCodeGenerationOptions Create(Action configure) { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs index ebaacf58b8f..242e5e0b7ac 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs @@ -11,8 +11,6 @@ public sealed class RazorCodeGenerationOptionsBuilder public bool DesignTime => _designTime; - public string? FileKind { get; } - public int IndentSize { get; set; } = 4; public bool IndentWithTabs { get; set; } @@ -100,12 +98,11 @@ public sealed class RazorCodeGenerationOptionsBuilder /// internal bool RemapLinePragmaPathsOnWindows { get; set; } - public RazorCodeGenerationOptionsBuilder(RazorConfiguration configuration, string fileKind) + public RazorCodeGenerationOptionsBuilder(RazorConfiguration configuration) { ArgHelper.ThrowIfNull(configuration); Configuration = configuration; - FileKind = fileKind; } public RazorCodeGenerationOptionsBuilder(bool designTime) @@ -114,14 +111,14 @@ public RazorCodeGenerationOptionsBuilder(bool designTime) } public RazorCodeGenerationOptions Build() - { - return new RazorCodeGenerationOptions( + => new( IndentWithTabs, IndentSize, DesignTime, RootNamespace, SuppressChecksum, SuppressMetadataAttributes, + SuppressMetadataSourceChecksumAttributes, SuppressPrimaryMethodBody, SuppressNullabilityEnforcement, OmitMinimizedComponentAttributeValues, @@ -129,11 +126,7 @@ public RazorCodeGenerationOptions Build() UseEnhancedLinePragma, SuppressUniqueIds, SuppressAddComponentParameter, - RemapLinePragmaPathsOnWindows) - { - SuppressMetadataSourceChecksumAttributes = SuppressMetadataSourceChecksumAttributes, - }; - } + RemapLinePragmaPathsOnWindows); public void SetDesignTime(bool designTime) { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorProjectEngine.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorProjectEngine.cs index 81afcdf946c..3675b59bf42 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorProjectEngine.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorProjectEngine.cs @@ -185,7 +185,7 @@ internal RazorCodeDocument CreateCodeDocumentCore( ConfigureParserOptions(builder); configureParser?.Invoke(builder); }); - var codeGenerationOptions = GetRequiredFeature().Create(fileKind, builder => + var codeGenerationOptions = GetRequiredFeature().Create(builder => { ConfigureCodeGenerationOptions(builder); configureCodeGeneration?.Invoke(builder); @@ -261,7 +261,7 @@ private RazorCodeDocument CreateCodeDocumentDesignTimeCore( ConfigureDesignTimeParserOptions(builder); configureParser?.Invoke(builder); }); - var codeGenerationOptions = GetRequiredFeature().Create(fileKind, builder => + var codeGenerationOptions = GetRequiredFeature().Create(builder => { ConfigureDesignTimeCodeGenerationOptions(builder); configureCodeGeneration?.Invoke(builder); diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs index b07988f16c3..d6408537f53 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/LanguageServer/RazorDiagnosticsBenchmark.cs @@ -60,7 +60,7 @@ public void Setup() var mockRazorCSharpDocument = new RazorCSharpDocument( mockRazorCodeDocument.Object, GeneratedCode, - RazorCodeGenerationOptions.CreateDesignTimeDefault(), + RazorCodeGenerationOptions.DesignTimeDefault, diagnostics: [], SourceMappings, linePragmas: []); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs index 58e03d3d2bc..869786c9280 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Diagnostics/RazorDiagnosticsPublisherTest.cs @@ -528,7 +528,7 @@ public void ClearClosedDocuments_RestartsTimerIfDocumentsStillOpen() private static RazorCodeDocument CreateCodeDocument(IEnumerable diagnostics) { var codeDocument = TestRazorCodeDocument.Create("hello"); - var razorCSharpDocument = new RazorCSharpDocument(codeDocument, "hello", RazorCodeGenerationOptions.CreateDefault(), diagnostics.ToImmutableArray()); + var razorCSharpDocument = new RazorCSharpDocument(codeDocument, "hello", RazorCodeGenerationOptions.Default, diagnostics.ToImmutableArray()); codeDocument.SetCSharpDocument(razorCSharpDocument); return codeDocument; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs index 70ad34fc7a9..4403c977fbb 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingLanguageServerTestBase.cs @@ -23,7 +23,7 @@ internal static RazorCodeDocument CreateCodeDocument(string content, ImmutableAr var codeDocument = RazorCodeDocument.Create(sourceDocument); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument, RazorParserOptions.CreateDefault()); var razorCSharpDocument = new RazorCSharpDocument( - codeDocument, content, RazorCodeGenerationOptions.CreateDefault(), diagnostics: [], sourceMappings, linePragmas: []); + codeDocument, content, RazorCodeGenerationOptions.Default, diagnostics: [], sourceMappings, linePragmas: []); codeDocument.SetSyntaxTree(syntaxTree); codeDocument.SetCSharpDocument(razorCSharpDocument); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs index 406250585c4..0a68fcf4892 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorLanguageQueryEndpointTest.cs @@ -148,7 +148,7 @@ private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string r var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, - RazorCodeGenerationOptions.CreateDefault(), + RazorCodeGenerationOptions.Default, diagnostics: [], sourceMappings, linePragmas: []); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs index bda6189e8e6..ef39684a793 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Mapping/RazorMapToDocumentRangesEndpointTest.cs @@ -234,7 +234,7 @@ private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string r var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, - RazorCodeGenerationOptions.CreateDefault(), + RazorCodeGenerationOptions.Default, diagnostics: [], sourceMappings, linePragmas: []); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs index ec594997150..0895c0cbd82 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs @@ -1035,7 +1035,7 @@ private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string r var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, - RazorCodeGenerationOptions.CreateDefault(), + RazorCodeGenerationOptions. Default, diagnostics: [], sourceMappings, linePragmas: []); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index 9a524babdc5..f597323bc77 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -16,7 +16,7 @@ public static CodeRenderingContext CreateDesignTime( IntermediateNodeWriter nodeWriter = null) { var documentNode = new DocumentIntermediateNode(); - var options = RazorCodeGenerationOptions.CreateDesignTimeDefault(); + var options = RazorCodeGenerationOptions.DesignTimeDefault; if (source == null) { @@ -52,7 +52,7 @@ public static CodeRenderingContext CreateRuntime( IntermediateNodeWriter nodeWriter = null) { var documentNode = new DocumentIntermediateNode(); - var options = RazorCodeGenerationOptions.CreateDefault(); + var options = RazorCodeGenerationOptions.Default; if (source == null) { From 96adc428f7cddf1364156132d84ff2413221b7b8 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 11:56:41 -0700 Subject: [PATCH 18/24] Collapse RazorCodeGenerationOptions boolean fields to a flags enum --- .../Language/RazorCodeGenerationOptions.cs | 79 +-- .../RazorCodeGenerationOptionsBuilder.cs | 98 ++-- .../RazorCodeGenerationOptionsFlags.cs | 26 + .../EnumExtensionsTests.cs | 525 ++++++++++++++++++ .../EnumExtensions.cs | 143 +++++ 5 files changed, 789 insertions(+), 82 deletions(-) create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsFlags.cs create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/EnumExtensionsTests.cs create mode 100644 src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index af2aa5e8a8c..c06233cf657 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -6,24 +6,13 @@ namespace Microsoft.AspNetCore.Razor.Language; public sealed class RazorCodeGenerationOptions( - bool indentWithTabs, + RazorCodeGenerationOptionsFlags flags, int indentSize, - bool designTime, string? rootNamespace, - bool suppressChecksum, - bool suppressMetadataAttributes, - bool suppressMetadataSourceChecksumAttributes, - bool suppressPrimaryMethodBody, - bool suppressNullabilityEnforcement, - bool omitMinimizedComponentAttributeValues, - bool supportLocalizedComponentNames, - bool useEnhancedLinePragma, - string? suppressUniqueIds, - bool suppressAddComponentParameter, - bool remapLinePragmaPathsOnWindows) + string? suppressUniqueIds) { - public bool DesignTime { get; } = designTime; - public bool IndentWithTabs { get; } = indentWithTabs; + public bool DesignTime => flags.HasFlag(RazorCodeGenerationOptionsFlags.DesignTime); + public bool IndentWithTabs => flags.HasFlag(RazorCodeGenerationOptionsFlags.IndentWithTabs); public int IndentSize { get; } = indentSize; /// @@ -40,7 +29,8 @@ public sealed class RazorCodeGenerationOptions( /// The #pragma checksum is required to enable debugging and should only be suppressed for testing /// purposes. /// - public bool SuppressChecksum { get; } = suppressChecksum; + public bool SuppressChecksum + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressChecksum); /// /// Gets a value that indicates whether to suppress the default metadata attributes in the generated @@ -58,7 +48,8 @@ public sealed class RazorCodeGenerationOptions( /// a reference to Microsoft.AspNetCore.Razor.Runtime, or for testing purposes. /// /// - public bool SuppressMetadataAttributes { get; } = suppressMetadataAttributes; + public bool SuppressMetadataAttributes + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataAttributes); /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -67,32 +58,38 @@ public sealed class RazorCodeGenerationOptions( /// edit are treated as rude edits by hot reload. /// /// - public bool SuppressMetadataSourceChecksumAttributes { get; } = suppressMetadataSourceChecksumAttributes; + public bool SuppressMetadataSourceChecksumAttributes + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataSourceChecksumAttributes); /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// - public bool SuppressPrimaryMethodBody { get; } = suppressPrimaryMethodBody; + public bool SuppressPrimaryMethodBody + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressPrimaryMethodBody); /// /// Gets a value that determines if nullability type enforcement should be suppressed for user code. /// - public bool SuppressNullabilityEnforcement { get; } = suppressNullabilityEnforcement; + public bool SuppressNullabilityEnforcement + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressNullabilityEnforcement); /// /// Gets a value that determines if the components code writer may omit values for minimized attributes. /// - public bool OmitMinimizedComponentAttributeValues { get; } = omitMinimizedComponentAttributeValues; + public bool OmitMinimizedComponentAttributeValues + => flags.HasFlag(RazorCodeGenerationOptionsFlags.OmitMinimizedComponentAttributeValues); /// /// Gets a value that determines if localized component names are to be supported. /// - public bool SupportLocalizedComponentNames { get; set; } = supportLocalizedComponentNames; + public bool SupportLocalizedComponentNames + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SupportLocalizedComponentNames); /// /// Gets a value that determines if enhanced line pragmas are to be utilized. /// - public bool UseEnhancedLinePragma { get; } = useEnhancedLinePragma; + public bool UseEnhancedLinePragma + => flags.HasFlag(RazorCodeGenerationOptionsFlags.UseEnhancedLinePragma); /// /// Gets a value used for unique ids for testing purposes. Null for unique ids. @@ -102,46 +99,26 @@ public sealed class RazorCodeGenerationOptions( /// /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. /// - public bool SuppressAddComponentParameter { get; } = suppressAddComponentParameter; + public bool SuppressAddComponentParameter + => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressAddComponentParameter); /// /// Determines if the file paths emitted as part of line pragmas should be mapped back to a valid path on windows. /// - public bool RemapLinePragmaPathsOnWindows { get; } = remapLinePragmaPathsOnWindows; + public bool RemapLinePragmaPathsOnWindows + => flags.HasFlag(RazorCodeGenerationOptionsFlags.RemapLinePragmaPathsOnWindows); public static RazorCodeGenerationOptions Default { get; } = new RazorCodeGenerationOptions( - indentWithTabs: false, + flags: RazorCodeGenerationOptionsFlags.DefaultFlags, indentSize: 4, - designTime: false, - suppressChecksum: false, rootNamespace: null, - suppressMetadataAttributes: false, - suppressMetadataSourceChecksumAttributes: false, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: false); + suppressUniqueIds: null); public static RazorCodeGenerationOptions DesignTimeDefault { get; } = new RazorCodeGenerationOptions( - indentWithTabs: false, + flags: RazorCodeGenerationOptionsFlags.DefaultDesignTimeFlags, indentSize: 4, - designTime: true, rootNamespace: null, - suppressChecksum: false, - suppressMetadataAttributes: true, - suppressMetadataSourceChecksumAttributes: false, - suppressPrimaryMethodBody: false, - suppressNullabilityEnforcement: false, - omitMinimizedComponentAttributeValues: false, - supportLocalizedComponentNames: false, - useEnhancedLinePragma: true, - suppressUniqueIds: null, - suppressAddComponentParameter: false, - remapLinePragmaPathsOnWindows: true); + suppressUniqueIds: null); public static RazorCodeGenerationOptions Create(Action configure) { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs index 242e5e0b7ac..e5042bd1545 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsBuilder.cs @@ -5,15 +5,19 @@ namespace Microsoft.AspNetCore.Razor.Language; public sealed class RazorCodeGenerationOptionsBuilder { - private bool _designTime; + private RazorCodeGenerationOptionsFlags _flags; public RazorConfiguration? Configuration { get; } - public bool DesignTime => _designTime; + public bool DesignTime => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.DesignTime); public int IndentSize { get; set; } = 4; - public bool IndentWithTabs { get; set; } + public bool IndentWithTabs + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.IndentWithTabs); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.IndentWithTabs, value); + } /// /// Gets or sets the root namespace of the generated code. @@ -29,7 +33,11 @@ public sealed class RazorCodeGenerationOptionsBuilder /// The #pragma checksum is required to enable debugging and should only be suppressed for testing /// purposes. /// - public bool SuppressChecksum { get; set; } + public bool SuppressChecksum + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressChecksum); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressChecksum, value); + } /// /// Gets or sets a value that indicates whether to suppress the default metadata attributes in the generated @@ -47,7 +55,11 @@ public sealed class RazorCodeGenerationOptionsBuilder /// a reference to Microsoft.AspNetCore.Razor.Runtime, or for testing purposes. /// /// - public bool SuppressMetadataAttributes { get; set; } + public bool SuppressMetadataAttributes + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressMetadataAttributes); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataAttributes, value); + } /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -56,47 +68,79 @@ public sealed class RazorCodeGenerationOptionsBuilder /// edit are treated as rude edits by hot reload. /// /// - internal bool SuppressMetadataSourceChecksumAttributes { get; set; } + public bool SuppressMetadataSourceChecksumAttributes + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressMetadataSourceChecksumAttributes); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataSourceChecksumAttributes, value); + } /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// - public bool SuppressPrimaryMethodBody { get; set; } + public bool SuppressPrimaryMethodBody + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressPrimaryMethodBody); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressPrimaryMethodBody, value); + } /// /// Gets or sets a value that determines if nullability type enforcement should be suppressed for user code. /// - public bool SuppressNullabilityEnforcement { get; set; } + public bool SuppressNullabilityEnforcement + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressNullabilityEnforcement); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressNullabilityEnforcement, value); + } /// /// Gets or sets a value that determines if the components code writer may omit values for minimized attributes. /// - public bool OmitMinimizedComponentAttributeValues { get; set; } + public bool OmitMinimizedComponentAttributeValues + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.OmitMinimizedComponentAttributeValues); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.OmitMinimizedComponentAttributeValues, value); + } /// /// Gets or sets a value that determines if localized component names are to be supported. /// - public bool SupportLocalizedComponentNames { get; set; } + public bool SupportLocalizedComponentNames + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SupportLocalizedComponentNames); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SupportLocalizedComponentNames, value); + } /// /// Gets or sets a value that determines if enhanced line pragmas are to be utilized. /// - public bool UseEnhancedLinePragma { get; set; } + public bool UseEnhancedLinePragma + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.UseEnhancedLinePragma); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.UseEnhancedLinePragma, value); + } /// /// Gets or sets a value that determines if unique ids are suppressed for testing. /// - internal string? SuppressUniqueIds { get; set; } + public string? SuppressUniqueIds { get; set; } /// /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. /// - internal bool SuppressAddComponentParameter { get; set; } + public bool SuppressAddComponentParameter + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.SuppressAddComponentParameter); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.SuppressAddComponentParameter, value); + } /// /// Determines if the file paths emitted as part of line pragmas should be mapped back to a valid path on windows. /// - internal bool RemapLinePragmaPathsOnWindows { get; set; } + public bool RemapLinePragmaPathsOnWindows + { + get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.RemapLinePragmaPathsOnWindows); + set => _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.RemapLinePragmaPathsOnWindows, value); + } public RazorCodeGenerationOptionsBuilder(RazorConfiguration configuration) { @@ -107,29 +151,21 @@ public RazorCodeGenerationOptionsBuilder(RazorConfiguration configuration) public RazorCodeGenerationOptionsBuilder(bool designTime) { - _designTime = designTime; + if (designTime) + { + _flags = RazorCodeGenerationOptionsFlags.DesignTime; + } } public RazorCodeGenerationOptions Build() => new( - IndentWithTabs, + _flags, IndentSize, - DesignTime, RootNamespace, - SuppressChecksum, - SuppressMetadataAttributes, - SuppressMetadataSourceChecksumAttributes, - SuppressPrimaryMethodBody, - SuppressNullabilityEnforcement, - OmitMinimizedComponentAttributeValues, - SupportLocalizedComponentNames, - UseEnhancedLinePragma, - SuppressUniqueIds, - SuppressAddComponentParameter, - RemapLinePragmaPathsOnWindows); - - public void SetDesignTime(bool designTime) + SuppressUniqueIds); + + public void SetDesignTime(bool value) { - _designTime = designTime; + _flags.UpdateFlag(RazorCodeGenerationOptionsFlags.DesignTime, value); } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsFlags.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsFlags.cs new file mode 100644 index 00000000000..f0c651e8e40 --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptionsFlags.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.AspNetCore.Razor.Language; + +[Flags] +public enum RazorCodeGenerationOptionsFlags +{ + DesignTime = 1 << 0, + IndentWithTabs = 1 << 1, + SuppressChecksum = 1 << 2, + SuppressMetadataAttributes = 1 << 3, + SuppressMetadataSourceChecksumAttributes = 1 << 4, + SuppressPrimaryMethodBody = 1 << 5, + SuppressNullabilityEnforcement = 1 << 6, + OmitMinimizedComponentAttributeValues = 1 << 7, + SupportLocalizedComponentNames = 1 << 8, + UseEnhancedLinePragma = 1 << 9, + SuppressAddComponentParameter = 1 << 10, + RemapLinePragmaPathsOnWindows = 1 << 11, + + DefaultFlags = UseEnhancedLinePragma, + DefaultDesignTimeFlags = DesignTime | SuppressMetadataAttributes | UseEnhancedLinePragma | RemapLinePragmaPathsOnWindows +} diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/EnumExtensionsTests.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/EnumExtensionsTests.cs new file mode 100644 index 00000000000..6cd347ae095 --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared.Test/EnumExtensionsTests.cs @@ -0,0 +1,525 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.AspNetCore.Razor.Utilities.Shared.Test; + +public class EnumExtensionsTests +{ + private enum ByteEnum : byte + { + Flag1 = 1 << 0, + Flag2 = 1 << 1, + Flag3 = 1 << 2, + Flag4 = 1 << 3, + Flag5 = 1 << 4, + Flag6 = 1 << 5, + Flag7 = 1 << 6, + Flag8 = 1 << 7 + } + + [Fact] + public void TestByteSizedEnum() + { + ByteEnum actual = 0; + ByteEnum expected = 0; + + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag1); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag2); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag3); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag4); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag5); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag6); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag7); + SetFlagAndAssert(ref actual, ref expected, ByteEnum.Flag8); + + Assert.Equal(byte.MaxValue, (byte)actual); + Assert.Equal(byte.MaxValue, (byte)expected); + + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag1); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag2); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag3); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag4); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag5); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag6); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag7); + ClearFlagAndAssert(ref actual, ref expected, ByteEnum.Flag8); + + Assert.Equal(0, (byte)actual); + Assert.Equal(0, (byte)expected); + + static void SetFlagAndAssert(ref ByteEnum actual, ref ByteEnum expected, ByteEnum flag) + { + actual.SetFlag(flag); + expected |= flag; + Assert.Equal(expected, actual); + + Assert.True(actual.IsFlagSet(flag)); + Assert.False(actual.IsFlagClear(flag)); + } + + static void ClearFlagAndAssert(ref ByteEnum actual, ref ByteEnum expected, ByteEnum flag) + { + actual.ClearFlag(flag); + expected &= ~flag; + Assert.Equal(expected, actual); + + Assert.False(actual.IsFlagSet(flag)); + Assert.True(actual.IsFlagClear(flag)); + } + } + + private enum UInt16Enum : ushort + { + Flag1 = 1 << 0, + Flag2 = 1 << 1, + Flag3 = 1 << 2, + Flag4 = 1 << 3, + Flag5 = 1 << 4, + Flag6 = 1 << 5, + Flag7 = 1 << 6, + Flag8 = 1 << 7, + Flag9 = 1 << 8, + Flag10 = 1 << 9, + Flag11 = 1 << 10, + Flag12 = 1 << 11, + Flag13 = 1 << 12, + Flag14 = 1 << 13, + Flag15 = 1 << 14, + Flag16 = 1 << 15 + } + + [Fact] + public void TestUInt16SizedEnum() + { + UInt16Enum actual = 0; + UInt16Enum expected = 0; + + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag1); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag2); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag3); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag4); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag5); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag6); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag7); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag8); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag9); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag10); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag11); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag12); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag13); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag14); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag15); + SetFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag16); + + Assert.Equal(ushort.MaxValue, (ushort)actual); + Assert.Equal(ushort.MaxValue, (ushort)expected); + + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag1); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag2); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag3); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag4); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag5); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag6); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag7); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag8); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag9); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag10); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag11); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag12); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag13); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag14); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag15); + ClearFlagAndAssert(ref actual, ref expected, UInt16Enum.Flag16); + + Assert.Equal(0, (ushort)actual); + Assert.Equal(0, (ushort)expected); + + static void SetFlagAndAssert(ref UInt16Enum actual, ref UInt16Enum expected, UInt16Enum flag) + { + actual.SetFlag(flag); + expected |= flag; + Assert.Equal(expected, actual); + + Assert.True(actual.IsFlagSet(flag)); + Assert.False(actual.IsFlagClear(flag)); + } + + static void ClearFlagAndAssert(ref UInt16Enum actual, ref UInt16Enum expected, UInt16Enum flag) + { + actual.ClearFlag(flag); + expected &= ~flag; + Assert.Equal(expected, actual); + + Assert.False(actual.IsFlagSet(flag)); + Assert.True(actual.IsFlagClear(flag)); + } + } + + private enum UInt32Enum : uint + { + Flag1 = 1u << 0, + Flag2 = 1u << 1, + Flag3 = 1u << 2, + Flag4 = 1u << 3, + Flag5 = 1u << 4, + Flag6 = 1u << 5, + Flag7 = 1u << 6, + Flag8 = 1u << 7, + Flag9 = 1u << 8, + Flag10 = 1u << 9, + Flag11 = 1u << 10, + Flag12 = 1u << 11, + Flag13 = 1u << 12, + Flag14 = 1u << 13, + Flag15 = 1u << 14, + Flag16 = 1u << 15, + Flag17 = 1u << 16, + Flag18 = 1u << 17, + Flag19 = 1u << 18, + Flag20 = 1u << 19, + Flag21 = 1u << 20, + Flag22 = 1u << 21, + Flag23 = 1u << 22, + Flag24 = 1u << 23, + Flag25 = 1u << 24, + Flag26 = 1u << 25, + Flag27 = 1u << 26, + Flag28 = 1u << 27, + Flag29 = 1u << 28, + Flag30 = 1u << 29, + Flag31 = 1u << 30, + Flag32 = 1u << 31 + } + + [Fact] + public void TestUInt32SizedEnum() + { + UInt32Enum actual = 0; + UInt32Enum expected = 0; + + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag1); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag2); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag3); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag4); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag5); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag6); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag7); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag8); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag9); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag10); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag11); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag12); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag13); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag14); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag15); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag16); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag17); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag18); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag19); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag20); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag21); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag22); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag23); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag24); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag25); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag26); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag27); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag28); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag29); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag30); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag31); + SetFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag32); + + Assert.Equal(uint.MaxValue, (uint)actual); + Assert.Equal(uint.MaxValue, (uint)expected); + + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag1); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag2); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag3); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag4); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag5); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag6); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag7); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag8); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag9); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag10); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag11); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag12); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag13); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag14); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag15); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag16); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag17); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag18); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag19); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag20); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag21); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag22); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag23); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag24); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag25); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag26); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag27); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag28); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag29); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag30); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag31); + ClearFlagAndAssert(ref actual, ref expected, UInt32Enum.Flag32); + + Assert.Equal(0u, (uint)actual); + Assert.Equal(0u, (uint)expected); + + static void SetFlagAndAssert(ref UInt32Enum actual, ref UInt32Enum expected, UInt32Enum flag) + { + actual.SetFlag(flag); + expected |= flag; + Assert.Equal(expected, actual); + + Assert.True(actual.IsFlagSet(flag)); + Assert.False(actual.IsFlagClear(flag)); + } + + static void ClearFlagAndAssert(ref UInt32Enum actual, ref UInt32Enum expected, UInt32Enum flag) + { + actual.ClearFlag(flag); + expected &= ~flag; + Assert.Equal(expected, actual); + + Assert.False(actual.IsFlagSet(flag)); + Assert.True(actual.IsFlagClear(flag)); + } + } + + private enum UInt64Enum : ulong + { + Flag1 = 1ul << 0, + Flag2 = 1ul << 1, + Flag3 = 1ul << 2, + Flag4 = 1ul << 3, + Flag5 = 1ul << 4, + Flag6 = 1ul << 5, + Flag7 = 1ul << 6, + Flag8 = 1ul << 7, + Flag9 = 1ul << 8, + Flag10 = 1ul << 9, + Flag11 = 1ul << 10, + Flag12 = 1ul << 11, + Flag13 = 1ul << 12, + Flag14 = 1ul << 13, + Flag15 = 1ul << 14, + Flag16 = 1ul << 15, + Flag17 = 1ul << 16, + Flag18 = 1ul << 17, + Flag19 = 1ul << 18, + Flag20 = 1ul << 19, + Flag21 = 1ul << 20, + Flag22 = 1ul << 21, + Flag23 = 1ul << 22, + Flag24 = 1ul << 23, + Flag25 = 1ul << 24, + Flag26 = 1ul << 25, + Flag27 = 1ul << 26, + Flag28 = 1ul << 27, + Flag29 = 1ul << 28, + Flag30 = 1ul << 29, + Flag31 = 1ul << 30, + Flag32 = 1ul << 31, + Flag33 = 1ul << 32, + Flag34 = 1ul << 33, + Flag35 = 1ul << 34, + Flag36 = 1ul << 35, + Flag37 = 1ul << 36, + Flag38 = 1ul << 37, + Flag39 = 1ul << 38, + Flag40 = 1ul << 39, + Flag41 = 1ul << 40, + Flag42 = 1ul << 41, + Flag43 = 1ul << 42, + Flag44 = 1ul << 43, + Flag45 = 1ul << 44, + Flag46 = 1ul << 45, + Flag47 = 1ul << 46, + Flag48 = 1ul << 47, + Flag49 = 1ul << 48, + Flag50 = 1ul << 49, + Flag51 = 1ul << 50, + Flag52 = 1ul << 51, + Flag53 = 1ul << 52, + Flag54 = 1ul << 53, + Flag55 = 1ul << 54, + Flag56 = 1ul << 55, + Flag57 = 1ul << 56, + Flag58 = 1ul << 57, + Flag59 = 1ul << 58, + Flag60 = 1ul << 59, + Flag61 = 1ul << 60, + Flag62 = 1ul << 61, + Flag63 = 1ul << 62, + Flag64 = 1ul << 63 + } + + [Fact] + public void TestUInt64SizedEnum() + { + UInt64Enum actual = 0; + UInt64Enum expected = 0; + + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag1); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag2); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag3); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag4); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag5); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag6); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag7); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag8); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag9); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag10); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag11); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag12); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag13); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag14); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag15); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag16); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag17); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag18); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag19); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag20); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag21); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag22); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag23); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag24); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag25); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag26); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag27); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag28); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag29); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag30); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag31); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag32); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag33); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag34); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag35); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag36); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag37); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag38); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag39); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag40); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag41); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag42); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag43); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag44); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag45); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag46); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag47); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag48); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag49); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag50); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag51); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag52); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag53); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag54); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag55); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag56); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag57); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag58); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag59); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag60); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag61); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag62); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag63); + SetFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag64); + + Assert.Equal(ulong.MaxValue, (ulong)actual); + Assert.Equal(ulong.MaxValue, (ulong)expected); + + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag1); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag2); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag3); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag4); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag5); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag6); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag7); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag8); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag9); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag10); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag11); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag12); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag13); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag14); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag15); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag16); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag17); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag18); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag19); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag20); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag21); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag22); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag23); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag24); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag25); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag26); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag27); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag28); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag29); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag30); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag31); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag32); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag33); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag34); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag35); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag36); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag37); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag38); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag39); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag40); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag41); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag42); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag43); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag44); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag45); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag46); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag47); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag48); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag49); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag50); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag51); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag52); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag53); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag54); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag55); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag56); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag57); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag58); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag59); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag60); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag61); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag62); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag63); + ClearFlagAndAssert(ref actual, ref expected, UInt64Enum.Flag64); + + Assert.Equal(0ul, (ulong)actual); + Assert.Equal(0ul, (ulong)expected); + + static void SetFlagAndAssert(ref UInt64Enum actual, ref UInt64Enum expected, UInt64Enum flag) + { + actual.SetFlag(flag); + expected |= flag; + Assert.Equal(expected, actual); + + Assert.True(actual.IsFlagSet(flag)); + Assert.False(actual.IsFlagClear(flag)); + } + + static void ClearFlagAndAssert(ref UInt64Enum actual, ref UInt64Enum expected, UInt64Enum flag) + { + actual.ClearFlag(flag); + expected &= ~flag; + Assert.Equal(expected, actual); + + Assert.False(actual.IsFlagSet(flag)); + Assert.True(actual.IsFlagClear(flag)); + } + } +} diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs new file mode 100644 index 00000000000..2e23da02435 --- /dev/null +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs @@ -0,0 +1,143 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.AspNetCore.Razor; + +internal static class EnumExtensions +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void SetFlag(ref this T value, T flag) + where T : unmanaged, Enum + { + var v = (T*)Unsafe.AsPointer(ref value); + + if (sizeof(T) == sizeof(byte)) + { + *(byte*)v |= *(byte*)&flag; + return; + } + else if (sizeof(T) == sizeof(ushort)) + { + *(ushort*)v |= *(ushort*)&flag; + return; + } + else if (sizeof(T) == sizeof(uint)) + { + *(uint*)v |= *(uint*)&flag; + return; + } + else if (sizeof(T) == sizeof(ulong)) + { + *(ulong*)v |= *(ulong*)&flag; + return; + } + + Debug.Fail("Unexpected enum underlying type."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void ClearFlag(ref this T value, T flag) + where T : unmanaged, Enum + { + var v = (T*)Unsafe.AsPointer(ref value); + + if (sizeof(T) == sizeof(byte)) + { + *(byte*)v &= (byte)~*(byte*)&flag; + return; + } + else if (sizeof(T) == sizeof(ushort)) + { + *(ushort*)v &= (ushort)~*(ushort*)&flag; + return; + } + else if (sizeof(T) == sizeof(uint)) + { + *(uint*)v &= ~*(uint*)&flag; + return; + } + else if (sizeof(T) == sizeof(ulong)) + { + *(ulong*)v &= ~*(ulong*)&flag; + return; + } + + Debug.Fail("Unexpected enum underlying type."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void UpdateFlag(ref this T value, T flag, bool set) + where T : unmanaged, Enum + { + if (set) + { + value.SetFlag(flag); + } + else + { + value.ClearFlag(flag); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe bool IsFlagSet(this T value, T flags) + where T : unmanaged, Enum + { + if (sizeof(T) == sizeof(byte)) + { + var f = *(byte*)&flags; + return (*(byte*)&value & f) == f; + } + else if (sizeof(T) == sizeof(ushort)) + { + var f = *(ushort*)&flags; + return (*(ushort*)&value & f) == f; + } + else if (sizeof(T) == sizeof(uint)) + { + var f = *(uint*)&flags; + return (*(uint*)&value & f) == f; + } + else if (sizeof(T) == sizeof(ulong)) + { + var f = *(ulong*)&flags; + return (*(ulong*)&value & f) == f; + } + + Debug.Fail("Unexpected enum underlying type."); + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe bool IsFlagClear(this T value, T flags) + where T : unmanaged, Enum + { + if (sizeof(T) == sizeof(byte)) + { + var f = *(byte*)&flags; + return (*(byte*)&value & f) == 0; + } + else if (sizeof(T) == sizeof(ushort)) + { + var f = *(ushort*)&flags; + return (*(ushort*)&value & f) == 0; + } + else if (sizeof(T) == sizeof(uint)) + { + var f = *(uint*)&flags; + return (*(uint*)&value & f) == 0; + } + else if (sizeof(T) == sizeof(ulong)) + { + var f = *(ulong*)&flags; + return (*(ulong*)&value & f) == 0; + } + + Debug.Fail("Unexpected enum underlying type."); + return false; + } +} From 28bfd61d3852a864dcc77902c96b6f5c9ff4e17f Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 12:41:39 -0700 Subject: [PATCH 19/24] Use SuppressUniqueIds exclusively from RazorCodeGenerationOptions This change stops pushing the SuppressUniqueIds value into RazorCodeDocument.Items. --- .../CodeGeneration/CodeRenderingContext.cs | 5 --- .../DefaultTagHelperTargetExtension.cs | 2 +- .../Language/RazorCodeGenerationOptions.cs | 36 ++++++++++++------- .../RazorCodeGenerationOptionsBuilder.cs | 5 +++ .../TestCodeRenderingContext.cs | 12 ++++--- .../IntegrationTests/IntegrationTestBase.cs | 12 ++++++- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 045be588210..a2d1cee94ee 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -17,11 +17,8 @@ public sealed class CodeRenderingContext : IDisposable internal static readonly object NewLineStringKey = "NewLineString"; - internal static readonly object SuppressUniqueIdsKey = "SuppressUniqueIds"; - public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } - public string SuppressUniqueIds { get; } private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; @@ -68,8 +65,6 @@ public CodeRenderingContext( // Set new line character to a specific string regardless of platform, for testing purposes. var newLineString = codeDocument.Items[NewLineStringKey] as string ?? Environment.NewLine; CodeWriter = new CodeWriter(newLineString, options); - - SuppressUniqueIds = codeDocument.Items[SuppressUniqueIdsKey] as string ?? options.SuppressUniqueIds; } public void Dispose() diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs index 9509bb6cd61..381812e40f4 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Extensions/DefaultTagHelperTargetExtension.cs @@ -101,7 +101,7 @@ public void WriteTagHelperBody(CodeRenderingContext context, DefaultTagHelperBod // Assign a unique ID for this instance of the source HTML tag. This must be unique // per call site, e.g. if the tag is on the view twice, there should be two IDs. - var uniqueId = context.SuppressUniqueIds; + var uniqueId = context.Options.SuppressUniqueIds; if (uniqueId == null) { uniqueId = GetDeterministicId(context); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index c06233cf657..c80202b078d 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -11,8 +11,10 @@ public sealed class RazorCodeGenerationOptions( string? rootNamespace, string? suppressUniqueIds) { - public bool DesignTime => flags.HasFlag(RazorCodeGenerationOptionsFlags.DesignTime); - public bool IndentWithTabs => flags.HasFlag(RazorCodeGenerationOptionsFlags.IndentWithTabs); + private readonly RazorCodeGenerationOptionsFlags _flags = flags; + + public bool DesignTime => _flags.HasFlag(RazorCodeGenerationOptionsFlags.DesignTime); + public bool IndentWithTabs => _flags.HasFlag(RazorCodeGenerationOptionsFlags.IndentWithTabs); public int IndentSize { get; } = indentSize; /// @@ -30,7 +32,7 @@ public sealed class RazorCodeGenerationOptions( /// purposes. /// public bool SuppressChecksum - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressChecksum); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressChecksum); /// /// Gets a value that indicates whether to suppress the default metadata attributes in the generated @@ -49,7 +51,7 @@ public bool SuppressChecksum /// /// public bool SuppressMetadataAttributes - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataAttributes); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataAttributes); /// /// Gets a value that indicates whether to suppress the RazorSourceChecksumAttribute. @@ -59,37 +61,37 @@ public bool SuppressMetadataAttributes /// /// public bool SuppressMetadataSourceChecksumAttributes - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataSourceChecksumAttributes); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressMetadataSourceChecksumAttributes); /// /// Gets or sets a value that determines if an empty body is generated for the primary method. /// public bool SuppressPrimaryMethodBody - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressPrimaryMethodBody); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressPrimaryMethodBody); /// /// Gets a value that determines if nullability type enforcement should be suppressed for user code. /// public bool SuppressNullabilityEnforcement - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressNullabilityEnforcement); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressNullabilityEnforcement); /// /// Gets a value that determines if the components code writer may omit values for minimized attributes. /// public bool OmitMinimizedComponentAttributeValues - => flags.HasFlag(RazorCodeGenerationOptionsFlags.OmitMinimizedComponentAttributeValues); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.OmitMinimizedComponentAttributeValues); /// /// Gets a value that determines if localized component names are to be supported. /// public bool SupportLocalizedComponentNames - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SupportLocalizedComponentNames); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SupportLocalizedComponentNames); /// /// Gets a value that determines if enhanced line pragmas are to be utilized. /// public bool UseEnhancedLinePragma - => flags.HasFlag(RazorCodeGenerationOptionsFlags.UseEnhancedLinePragma); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.UseEnhancedLinePragma); /// /// Gets a value used for unique ids for testing purposes. Null for unique ids. @@ -100,13 +102,13 @@ public bool UseEnhancedLinePragma /// Determines whether RenderTreeBuilder.AddComponentParameter should not be used. /// public bool SuppressAddComponentParameter - => flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressAddComponentParameter); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.SuppressAddComponentParameter); /// /// Determines if the file paths emitted as part of line pragmas should be mapped back to a valid path on windows. /// public bool RemapLinePragmaPathsOnWindows - => flags.HasFlag(RazorCodeGenerationOptionsFlags.RemapLinePragmaPathsOnWindows); + => _flags.HasFlag(RazorCodeGenerationOptionsFlags.RemapLinePragmaPathsOnWindows); public static RazorCodeGenerationOptions Default { get; } = new RazorCodeGenerationOptions( flags: RazorCodeGenerationOptionsFlags.DefaultFlags, @@ -145,4 +147,14 @@ public static RazorCodeGenerationOptions CreateDesignTime(Action { + b.Features.Add(new ConfigureCodeGenerationOptionsFeature()); b.Phases.Insert(0, new ConfigureCodeRenderingPhase(LineEnding)); b.RegisterExtensions(); @@ -782,6 +783,16 @@ private static string NormalizeNewLines(string content, string lineEnding) return Regex.Replace(content, "(? Date: Wed, 14 Aug 2024 13:03:27 -0700 Subject: [PATCH 20/24] Push NewLine setting into RazorCodeGenerationOptions This change stops pushing the NewLine value into RazorCodeDocument.Items. --- .../CodeGeneration/CSharpCodeWriterTest.cs | 4 ++-- .../CodeGeneration/CodeRenderingContext.cs | 6 +---- .../src/Language/CodeGeneration/CodeWriter.cs | 6 ++--- .../Language/RazorCodeGenerationOptions.cs | 16 ++++++++++---- .../RazorCodeGenerationOptionsBuilder.cs | 13 +++++++++++ .../RazorToolingIntegrationTestBase.cs | 16 +++++--------- .../TestCodeRenderingContext.cs | 4 ++-- .../IntegrationTests/IntegrationTestBase.cs | 22 +++---------------- .../RazorIntegrationTestBase.cs | 16 +++++--------- 9 files changed, 46 insertions(+), 57 deletions(-) diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs index 8d7c6ff83c3..39604a88965 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs @@ -402,7 +402,7 @@ public void CSharpCodeWriter_RespectTabSetting() o.IndentSize = 4; }); - using var writer = new CodeWriter(Environment.NewLine, options); + using var writer = new CodeWriter(options); // Act writer.BuildClassDeclaration(Array.Empty(), "C", "", Array.Empty(), Array.Empty(), context: null); @@ -428,7 +428,7 @@ public void CSharpCodeWriter_RespectSpaceSetting() o.IndentSize = 4; }); - using var writer = new CodeWriter(Environment.NewLine, options); + using var writer = new CodeWriter(options); // Act writer.BuildClassDeclaration(Array.Empty(), "C", "", Array.Empty(), Array.Empty(), context: null); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index a2d1cee94ee..16c95e3b050 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -15,8 +15,6 @@ public sealed class CodeRenderingContext : IDisposable { private readonly record struct ScopeInternal(IntermediateNodeWriter Writer); - internal static readonly object NewLineStringKey = "NewLineString"; - public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } @@ -62,9 +60,7 @@ public CodeRenderingContext( _linePragmas = ArrayBuilderPool.Default.Get(); _sourceMappings = ArrayBuilderPool.Default.Get(); - // Set new line character to a specific string regardless of platform, for testing purposes. - var newLineString = codeDocument.Items[NewLineStringKey] as string ?? Environment.NewLine; - CodeWriter = new CodeWriter(newLineString, options); + CodeWriter = new CodeWriter(options); } public void Dispose() diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs index 2c070e4e97e..15f762cc291 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriter.cs @@ -43,13 +43,13 @@ public sealed partial class CodeWriter : IDisposable private int _currentLineCharacterIndex; public CodeWriter() - : this(Environment.NewLine, RazorCodeGenerationOptions.Default) + : this(RazorCodeGenerationOptions.Default) { } - public CodeWriter(string newLine, RazorCodeGenerationOptions options) + public CodeWriter(RazorCodeGenerationOptions options) { - SetNewLine(newLine); + SetNewLine(options.NewLine); IndentWithTabs = options.IndentWithTabs; TabSize = options.IndentSize; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs index c80202b078d..62d0985a558 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs @@ -8,14 +8,17 @@ namespace Microsoft.AspNetCore.Razor.Language; public sealed class RazorCodeGenerationOptions( RazorCodeGenerationOptionsFlags flags, int indentSize, + string newLine, string? rootNamespace, string? suppressUniqueIds) { private readonly RazorCodeGenerationOptionsFlags _flags = flags; public bool DesignTime => _flags.HasFlag(RazorCodeGenerationOptionsFlags.DesignTime); + public bool IndentWithTabs => _flags.HasFlag(RazorCodeGenerationOptionsFlags.IndentWithTabs); public int IndentSize { get; } = indentSize; + public string NewLine { get; } = newLine; /// /// Gets the root namespace for the generated code. @@ -113,12 +116,14 @@ public bool RemapLinePragmaPathsOnWindows public static RazorCodeGenerationOptions Default { get; } = new RazorCodeGenerationOptions( flags: RazorCodeGenerationOptionsFlags.DefaultFlags, indentSize: 4, + newLine: Environment.NewLine, rootNamespace: null, suppressUniqueIds: null); public static RazorCodeGenerationOptions DesignTimeDefault { get; } = new RazorCodeGenerationOptions( flags: RazorCodeGenerationOptionsFlags.DefaultDesignTimeFlags, indentSize: 4, + newLine: Environment.NewLine, rootNamespace: null, suppressUniqueIds: null); @@ -150,10 +155,13 @@ public static RazorCodeGenerationOptions CreateDesignTime(Action _newLine; + set + { + _newLine = value ?? Environment.NewLine; + } + } + public bool IndentWithTabs { get => _flags.IsFlagSet(RazorCodeGenerationOptionsFlags.IndentWithTabs); @@ -166,6 +178,7 @@ public RazorCodeGenerationOptions Build() => new( _flags, IndentSize, + NewLine, RootNamespace, SuppressUniqueIds); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs index f51221d8a55..8d4d088e7d9 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Language/IntegrationTests/RazorToolingIntegrationTestBase.cs @@ -10,7 +10,6 @@ using System.Reflection; using System.Runtime.InteropServices; using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Mef; @@ -117,7 +116,7 @@ private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, if (LineEnding != null) { - b.Phases.Insert(0, new ForceLineEndingPhase(LineEnding)); + b.Features.Add(new SetNewLineOptionFeature(LineEnding)); } b.Features.Add(new DefaultTypeNameFeature()); @@ -430,18 +429,13 @@ public void Configure(RazorCodeGenerationOptionsBuilder options) } } - private class ForceLineEndingPhase : RazorEnginePhaseBase + private sealed class SetNewLineOptionFeature(string newLine) : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature { - public ForceLineEndingPhase(string lineEnding) - { - LineEnding = lineEnding; - } + public int Order { get; } - public string LineEnding { get; } - - protected override void ExecuteCore(RazorCodeDocument codeDocument) + public void Configure(RazorCodeGenerationOptionsBuilder options) { - codeDocument.Items[CodeRenderingContext.NewLineStringKey] = LineEnding; + options.NewLine = newLine; } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index cfa1bc85fd6..95171e4d37f 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -26,7 +26,7 @@ public static CodeRenderingContext CreateDesignTime( var codeDocument = RazorCodeDocument.Create(source); if (newLineString != null) { - codeDocument.Items[CodeRenderingContext.NewLineStringKey] = newLineString; + optionsBuilder.NewLine = newLineString; } if (suppressUniqueIds != null) @@ -64,7 +64,7 @@ public static CodeRenderingContext CreateRuntime( var codeDocument = RazorCodeDocument.Create(source); if (newLineString != null) { - codeDocument.Items[CodeRenderingContext.NewLineStringKey] = newLineString; + optionsBuilder.NewLine = newLineString; } if (suppressUniqueIds != null) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs index 1a4f8dedcc0..9ec2db725da 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntegrationTestBase.cs @@ -10,7 +10,6 @@ using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Razor.Language.CodeGeneration; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Syntax; @@ -299,8 +298,7 @@ private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, { return RazorProjectEngine.Create(configuration, FileSystem, b => { - b.Features.Add(new ConfigureCodeGenerationOptionsFeature()); - b.Phases.Insert(0, new ConfigureCodeRenderingPhase(LineEnding)); + b.Features.Add(new ConfigureCodeGenerationOptionsFeature(LineEnding)); b.RegisterExtensions(); @@ -783,31 +781,17 @@ private static string NormalizeNewLines(string content, string lineEnding) return Regex.Replace(content, "(? Date: Wed, 14 Aug 2024 13:04:06 -0700 Subject: [PATCH 21/24] Pass RazorSourceDocument into CodeRenderingContext rather than RazorCodeDocument --- .../CodeGeneration/CodeRenderingContext.cs | 9 ++- .../CodeGeneration/DefaultDocumentWriter.cs | 15 ++--- .../TestCodeRenderingContext.cs | 66 +++++++------------ 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 16c95e3b050..9a464eb3ad8 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -15,10 +15,10 @@ public sealed class CodeRenderingContext : IDisposable { private readonly record struct ScopeInternal(IntermediateNodeWriter Writer); + public RazorSourceDocument SourceDocument { get; } public RazorCodeGenerationOptions Options { get; } public CodeWriter CodeWriter { get; } - private readonly RazorCodeDocument _codeDocument; private readonly DocumentIntermediateNode _documentNode; private readonly Stack _ancestorStack; @@ -29,20 +29,19 @@ public sealed class CodeRenderingContext : IDisposable private readonly ImmutableArray.Builder _linePragmas; public string DocumentKind => _documentNode.DocumentKind; - public RazorSourceDocument SourceDocument => _codeDocument.Source; public CodeRenderingContext( IntermediateNodeWriter nodeWriter, - RazorCodeDocument codeDocument, + RazorSourceDocument sourceDocument, DocumentIntermediateNode documentNode, RazorCodeGenerationOptions options) { ArgHelper.ThrowIfNull(nodeWriter); - ArgHelper.ThrowIfNull(codeDocument); + ArgHelper.ThrowIfNull(sourceDocument); ArgHelper.ThrowIfNull(documentNode); ArgHelper.ThrowIfNull(options); - _codeDocument = codeDocument; + SourceDocument = sourceDocument; _documentNode = documentNode; Options = options; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index cd9a8ab0833..81c09425d0c 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -4,7 +4,6 @@ #nullable disable using System; -using System.Collections.Immutable; using System.Linq; using System.Security.Cryptography; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -24,21 +23,15 @@ public DefaultDocumentWriter(CodeTarget codeTarget, RazorCodeGenerationOptions o public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) { - if (codeDocument == null) - { - throw new ArgumentNullException(nameof(codeDocument)); - } - - if (documentNode == null) - { - throw new ArgumentNullException(nameof(documentNode)); - } + ArgHelper.ThrowIfNull(codeDocument); + ArgHelper.ThrowIfNull(documentNode); using var context = new CodeRenderingContext( _codeTarget.CreateNodeWriter(), - codeDocument, + codeDocument.Source, documentNode, _options); + context.Visitor = new Visitor(_codeTarget, context); context.Visitor.VisitDocument(documentNode); diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index 95171e4d37f..23338cab77b 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -15,33 +15,13 @@ public static CodeRenderingContext CreateDesignTime( RazorSourceDocument source = null, IntermediateNodeWriter nodeWriter = null) { + nodeWriter ??= new RuntimeNodeWriter(); + source ??= TestRazorSourceDocument.Create(); var documentNode = new DocumentIntermediateNode(); - var optionsBuilder = RazorCodeGenerationOptions.DesignTimeDefault.ToBuilder(); - if (source == null) - { - source = TestRazorSourceDocument.Create(); - } + var options = ConfigureOptions(RazorCodeGenerationOptions.DesignTimeDefault, newLineString, suppressUniqueIds); - var codeDocument = RazorCodeDocument.Create(source); - if (newLineString != null) - { - optionsBuilder.NewLine = newLineString; - } - - if (suppressUniqueIds != null) - { - optionsBuilder.SuppressUniqueIds = suppressUniqueIds; - } - - if (nodeWriter == null) - { - nodeWriter = new DesignTimeNodeWriter(); - } - - var options = optionsBuilder.Build(); - - var context = new CodeRenderingContext(nodeWriter, codeDocument, documentNode, options); + var context = new CodeRenderingContext(nodeWriter, source, documentNode, options); context.Visitor = new RenderChildrenVisitor(context); return context; @@ -53,36 +33,38 @@ public static CodeRenderingContext CreateRuntime( RazorSourceDocument source = null, IntermediateNodeWriter nodeWriter = null) { + nodeWriter ??= new RuntimeNodeWriter(); + source ??= TestRazorSourceDocument.Create(); var documentNode = new DocumentIntermediateNode(); - var optionsBuilder = RazorCodeGenerationOptions.Default.ToBuilder(); - if (source == null) - { - source = TestRazorSourceDocument.Create(); - } + var options = ConfigureOptions(RazorCodeGenerationOptions.Default, newLineString, suppressUniqueIds); + + var context = new CodeRenderingContext(nodeWriter, source, documentNode, options); + context.Visitor = new RenderChildrenVisitor(context); + + return context; + } - var codeDocument = RazorCodeDocument.Create(source); - if (newLineString != null) + private static RazorCodeGenerationOptions ConfigureOptions(RazorCodeGenerationOptions options, string newLine, string suppressUniqueIds) + { + if (newLine is null && suppressUniqueIds is null) { - optionsBuilder.NewLine = newLineString; + return options; } - if (suppressUniqueIds != null) + var builder = options.ToBuilder(); + + if (newLine is not null) { - optionsBuilder.SuppressUniqueIds = suppressUniqueIds; + builder.NewLine = newLine; } - if (nodeWriter == null) + if (suppressUniqueIds is not null) { - nodeWriter = new RuntimeNodeWriter(); + builder.SuppressUniqueIds = suppressUniqueIds; } - var options = optionsBuilder.Build(); - - var context = new CodeRenderingContext(nodeWriter, codeDocument, documentNode, options); - context.Visitor = new RenderChildrenVisitor(context); - - return context; + return builder.Build(); } private class RenderChildrenVisitor : IntermediateNodeVisitor From 6593264ac651f3511f82c9c9a0743786437c14c1 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 14 Aug 2024 14:37:56 -0700 Subject: [PATCH 22/24] Clean up and enable nullability for CodeRenderingContext and DefaultDocumentWriter --- .../src/Language/ChecksumUtilities.cs | 1 - .../CodeGeneration/CodeRenderingContext.cs | 15 +- .../CodeGeneration/DefaultDocumentWriter.cs | 176 ++++++++---------- .../TestCodeRenderingContext.cs | 14 +- 4 files changed, 94 insertions(+), 112 deletions(-) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/ChecksumUtilities.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/ChecksumUtilities.cs index 790b35abe3a..4b40a41f45f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/ChecksumUtilities.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/ChecksumUtilities.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Immutable; using System.Globalization; -using System.Text; using Microsoft.AspNetCore.Razor.PooledObjects; namespace Microsoft.AspNetCore.Razor.Language; diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs index 9a464eb3ad8..23cc201671f 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContext.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -28,6 +26,9 @@ public sealed class CodeRenderingContext : IDisposable private readonly ImmutableArray.Builder _sourceMappings; private readonly ImmutableArray.Builder _linePragmas; + private IntermediateNodeVisitor? _visitor; + public IntermediateNodeVisitor Visitor => _visitor.AssumeNotNull(); + public string DocumentKind => _documentNode.DocumentKind; public CodeRenderingContext( @@ -74,12 +75,16 @@ public void Dispose() CodeWriter.Dispose(); } - // This will be initialized by the document writer when the context is 'live'. - public IntermediateNodeVisitor Visitor { get; set; } + // This will be called by the document writer when the context is 'live'. + public void SetVisitor(IntermediateNodeVisitor visitor) + { + _visitor = visitor; + } public IntermediateNodeWriter NodeWriter => _scopeStack.Peek().Writer; - public IntermediateNode Parent => _ancestorStack.Count == 0 ? null : _ancestorStack.Peek(); + public IntermediateNode? Parent + => _ancestorStack.Count == 0 ? null : _ancestorStack.Peek(); public void AddDiagnostic(RazorDiagnostic diagnostic) { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs index 81c09425d0c..550e32ca7ea 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/DefaultDocumentWriter.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - using System; using System.Linq; using System.Security.Cryptography; @@ -10,16 +8,10 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; -internal class DefaultDocumentWriter : DocumentWriter +internal class DefaultDocumentWriter(CodeTarget codeTarget, RazorCodeGenerationOptions options) : DocumentWriter { - private readonly CodeTarget _codeTarget; - private readonly RazorCodeGenerationOptions _options; - - public DefaultDocumentWriter(CodeTarget codeTarget, RazorCodeGenerationOptions options) - { - _codeTarget = codeTarget; - _options = options; - } + private readonly CodeTarget _codeTarget = codeTarget; + private readonly RazorCodeGenerationOptions _options = options; public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) { @@ -32,37 +24,35 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument documentNode, _options); - context.Visitor = new Visitor(_codeTarget, context); + context.SetVisitor(new Visitor(_codeTarget, context)); context.Visitor.VisitDocument(documentNode); - var csharp = context.CodeWriter.GenerateCode(); + var generatedCode = context.CodeWriter.GenerateCode(); return new RazorCSharpDocument( codeDocument, - csharp, + generatedCode, _options, context.GetDiagnostics(), context.GetSourceMappings(), context.GetLinePragmas()); } - private class Visitor : IntermediateNodeVisitor + private sealed class Visitor(CodeTarget codeTarget, CodeRenderingContext context) : IntermediateNodeVisitor { - private readonly CodeRenderingContext _context; - private readonly CodeTarget _target; + private readonly CodeRenderingContext _context = context; + private readonly CodeTarget _codeTarget = codeTarget; - public Visitor(CodeTarget target, CodeRenderingContext context) - { - _target = target; - _context = context; - } - - private CodeRenderingContext Context => _context; + private CodeWriter CodeWriter => _context.CodeWriter; + private IntermediateNodeWriter NodeWriter => _context.NodeWriter; + private RazorCodeGenerationOptions Options => _context.Options; public override void VisitDocument(DocumentIntermediateNode node) { - if (!Context.Options.SuppressChecksum) + var codeWriter = CodeWriter; + + if (!Options.SuppressChecksum) { // See http://msdn.microsoft.com/en-us/library/system.codedom.codechecksumpragma.checksumalgorithmid.aspx // And https://github.com/dotnet/roslyn/blob/614299ff83da9959fa07131c6d0ffbc58873b6ae/src/Compilers/Core/Portable/PEWriter/DebugSourceDocument.cs#L67 @@ -70,7 +60,7 @@ public override void VisitDocument(DocumentIntermediateNode node) // We only support algorithms that the debugger understands, which is currently SHA1 and SHA256. string algorithmId; - var algorithm = Context.SourceDocument.Text.ChecksumAlgorithm; + var algorithm = _context.SourceDocument.Text.ChecksumAlgorithm; if (algorithm == CodeAnalysis.Text.SourceHashAlgorithm.Sha256) { algorithmId = "{8829d00f-11b8-4213-878b-770e8597ac16}"; @@ -81,80 +71,75 @@ public override void VisitDocument(DocumentIntermediateNode node) } else { - var supportedAlgorithms = string.Join(" ", new string[] - { - HashAlgorithmName.SHA1.Name, - HashAlgorithmName.SHA256.Name - }); + string?[] supportedAlgorithms = [HashAlgorithmName.SHA1.Name, HashAlgorithmName.SHA256.Name]; var message = Resources.FormatUnsupportedChecksumAlgorithm( algorithm, - supportedAlgorithms, - nameof(RazorCodeGenerationOptions) + "." + nameof(RazorCodeGenerationOptions.SuppressChecksum), + string.Join(" ", supportedAlgorithms), + $"{nameof(RazorCodeGenerationOptions)}.{nameof(RazorCodeGenerationOptions.SuppressChecksum)}", bool.TrueString); + throw new InvalidOperationException(message); } - var sourceDocument = Context.SourceDocument; + var sourceDocument = _context.SourceDocument; var checksum = ChecksumUtilities.BytesToString(sourceDocument.Text.GetChecksum()); - if (!string.IsNullOrEmpty(checksum)) + var filePath = sourceDocument.FilePath.AssumeNotNull(); + + if (checksum.Length > 0) { - Context.CodeWriter - .Write("#pragma checksum \"") - .Write(sourceDocument.FilePath) - .Write("\" \"") - .Write(algorithmId) - .Write("\" \"") - .Write(checksum) - .WriteLine("\""); + codeWriter.WriteLine($"#pragma checksum \"{filePath}\" \"{algorithmId}\" \"{checksum}\""); } } - Context.CodeWriter + codeWriter .WriteLine("// ") .WriteLine("#pragma warning disable 1591"); VisitDefault(node); - Context.CodeWriter.WriteLine("#pragma warning restore 1591"); + codeWriter.WriteLine("#pragma warning restore 1591"); } public override void VisitUsingDirective(UsingDirectiveIntermediateNode node) { - Context.NodeWriter.WriteUsingDirective(Context, node); + NodeWriter.WriteUsingDirective(_context, node); } public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node) { - using (Context.CodeWriter.BuildNamespace(node.Content, node.Source, Context)) + var codeWriter = CodeWriter; + + using (codeWriter.BuildNamespace(node.Content, node.Source, _context)) { if (node.Children.OfType().Any()) { // Tooling needs at least one line directive before using directives, otherwise Roslyn will // not offer to create a new one. The last using in the group will output a hidden line // directive after itself. - Context.CodeWriter.WriteLine("#line default"); + codeWriter.WriteLine("#line default"); } else { // If there are no using directives, we output the hidden directive here. - Context.CodeWriter.WriteLine("#line hidden"); + codeWriter.WriteLine("#line hidden"); } + VisitDefault(node); } } public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node) { - using (Context.CodeWriter.BuildClassDeclaration( + using (CodeWriter.BuildClassDeclaration( node.Modifiers, node.ClassName, node.BaseType, node.Interfaces, node.TypeParameters, - Context, - useNullableContext: !Context.Options.SuppressNullabilityEnforcement && node.Annotations[CommonAnnotations.NullableContext] is not null)) + _context, + useNullableContext: !Options.SuppressNullabilityEnforcement && node.Annotations[CommonAnnotations.NullableContext] is not null)) { VisitDefault(node); } @@ -162,100 +147,99 @@ public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node public override void VisitMethodDeclaration(MethodDeclarationIntermediateNode node) { - Context.CodeWriter.WriteLine("#pragma warning disable 1998"); + var codeWriter = CodeWriter; + + codeWriter.WriteLine("#pragma warning disable 1998"); for (var i = 0; i < node.Modifiers.Count; i++) { - Context.CodeWriter.Write(node.Modifiers[i]); - Context.CodeWriter.Write(" "); + codeWriter.Write($"{node.Modifiers[i]} "); } - Context.CodeWriter.Write(node.ReturnType); - Context.CodeWriter.Write(" "); + codeWriter.Write($"{node.ReturnType} "); + codeWriter.Write($"{node.MethodName}("); - Context.CodeWriter.Write(node.MethodName); - Context.CodeWriter.Write("("); + var isFirst = true; for (var i = 0; i < node.Parameters.Count; i++) { var parameter = node.Parameters[i]; - for (var j = 0; j < parameter.Modifiers.Count; j++) + if (isFirst) { - Context.CodeWriter.Write(parameter.Modifiers[j]); - Context.CodeWriter.Write(" "); + isFirst = false; + } + else + { + codeWriter.Write(", "); } - Context.CodeWriter.Write(parameter.TypeName); - Context.CodeWriter.Write(" "); - - Context.CodeWriter.Write(parameter.ParameterName); - - if (i < node.Parameters.Count - 1) + for (var j = 0; j < parameter.Modifiers.Count; j++) { - Context.CodeWriter.Write(", "); + codeWriter.Write($"{parameter.Modifiers[j]} "); } + + codeWriter.Write($"{parameter.TypeName} {parameter.ParameterName}"); } - Context.CodeWriter.Write(")"); - Context.CodeWriter.WriteLine(); + codeWriter.WriteLine(")"); - using (Context.CodeWriter.BuildScope()) + using (codeWriter.BuildScope()) { VisitDefault(node); } - Context.CodeWriter.WriteLine("#pragma warning restore 1998"); + codeWriter.WriteLine("#pragma warning restore 1998"); } public override void VisitFieldDeclaration(FieldDeclarationIntermediateNode node) { - Context.CodeWriter.WriteField(node.SuppressWarnings, node.Modifiers, node.FieldType, node.FieldName); + CodeWriter.WriteField(node.SuppressWarnings, node.Modifiers, node.FieldType, node.FieldName); } public override void VisitPropertyDeclaration(PropertyDeclarationIntermediateNode node) { - Context.CodeWriter.WriteAutoPropertyDeclaration(node.Modifiers, node.PropertyType, node.PropertyName); + CodeWriter.WriteAutoPropertyDeclaration(node.Modifiers, node.PropertyType, node.PropertyName); } public override void VisitExtension(ExtensionIntermediateNode node) { - node.WriteNode(_target, Context); + node.WriteNode(_codeTarget, _context); } public override void VisitCSharpExpression(CSharpExpressionIntermediateNode node) { - Context.NodeWriter.WriteCSharpExpression(Context, node); + NodeWriter.WriteCSharpExpression(_context, node); } public override void VisitCSharpCode(CSharpCodeIntermediateNode node) { - Context.NodeWriter.WriteCSharpCode(Context, node); + NodeWriter.WriteCSharpCode(_context, node); } public override void VisitHtmlAttribute(HtmlAttributeIntermediateNode node) { - Context.NodeWriter.WriteHtmlAttribute(Context, node); + NodeWriter.WriteHtmlAttribute(_context, node); } public override void VisitHtmlAttributeValue(HtmlAttributeValueIntermediateNode node) { - Context.NodeWriter.WriteHtmlAttributeValue(Context, node); + NodeWriter.WriteHtmlAttributeValue(_context, node); } public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node) { - Context.NodeWriter.WriteCSharpExpressionAttributeValue(Context, node); + NodeWriter.WriteCSharpExpressionAttributeValue(_context, node); } public override void VisitCSharpCodeAttributeValue(CSharpCodeAttributeValueIntermediateNode node) { - Context.NodeWriter.WriteCSharpCodeAttributeValue(Context, node); + NodeWriter.WriteCSharpCodeAttributeValue(_context, node); } public override void VisitHtml(HtmlContentIntermediateNode node) { - Context.NodeWriter.WriteHtmlContent(Context, node); + NodeWriter.WriteHtmlContent(_context, node); } public override void VisitTagHelper(TagHelperIntermediateNode node) @@ -265,67 +249,67 @@ public override void VisitTagHelper(TagHelperIntermediateNode node) public override void VisitComponent(ComponentIntermediateNode node) { - Context.NodeWriter.WriteComponent(Context, node); + NodeWriter.WriteComponent(_context, node); } public override void VisitComponentAttribute(ComponentAttributeIntermediateNode node) { - Context.NodeWriter.WriteComponentAttribute(Context, node); + NodeWriter.WriteComponentAttribute(_context, node); } public override void VisitComponentChildContent(ComponentChildContentIntermediateNode node) { - Context.NodeWriter.WriteComponentChildContent(Context, node); + NodeWriter.WriteComponentChildContent(_context, node); } public override void VisitComponentTypeArgument(ComponentTypeArgumentIntermediateNode node) { - Context.NodeWriter.WriteComponentTypeArgument(Context, node); + NodeWriter.WriteComponentTypeArgument(_context, node); } public override void VisitComponentTypeInferenceMethod(ComponentTypeInferenceMethodIntermediateNode node) { - Context.NodeWriter.WriteComponentTypeInferenceMethod(Context, node); + NodeWriter.WriteComponentTypeInferenceMethod(_context, node); } public override void VisitMarkupElement(MarkupElementIntermediateNode node) { - Context.NodeWriter.WriteMarkupElement(Context, node); + NodeWriter.WriteMarkupElement(_context, node); } public override void VisitMarkupBlock(MarkupBlockIntermediateNode node) { - Context.NodeWriter.WriteMarkupBlock(Context, node); + NodeWriter.WriteMarkupBlock(_context, node); } public override void VisitReferenceCapture(ReferenceCaptureIntermediateNode node) { - Context.NodeWriter.WriteReferenceCapture(Context, node); + NodeWriter.WriteReferenceCapture(_context, node); } public override void VisitSetKey(SetKeyIntermediateNode node) { - Context.NodeWriter.WriteSetKey(Context, node); + NodeWriter.WriteSetKey(_context, node); } public override void VisitSplat(SplatIntermediateNode node) { - Context.NodeWriter.WriteSplat(Context, node); + NodeWriter.WriteSplat(_context, node); } public override void VisitRenderMode(RenderModeIntermediateNode node) { - Context.NodeWriter.WriteRenderMode(Context, node); + NodeWriter.WriteRenderMode(_context, node); } public override void VisitFormName(FormNameIntermediateNode node) { - Context.NodeWriter.WriteFormName(Context, node); + NodeWriter.WriteFormName(_context, node); } public override void VisitDefault(IntermediateNode node) { - Context.RenderChildren(node); + _context.RenderChildren(node); } } } diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs index 23338cab77b..b884acf51ef 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/CodeGeneration/TestCodeRenderingContext.cs @@ -22,7 +22,7 @@ public static CodeRenderingContext CreateDesignTime( var options = ConfigureOptions(RazorCodeGenerationOptions.DesignTimeDefault, newLineString, suppressUniqueIds); var context = new CodeRenderingContext(nodeWriter, source, documentNode, options); - context.Visitor = new RenderChildrenVisitor(context); + context.SetVisitor(new RenderChildrenVisitor(context.CodeWriter)); return context; } @@ -40,7 +40,7 @@ public static CodeRenderingContext CreateRuntime( var options = ConfigureOptions(RazorCodeGenerationOptions.Default, newLineString, suppressUniqueIds); var context = new CodeRenderingContext(nodeWriter, source, documentNode, options); - context.Visitor = new RenderChildrenVisitor(context); + context.SetVisitor(new RenderChildrenVisitor(context.CodeWriter)); return context; } @@ -67,17 +67,11 @@ private static RazorCodeGenerationOptions ConfigureOptions(RazorCodeGenerationOp return builder.Build(); } - private class RenderChildrenVisitor : IntermediateNodeVisitor + private class RenderChildrenVisitor(CodeWriter writer) : IntermediateNodeVisitor { - private readonly CodeRenderingContext _context; - public RenderChildrenVisitor(CodeRenderingContext context) - { - _context = context; - } - public override void VisitDefault(IntermediateNode node) { - _context.CodeWriter.WriteLine("Render Children"); + writer.WriteLine("Render Children"); } } } From b58f1809105f2435c50c7c4daabbc89a3930e608 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 20 Aug 2024 10:24:06 -0700 Subject: [PATCH 23/24] Fix goofy whitespace --- .../RazorDocumentMappingServiceTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs index 0895c0cbd82..041d32417a2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentMappingServiceTest.cs @@ -1035,7 +1035,7 @@ private static RazorCodeDocument CreateCodeDocumentWithCSharpProjection(string r var csharpDocument = new RazorCSharpDocument( codeDocument, projectedCSharpSource, - RazorCodeGenerationOptions. Default, + RazorCodeGenerationOptions.Default, diagnostics: [], sourceMappings, linePragmas: []); From 934fea83a748638399af237d54c6690390abeabe Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 20 Aug 2024 10:38:02 -0700 Subject: [PATCH 24/24] Add comments explaining the aggressive inlining behavior of EnumExtensions --- .../EnumExtensions.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs index 2e23da02435..67df57e028c 100644 --- a/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs +++ b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/EnumExtensions.cs @@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor; internal static class EnumExtensions { + // Note: This is written to allow the JIT to inline only the correct branch depending on the size of T. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void SetFlag(ref this T value, T flag) where T : unmanaged, Enum @@ -39,6 +40,7 @@ public static unsafe void SetFlag(ref this T value, T flag) Debug.Fail("Unexpected enum underlying type."); } + // Note: This is written to allow the JIT to inline only the correct branch depending on the size of T. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void ClearFlag(ref this T value, T flag) where T : unmanaged, Enum @@ -83,6 +85,8 @@ public static unsafe void UpdateFlag(ref this T value, T flag, bool set) } } + // Note: This is written to allow the JIT to inline only the correct branch depending on the size of T. + // This is somewhat faster than Enum.HasFlag(...) when running on .NET Framework. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool IsFlagSet(this T value, T flags) where T : unmanaged, Enum @@ -112,6 +116,7 @@ public static unsafe bool IsFlagSet(this T value, T flags) return false; } + // Note: This is written to allow the JIT to inline only the correct branch depending on the size of T. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool IsFlagClear(this T value, T flags) where T : unmanaged, Enum