Skip to content

Commit 9e67d40

Browse files
Change Build(Enhanced)LinePragma extensions to target CodeRenderingContext
Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `BuildLinePragma` and `BuildEnhancedLinePragma` extension methods target `CodeWriter` and also take a `CodeRenderingContext`, we can change them can target `CodeRenderingContext`. In addition, this change changes the type that's returned to readonly ref struct. This requires a bit of adjustment to some of the calling code.
1 parent f7e21c8 commit 9e67d40

13 files changed

+278
-283
lines changed

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeRenderingContextExtensions.cs

Lines changed: 149 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Immutable;
66
using System.Diagnostics;
77
using Microsoft.AspNetCore.Razor.Language.Intermediate;
8+
using Microsoft.AspNetCore.Razor.Utilities;
89
using static Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriterExtensions;
910

1011
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration;
@@ -29,11 +30,12 @@ public static CSharpCodeWritingScope BuildNamespace(this CodeRenderingContext co
2930
else
3031
{
3132
writer.WriteLine();
32-
using (writer.BuildEnhancedLinePragma(span, context))
33+
using (context.BuildEnhancedLinePragma(span))
3334
{
3435
writer.WriteLine(name);
3536
}
3637
}
38+
3739
return new CSharpCodeWritingScope(writer);
3840
}
3941

