| File: Language\CodeGeneration\CodeRenderingContextExtensions.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using Microsoft.AspNetCore.Razor.Utilities; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration; internal static class CodeRenderingContextExtensions { public static LinePragmaScope BuildLinePragma( this CodeRenderingContext context, SourceSpan? span, bool suppressLineDefaultAndHidden = false) { // Can't build a valid line pragma without a file path. return span is SourceSpan spanValue && !spanValue.FilePath.IsNullOrEmpty() ? LinePragmaScope.Standard(context, spanValue, suppressLineDefaultAndHidden) : LinePragmaScope.None; } public static LinePragmaScope BuildEnhancedLinePragma( this CodeRenderingContext context, SourceSpan? span, int characterOffset = 0, bool suppressLineDefaultAndHidden = false) { // Can't build a valid line pragma without a file path. return span is SourceSpan spanValue && !spanValue.FilePath.IsNullOrEmpty() ? LinePragmaScope.Enhanced(context, spanValue, characterOffset, suppressLineDefaultAndHidden) : LinePragmaScope.None; } public readonly ref struct LinePragmaScope { private readonly CodeRenderingContext _context; private readonly SourceSpan _span; private readonly bool _isEnhanced; private readonly int _originalIndent; private readonly bool _suppressLineDefaultAndHidden; private LinePragmaScope( CodeRenderingContext context, SourceSpan span, bool isEnhanced, int originalIndent, bool suppressLineDefaultAndHidden) { _context = context; _span = span; _isEnhanced = isEnhanced; _originalIndent = originalIndent; _suppressLineDefaultAndHidden = suppressLineDefaultAndHidden; } public static LinePragmaScope None => default; public static LinePragmaScope Standard(CodeRenderingContext context, SourceSpan span, bool suppressLineDefaultAndHidden) { var writer = context.CodeWriter; var options = context.Options; var (originalIndent, ensurePathBackSlashes) = WritePreamble(writer, options); writer.WriteLineNumberDirective(span, ensurePathBackSlashes); return new(context, span, isEnhanced: false, originalIndent, suppressLineDefaultAndHidden); } public static LinePragmaScope Enhanced(CodeRenderingContext context, SourceSpan span, int characterOffset, bool suppressLineDefaultAndHidden) { var writer = context.CodeWriter; var options = context.Options; // Are we allowed to write an enhanced line pragma? if (!options.UseEnhancedLinePragma) { var standardScope = Standard(context, span, suppressLineDefaultAndHidden); // If the caller requested an enhanced line directive, but we fell back to // a regular one, write out the extra padding and add a source mapping. writer.WritePadding(offset: 0, span, context); context.AddSourceMappingFor(span); return standardScope; } var (originalIndent, ensurePathBackSlashes) = WritePreamble(writer, options); writer.WriteEnhancedLineNumberDirective(span, characterOffset, ensurePathBackSlashes); context.AddSourceMappingFor(span, characterOffset); return new(context, span, isEnhanced: true, originalIndent, suppressLineDefaultAndHidden); } private static (int originalIndent, bool ensureBackSlashes) WritePreamble(CodeWriter writer, RazorCodeGenerationOptions options) { // Capture the current indent and reset to 0 for writing directives. var originalIndent = writer.CurrentIndent; writer.CurrentIndent = 0; // Ensure that we start on a new line. writer.EnsureNewLine(); if (!options.SuppressNullabilityEnforcement) { writer.WriteLine("#nullable restore"); } var ensurePathBackSlashes = options.RemapLinePragmaPathsOnWindows && PlatformInformation.IsWindows; return (originalIndent, ensurePathBackSlashes); } public void Dispose() { // Just return if this LinePragmaScope wasn't initialized. if (_context is null) { return; } var writer = _context.CodeWriter; var options = _context.Options; writer.EnsureNewLine(); // Always write at least 1 empty line to potentially separate code from pragmas. writer.WriteLine(); var linePragma = new LinePragma( _isEnhanced, _span.FilePath, _span.LineIndex, endLineIndex: writer.Location.LineIndex); _context.AddLinePragma(linePragma); if (!_suppressLineDefaultAndHidden) { writer .WriteLine("#line default") .WriteLine("#line hidden"); } if (!options.SuppressNullabilityEnforcement) { writer.WriteLine("#nullable disable"); } // Reset indentation. writer.CurrentIndent = _originalIndent; } } }