Lazily allocate ProcessInlinesBegin/End delegates on Blocks (#906)

This commit is contained in:
Miha Zupan
2025-10-21 08:37:02 +02:00
committed by GitHub
parent d6e88f16f7
commit bcbd8e47ac
7 changed files with 32 additions and 18 deletions

View File

@@ -73,8 +73,6 @@ public class AbbreviationParser : BlockParser
private void DocumentOnProcessInlinesBegin(InlineProcessor inlineProcessor, Inline? inline)
{
inlineProcessor.Document.ProcessInlinesBegin -= DocumentOnProcessInlinesBegin;
var abbreviations = inlineProcessor.Document.GetAbbreviations();
// Should not happen, but another extension could decide to remove them, so...
if (abbreviations is null)

View File

@@ -101,7 +101,6 @@ public class AutoIdentifierExtension : IMarkdownExtension
private void DocumentOnProcessInlinesBegin(InlineProcessor processor, Inline? inline)
{
var doc = processor.Document;
doc.ProcessInlinesBegin -= _processInlinesBegin;
var dictionary = (Dictionary<string, HeadingLinkReferenceDefinition>)doc.GetData(this)!;
foreach (var keyPair in dictionary)
{

View File

@@ -134,9 +134,6 @@ public class FootnoteParser : BlockParser
/// <param name="inline">The inline.</param>
private void Document_ProcessInlinesEnd(InlineProcessor state, Inline? inline)
{
// Unregister
state.Document.ProcessInlinesEnd -= Document_ProcessInlinesEnd;
var footnotes = (FootnoteGroup)state.Document.GetData(DocumentKey)!;
// Remove the footnotes from the document and readd them at the end
state.Document.Remove(footnotes);

View File

@@ -204,8 +204,6 @@ public class SmartyPantsInlineParser : InlineParser, IPostInlineProcessor
private void BlockOnProcessInlinesEnd(InlineProcessor processor, Inline? inline)
{
processor.Block!.ProcessInlinesEnd -= BlockOnProcessInlinesEnd;
var pants = (ListSmartyPants) processor.ParserStates[Index];
var openers = new Stack<Opener>(4);

View File

@@ -497,13 +497,10 @@ public class PipeTableParser : InlineParser, IPostInlineProcessor
ContainerBlock parent = leadingParagraph.Parent!;
ProcessInlineDelegate insertTableDelegate = null!;
insertTableDelegate = (processor, _) =>
parent.ProcessInlinesEnd += (_, _) =>
{
parent.ProcessInlinesEnd -= insertTableDelegate;
parent.Insert(parent.IndexOf(leadingParagraph) + 1, table);
};
parent.ProcessInlinesEnd += insertTableDelegate;
}
else
{

View File

@@ -85,12 +85,12 @@ public abstract class RendererBase : IMarkdownRenderer
public bool IsLastInContainer { get; private set; }
/// <summary>
/// Occurs when before writing an object.
/// Occurs before writing an object.
/// </summary>
public event Action<IMarkdownRenderer, MarkdownObject>? ObjectWriteBefore;
/// <summary>
/// Occurs when after writing an object.
/// Occurs after writing an object.
/// </summary>
public event Action<IMarkdownRenderer, MarkdownObject>? ObjectWriteAfter;

View File

@@ -92,12 +92,20 @@ public abstract class Block : MarkdownObject, IBlock
/// <summary>
/// Occurs when the process of inlines begin.
/// </summary>
public event ProcessInlineDelegate? ProcessInlinesBegin;
public event ProcessInlineDelegate? ProcessInlinesBegin
{
add => Trivia.ProcessInlinesBegin += value;
remove => _trivia?.ProcessInlinesBegin -= value;
}
/// <summary>
/// Occurs when the process of inlines ends for this instance.
/// </summary>
public event ProcessInlineDelegate? ProcessInlinesEnd;
public event ProcessInlineDelegate? ProcessInlinesEnd
{
add => Trivia.ProcessInlinesEnd += value;
remove => _trivia?.ProcessInlinesEnd -= value;
}
/// <summary>
/// Called when the process of inlines begin.
@@ -105,7 +113,13 @@ public abstract class Block : MarkdownObject, IBlock
/// <param name="state">The inline parser state.</param>
internal void OnProcessInlinesBegin(InlineProcessor state)
{
ProcessInlinesBegin?.Invoke(state, null);
if (_trivia is BlockTriviaProperties trivia)
{
trivia.ProcessInlinesBegin?.Invoke(state, null);
// Not exactly standard 'event' behavior, but these aren't expected to be called more than once.
_trivia.ProcessInlinesBegin = null;
}
}
/// <summary>
@@ -114,7 +128,13 @@ public abstract class Block : MarkdownObject, IBlock
/// <param name="state">The inline parser state.</param>
internal void OnProcessInlinesEnd(InlineProcessor state)
{
ProcessInlinesEnd?.Invoke(state, null);
if (_trivia is BlockTriviaProperties trivia)
{
trivia.ProcessInlinesEnd?.Invoke(state, null);
// Not exactly standard 'event' behavior, but these aren't expected to be called more than once.
_trivia.ProcessInlinesEnd = null;
}
}
public void UpdateSpanEnd(int spanEnd)
@@ -156,6 +176,11 @@ public abstract class Block : MarkdownObject, IBlock
// Used by derived types to store their own TriviaProperties
public object? DerivedTriviaSlot;
// These callbacks are set on a tiny subset of blocks (usually only the main MarkdownDocument),
// so we store them in a lazily-allocated container to save memory for the majority of blocks.
public ProcessInlineDelegate? ProcessInlinesBegin;
public ProcessInlineDelegate? ProcessInlinesEnd;
public StringSlice TriviaBefore;
public StringSlice TriviaAfter;
public List<StringSlice>? LinesBefore;