@@ -81,7 +83,7 @@ public static CSharpCodeWritingScope BuildClassDeclaration(
8183

8284
if (typeParameter.ParameterNameSource is { } source)
8385
{
84-
WriteWithPragma(writer, typeParameter.ParameterName, context, source);
86+
WriteWithPragma(context, typeParameter.ParameterName, source);
8587
}
8688
else
8789
{
@@ -137,7 +139,7 @@ public static CSharpCodeWritingScope BuildClassDeclaration(
137139
if (typeParameter.ConstraintsSource is { } source)
138140
{
139141
Debug.Assert(context != null);
140-
WriteWithPragma(writer, constraint, context, source);
142+
WriteWithPragma(context, constraint, source);
141143
}
142144
else
143145
{
@@ -167,27 +169,29 @@ void WriteToken(IntermediateToken token)
167169
{
168170
if (token.Source is { } source)
169171
{
170-
WriteWithPragma(writer, token.Content, context, source);
172+
WriteWithPragma(context, token.Content, source);
171173
}
172174
else
173175
{
174176
writer.Write(token.Content);
175177
}
176178
}
177179

178-
static void WriteWithPragma(CodeWriter writer, string content, CodeRenderingContext context, SourceSpan source)
180+
static void WriteWithPragma(CodeRenderingContext context, string content, SourceSpan source)
179181
{
182+
var writer = context.CodeWriter;
183+
180184
if (context.Options.DesignTime)
181185
{
182-
using (writer.BuildLinePragma(source, context))
186+
using (context.BuildLinePragma(source))
183187
{
184188
context.AddSourceMappingFor(source);
185189
writer.Write(content);
186190
}
187191
}
188192
else
189193
{
190-
using (writer.BuildEnhancedLinePragma(source, context))
194+
using (context.BuildEnhancedLinePragma(source))
191195
{
192196
writer.Write(content);
193197
}
@@ -262,17 +266,152 @@ private static void WritePropertyDeclarationPreamble(
262266

263267
static void WriteToken(CodeRenderingContext context, string content, SourceSpan? span)
264268
{
269+
var writer = context.CodeWriter;
270+
265271
if (span is not null && context.Options.DesignTime == false)
266272
{
267-
using (context.CodeWriter.BuildEnhancedLinePragma(span, context))
273+
using (context.BuildEnhancedLinePragma(span))
268274
{
269-
context.CodeWriter.Write(content);
275+
writer.Write(content);
270276
}
271277
}
272278
else
273279
{
274-
context.CodeWriter.Write(content);
280+
writer.Write(content);
281+
}
282+
}
283+
}
284+
285+
public static LinePragmaScope BuildLinePragma(
286+
this CodeRenderingContext context,
287+
SourceSpan? span,
288+
bool suppressLineDefaultAndHidden = false)
289+
{
290+
if (string.IsNullOrEmpty(span?.FilePath))
291+
{
292+
// Can't build a valid line pragma without a file path.
293+
return default;
294+
}
295+
296+
return new LinePragmaScope(context, span.Value, 0, useEnhancedLinePragma: false, suppressLineDefaultAndHidden);
297+
}
298+
299+
public static LinePragmaScope BuildEnhancedLinePragma(
300+
this CodeRenderingContext context,
301+
SourceSpan? span,
302+
int characterOffset = 0,
303+
bool suppressLineDefaultAndHidden = false)
304+
{
305+
if (string.IsNullOrEmpty(span?.FilePath))
306+
{
307+
// Can't build a valid line pragma without a file path.
308+
return default;
309+
}
310+
311+
return new LinePragmaScope(context, span.Value, characterOffset, useEnhancedLinePragma: true, suppressLineDefaultAndHidden);
312+
}
313+
314+
public readonly ref struct LinePragmaScope
315+
{
316+
private readonly CodeRenderingContext _context;
317+
private readonly int _startIndent;
318+
private readonly int _startLineIndex;
319+
private readonly SourceSpan _span;
320+
private readonly bool _suppressLineDefaultAndHidden;
321+
322+
public LinePragmaScope(
323+
CodeRenderingContext context,
324+
SourceSpan span,
325+
int characterOffset,
326+
bool useEnhancedLinePragma = false,
327+
bool suppressLineDefaultAndHidden = false)
328+
{
329+
Debug.Assert(context.Options.DesignTime || useEnhancedLinePragma, "Runtime generation should only use enhanced line pragmas");
330+
331+
_context = context;
332+
_suppressLineDefaultAndHidden = suppressLineDefaultAndHidden;
333+
_span = span;
334+
335+
var writer = context.CodeWriter;
336+
_startIndent = writer.CurrentIndent;
337+
writer.CurrentIndent = 0;
338+
339+
var endsWithNewline = writer.LastChar is '\n';
340+
if (!endsWithNewline)
341+
{
342+
writer.WriteLine();
343+
}
344+
345+
if (!_context.Options.SuppressNullabilityEnforcement)
346+
{
347+
writer.WriteLine("#nullable restore");
348+
}
349+
350+
var ensurePathBackslashes = context.Options.RemapLinePragmaPathsOnWindows && PlatformInformation.IsWindows;
351+
if (useEnhancedLinePragma && _context.Options.UseEnhancedLinePragma)
352+
{
353+
writer.WriteEnhancedLineNumberDirective(span, characterOffset, ensurePathBackslashes);
354+
}
355+
else
356+
{
357+
writer.WriteLineNumberDirective(span, ensurePathBackslashes);
358+
}
359+
360+
// Capture the line index after writing the #line directive.
361+
_startLineIndex = writer.Location.LineIndex;
362+
363+
if (useEnhancedLinePragma)
364+
{
365+
// If the caller requested an enhanced line directive, but we fell back to regular ones, write out the extra padding that is required
366+
if (!_context.Options.UseEnhancedLinePragma)
367+
{
368+
writer.WritePadding(0, span, context);
369+
characterOffset = 0;
370+
}
371+
372+
context.AddSourceMappingFor(span, characterOffset);
373+
}
374+
}
375+
376+
public void Dispose()
377+
{
378+
if (_context is null)
379+
{
380+
return;
381+
}
382+
383+
var writer = _context.CodeWriter;
384+
385+
// Need to add an additional line at the end IF there wasn't one already written.
386+
// This is needed to work with the C# editor's handling of #line ...
387+
var endsWithNewline = writer.LastChar is '\n';
388+
389+
// Always write at least 1 empty line to potentially separate code from pragmas.
390+
writer.WriteLine();
391+
392+
// Check if the previous empty line wasn't enough to separate code from pragmas.
393+
if (!endsWithNewline)
394+
{
395+
writer.WriteLine();
275396
}
397+
398+
var lineCount = writer.Location.LineIndex - _startLineIndex;
399+
var linePragma = new LinePragma(_span.LineIndex, lineCount, _span.FilePath, _span.EndCharacterIndex, _span.EndCharacterIndex, _span.CharacterIndex);
400+
_context.AddLinePragma(linePragma);
401+
402+
if (!_suppressLineDefaultAndHidden)
403+
{
404+
writer
405+
.WriteLine("#line default")
406+
.WriteLine("#line hidden");
407+
}
408+
409+
if (!_context.Options.SuppressNullabilityEnforcement)
410+
{
411+
writer.WriteLine("#nullable disable");
412+
}
413+
414+
writer.CurrentIndent = _startIndent;
276415
}
277416
}
278417
}

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/CodeGeneration/CodeWriterExtensions.cs

Lines changed: 0 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
using System.Diagnostics;
1010
using System.Globalization;
1111
using System.Linq;
12-
using Microsoft.AspNetCore.Razor.Language.Intermediate;
13-
using Microsoft.AspNetCore.Razor.Utilities;
1412

1513
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration;
1614

@@ -417,28 +415,6 @@ public static CSharpCodeWritingScope BuildMethodDeclaration(
417415
return new CSharpCodeWritingScope(writer);
418416
}
419417

420-
public static IDisposable BuildLinePragma(this CodeWriter writer, SourceSpan? span, CodeRenderingContext context, bool suppressLineDefaultAndHidden = false)
421-
{
422-
if (string.IsNullOrEmpty(span?.FilePath))
423-
{
424-
// Can't build a valid line pragma without a file path.
425-
return NullDisposable.Default;
426-
}
427-
428-
return new LinePragmaWriter(writer, span.Value, context, 0, useEnhancedLinePragma: false, suppressLineDefaultAndHidden);
429-
}
430-
431-
public static IDisposable BuildEnhancedLinePragma(this CodeWriter writer, SourceSpan? span, CodeRenderingContext context, int characterOffset = 0, bool suppressLineDefaultAndHidden = false)
432-
{
433-
if (string.IsNullOrEmpty(span?.FilePath))
434-
{
435-
// Can't build a valid line pragma without a file path.
436-
return NullDisposable.Default;
437-
}
438-
439-
return new LinePragmaWriter(writer, span.Value, context, characterOffset, useEnhancedLinePragma: true, suppressLineDefaultAndHidden);
440-
}
441-
442418
private static void WriteVerbatimStringLiteral(CodeWriter writer, ReadOnlyMemory<char> literal)
443419
{
444420
writer.Write("@\"");
@@ -595,121 +571,4 @@ _writer.LastChar is char ch &&
595571
}
596572
}
597573
}
598-
599-
private class LinePragmaWriter : IDisposable
600-
{
601-
private readonly CodeWriter _writer;
602-
private readonly CodeRenderingContext _context;
603-
private readonly int _startIndent;
604-
private readonly int _startLineIndex;
605-
private readonly SourceSpan _span;
606-
private readonly bool _suppressLineDefaultAndHidden;
607-
608-
public LinePragmaWriter(
609-
CodeWriter writer,
610-
SourceSpan span,
611-
CodeRenderingContext context,
612-
int characterOffset,
613-
bool useEnhancedLinePragma = false,
614-
bool suppressLineDefaultAndHidden = false)
615-
{
616-
Debug.Assert(context.Options.DesignTime || useEnhancedLinePragma, "Runtime generation should only use enhanced line pragmas");
617-
618-
if (writer == null)
619-
{
620-
throw new ArgumentNullException(nameof(writer));
621-
}
622-
623-
_writer = writer;
624-
_context = context;
625-
_suppressLineDefaultAndHidden = suppressLineDefaultAndHidden;
626-
_startIndent = _writer.CurrentIndent;
627-
_writer.CurrentIndent = 0;
628-
_span = span;
629-
630-
var endsWithNewline = _writer.LastChar is '\n';
631-
if (!endsWithNewline)
632-
{
633-
_writer.WriteLine();
634-
}
635-
636-
if (!_context.Options.SuppressNullabilityEnforcement)
637-
{
638-
_writer.WriteLine("#nullable restore");
639-
}
640-
641-
var ensurePathBackslashes = context.Options.RemapLinePragmaPathsOnWindows && PlatformInformation.IsWindows;
642-
if (useEnhancedLinePragma && _context.Options.UseEnhancedLinePragma)
643-
{
644-
WriteEnhancedLineNumberDirective(writer, span, characterOffset, ensurePathBackslashes);
645-
}
646-
else
647-
{
648-
WriteLineNumberDirective(writer, span, ensurePathBackslashes);
649-
}
650-
651-
// Capture the line index after writing the #line directive.
652-
_startLineIndex = writer.Location.LineIndex;
653-
654-
if (useEnhancedLinePragma)
655-
{
656-
// If the caller requested an enhanced line directive, but we fell back to regular ones, write out the extra padding that is required
657-
if (!_context.Options.UseEnhancedLinePragma)
658-
{
659-
context.CodeWriter.WritePadding(0, span, context);
660-
characterOffset = 0;
661-
}
662-
663-
context.AddSourceMappingFor(span, characterOffset);
664-
}
665-
}
666-
667-
public void Dispose()
668-
{
669-
// Need to add an additional line at the end IF there wasn't one already written.
670-
// This is needed to work with the C# editor's handling of #line ...
671-
var endsWithNewline = _writer.LastChar is '\n';
672-
673-
// Always write at least 1 empty line to potentially separate code from pragmas.
674-
_writer.WriteLine();
675-
676-
// Check if the previous empty line wasn't enough to separate code from pragmas.
677-
if (!endsWithNewline)
678-
{
679-
_writer.WriteLine();
680-
}
681-
682-
var lineCount = _writer.Location.LineIndex - _startLineIndex;
683-
var linePragma = new LinePragma(_span.LineIndex, lineCount, _span.FilePath, _span.EndCharacterIndex, _span.EndCharacterIndex, _span.CharacterIndex);
684-
_context.AddLinePragma(linePragma);
685-
686-
if (!_suppressLineDefaultAndHidden)
687-
{
688-
_writer
689-
.WriteLine("#line default")
690-
.WriteLine("#line hidden");
691-
}
692-
693-
if (!_context.Options.SuppressNullabilityEnforcement)
694-
{
695-
_writer.WriteLine("#nullable disable");
696-
}
697-
698-
_writer.CurrentIndent = _startIndent;
699-
700-
}
701-
}
702-
703-
private class NullDisposable : IDisposable
704-
{
705-
public static readonly NullDisposable Default = new NullDisposable();
706-
707-
private NullDisposable()
708-
{
709-
}
710-
711-
public void Dispose()
712-
{
713-
}
714-
}
715574
}

0 commit comments

Comments
 (0)