Skip to content

Commit

Permalink
Fix issue with MarkdownPipeline that was not threadsafe and initializ…
Browse files Browse the repository at this point in the history
…ation was deferred at parsing time instead of pipeline build time (issue #40)
  • Loading branch information
xoofx committed Jul 23, 2016
1 parent 800c81b commit 82af7ca
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 104 deletions.
2 changes: 1 addition & 1 deletion src/Markdig/Extensions/Emoji/EmojiParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public EmojiParser()
/// </summary>
public Dictionary<string, string> SmileyToEmoji { get; }

public override void Initialize(InlineProcessor processor)
public override void Initialize()
{
var firstChars = new HashSet<char>();
var textToMatch = new HashSet<string>();
Expand Down
3 changes: 2 additions & 1 deletion src/Markdig/Extensions/Tables/PipeTableExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ public void Setup(MarkdownPipelineBuilder pipeline)
{
pipeline.BlockParsers.Insert(0, new PipeTableBlockParser());
}
var lineBreakParser = pipeline.InlineParsers.FindExact<LineBreakInlineParser>();
if (!pipeline.InlineParsers.Contains<PipeTableParser>())
{
pipeline.InlineParsers.InsertBefore<EmphasisInlineParser>(new PipeTableParser(Options));
pipeline.InlineParsers.InsertBefore<EmphasisInlineParser>(new PipeTableParser(lineBreakParser, Options));
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/Markdig/Extensions/Tables/PipeTableParser.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.

using System;
using System.Collections.Generic;
using Markdig.Helpers;
using Markdig.Parsers;
Expand All @@ -18,14 +20,17 @@ namespace Markdig.Extensions.Tables
/// <seealso cref="IPostInlineProcessor" />
public class PipeTableParser : InlineParser, IPostInlineProcessor
{
private LineBreakInlineParser lineBreakParser;
private readonly LineBreakInlineParser lineBreakParser;

/// <summary>
/// Initializes a new instance of the <see cref="PipeTableParser" /> class.
/// </summary>
/// <param name="lineBreakParser">The linebreak parser to use</param>
/// <param name="options">The options.</param>
public PipeTableParser(PipeTableOptions options = null)
public PipeTableParser(LineBreakInlineParser lineBreakParser, PipeTableOptions options = null)
{
if (lineBreakParser == null) throw new ArgumentNullException(nameof(lineBreakParser));
this.lineBreakParser = lineBreakParser;
OpeningCharacters = new[] { '|', '\n' };
Options = options ?? new PipeTableOptions();
}
Expand All @@ -35,12 +40,6 @@ public PipeTableParser(PipeTableOptions options = null)
/// </summary>
public PipeTableOptions Options { get; }

public override void Initialize(InlineProcessor processor)
{
// We are using the linebreak parser
lineBreakParser = processor.Parsers.Find<LineBreakInlineParser>() ?? new LineBreakInlineParser();
}

public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
// Only working on Paragraph block
Expand Down
8 changes: 4 additions & 4 deletions src/Markdig/MarkdownPipelineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class MarkdownPipelineBuilder
public MarkdownPipelineBuilder()
{
// Add all default parsers
BlockParsers = new BlockParserList()
BlockParsers = new OrderedList<BlockParser>()
{
new ThematicBreakParser(),
new HeadingBlockParser(),
Expand All @@ -37,7 +37,7 @@ public MarkdownPipelineBuilder()
new ParagraphBlockParser(),
};

InlineParsers = new InlineParserList()
InlineParsers = new OrderedList<InlineParser>()
{
new HtmlEntityParser(),
new LinkInlineParser(),
Expand All @@ -56,12 +56,12 @@ public MarkdownPipelineBuilder()
/// <summary>
/// Gets the block parsers.
/// </summary>
public BlockParserList BlockParsers { get; private set; }
public OrderedList<BlockParser> BlockParsers { get; private set; }

/// <summary>
/// Gets the inline parsers.
/// </summary>
public InlineParserList InlineParsers { get; private set; }
public OrderedList<InlineParser> InlineParsers { get; private set; }

/// <summary>
/// Gets the register extensions.
Expand Down
7 changes: 0 additions & 7 deletions src/Markdig/Parsers/BlockParserList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ namespace Markdig.Parsers
/// <seealso cref="Markdig.Parsers.ParserList{Markdig.Parsers.BlockParser, Markdig.Parsers.BlockParserState}" />
public class BlockParserList : ParserList<BlockParser, BlockProcessor>
{
/// <summary>
/// Initializes a new instance of the <see cref="BlockParserList"/> class.
/// </summary>
public BlockParserList()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlockParserList"/> class.
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion src/Markdig/Parsers/BlockProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public BlockProcessor(StringBuilderCache stringBuilders, MarkdownDocument docume
Document = document;
document.IsOpen = true;
Parsers = parsers;
parsers.Initialize(this);
OpenedBlocks = new List<Block>();
NewBlocks = new Stack<Block>();
root = this;
Expand Down
3 changes: 1 addition & 2 deletions src/Markdig/Parsers/IMarkdownParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ public interface IMarkdownParser<in TProcessor>
/// <summary>
/// Initializes this parser with the specified parser processor.
/// </summary>
/// <param name="processor">The parser processor.</param>
void Initialize(TProcessor processor);
void Initialize();

/// <summary>
/// Gets the index of this parser in <see cref="BlockParserList"/> or <see cref="InlineParserList"/>.
Expand Down
20 changes: 5 additions & 15 deletions src/Markdig/Parsers/InlineParserList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,7 @@ namespace Markdig.Parsers
/// <seealso cref="Markdig.Parsers.ParserList{Markdig.Parsers.InlineParser, Markdig.Parsers.InlineParserState}" />
public class InlineParserList : ParserList<InlineParser, InlineProcessor>
{
public InlineParserList()
{
}

public InlineParserList(IEnumerable<InlineParser> parsers) : base(parsers)
{
}

/// <summary>
/// Gets the registered post inline processors.
/// </summary>
public IPostInlineProcessor[] PostInlineProcessors { get; private set; }

public override void Initialize(InlineProcessor initState)
{
// Prepare the list of post inline processors
var postInlineProcessors = new List<IPostInlineProcessor>();
Expand All @@ -37,8 +24,11 @@ public override void Initialize(InlineProcessor initState)
}
}
PostInlineProcessors = postInlineProcessors.ToArray();

base.Initialize(initState);
}

/// <summary>
/// Gets the registered post inline processors.
/// </summary>
public IPostInlineProcessor[] PostInlineProcessors { get; private set; }
}
}
1 change: 0 additions & 1 deletion src/Markdig/Parsers/InlineProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public InlineProcessor(StringBuilderCache stringBuilders, MarkdownDocument docum
Parsers = parsers;
PreciseSourceLocation = preciseSourcelocation;
lineOffsets = new List<StringLineGroup.LineOffset>();
Parsers.Initialize(this);
ParserStates = new object[Parsers.Count];
LiteralInlineParser = new LiteralInlineParser();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Markdig/Parsers/Inlines/EmphasisInlineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public bool HasEmphasisChar(char c)
/// </summary>
public CreateEmphasisInlineDelegate CreateEmphasisInline { get; set; }

public override void Initialize(InlineProcessor processor)
public override void Initialize()
{
OpeningCharacters = new char[EmphasisDescriptors.Count];

Expand Down
2 changes: 1 addition & 1 deletion src/Markdig/Parsers/ListBlockParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public ListBlockParser()
/// </summary>
public OrderedList<ListItemParser> ItemParsers { get; }

public override void Initialize(BlockProcessor processor)
public override void Initialize()
{
var tempMap = new Dictionary<char, ListItemParser>();

Expand Down
8 changes: 2 additions & 6 deletions src/Markdig/Parsers/MarkdownParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,10 @@ private MarkdownParser(string text, MarkdownPipeline pipeline)
document = new MarkdownDocument();

// Initialize the block parsers
var blockParserList = new BlockParserList();
blockParserList.AddRange(pipeline.BlockParsers);
blockProcessor = new BlockProcessor(stringBuilderCache, document, blockParserList);
blockProcessor = new BlockProcessor(stringBuilderCache, document, pipeline.BlockParsers);

// Initialize the inline parsers
var inlineParserList = new InlineParserList();
inlineParserList.AddRange(pipeline.InlineParsers);
inlineProcessor = new InlineProcessor(stringBuilderCache, document, inlineParserList, pipeline.PreciseSourceLocation)
inlineProcessor = new InlineProcessor(stringBuilderCache, document, pipeline.InlineParsers, pipeline.PreciseSourceLocation)
{
DebugLog = pipeline.DebugLog
};
Expand Down
3 changes: 1 addition & 2 deletions src/Markdig/Parsers/ParserBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public abstract class ParserBase<TProcessor> : IMarkdownParser<TProcessor>
/// <summary>
/// Initializes this parser with the specified parser processor.
/// </summary>
/// <param name="processor">The parser processor.</param>
public virtual void Initialize(TProcessor processor)
public virtual void Initialize()
{
}

Expand Down
103 changes: 49 additions & 54 deletions src/Markdig/Parsers/ParserList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,60 +16,10 @@ namespace Markdig.Parsers
/// <seealso cref="Markdig.Helpers.OrderedList{T}" />
public abstract class ParserList<T, TState> : OrderedList<T> where T : ParserBase<TState>
{
private CharacterMap<T[]> charMap;
private T[] globalParsers;
private readonly CharacterMap<T[]> charMap;
private readonly T[] globalParsers;

protected ParserList()
{
}

protected ParserList(IEnumerable<T> parsers) : base(parsers)
{
}

/// <summary>
/// Gets the list of global parsers (that don't have any opening characters defined)
/// </summary>
public T[] GlobalParsers => globalParsers;

/// <summary>
/// Gets all the opening characters defined.
/// </summary>
public char[] OpeningCharacters => charMap.OpeningCharacters;

/// <summary>
/// Gets the list of parsers valid for the specified opening character.
/// </summary>
/// <param name="openingChar">The opening character.</param>
/// <returns>A list of parsers valid for the specified opening character or null if no parsers registered.</returns>
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
public T[] GetParsersForOpeningCharacter(char openingChar)
{
return charMap[openingChar];
}

/// <summary>
/// Searches for an opening character from a registered parser in the specified string.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
/// <returns>Index position within the string of the first opening character found in the specified text; if not found, returns -1</returns>
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
public int IndexOfOpeningCharacter(string text, int start, int end)
{
return charMap.IndexOfOpeningCharacter(text, start, end);
}

/// <summary>
/// Initializes this instance with specified parser state.
/// </summary>
/// <param name="initState">State of the initialize.</param>
/// <exception cref="System.InvalidOperationException">
/// Unexpected null parser found
/// or
/// </exception>
public virtual void Initialize(TState initState)
protected ParserList(IEnumerable<T> parsersArg) : base(parsersArg)
{
var charCounter = new Dictionary<char, int>();
int globalCounter = 0;
Expand All @@ -82,7 +32,7 @@ public virtual void Initialize(TState initState)
throw new InvalidOperationException("Unexpected null parser found");
}

parser.Initialize(initState);
parser.Initialize();
parser.Index = i;
if (parser.OpeningCharacters != null && parser.OpeningCharacters.Length != 0)
{
Expand Down Expand Up @@ -134,5 +84,50 @@ public virtual void Initialize(TState initState)

charMap = new CharacterMap<T[]>(tempCharMap);
}

/// <summary>
/// Gets the list of global parsers (that don't have any opening characters defined)
/// </summary>
public T[] GlobalParsers => globalParsers;

/// <summary>
/// Gets all the opening characters defined.
/// </summary>
public char[] OpeningCharacters => charMap.OpeningCharacters;

/// <summary>
/// Gets the list of parsers valid for the specified opening character.
/// </summary>
/// <param name="openingChar">The opening character.</param>
/// <returns>A list of parsers valid for the specified opening character or null if no parsers registered.</returns>
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
public T[] GetParsersForOpeningCharacter(char openingChar)
{
return charMap[openingChar];
}

/// <summary>
/// Searches for an opening character from a registered parser in the specified string.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
/// <returns>Index position within the string of the first opening character found in the specified text; if not found, returns -1</returns>
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
public int IndexOfOpeningCharacter(string text, int start, int end)
{
return charMap.IndexOfOpeningCharacter(text, start, end);
}

/// <summary>
/// Initializes this instance with specified parser state.
/// </summary>
/// <exception cref="System.InvalidOperationException">
/// Unexpected null parser found
/// or
/// </exception>
private void Initialize()
{
}
}
}

0 comments on commit 82af7ca

Please sign in to comment.