From a2e74788e00cf3842d95bb77e4eb9af94f1f171c Mon Sep 17 00:00:00 2001 From: forest93 Date: Thu, 17 Aug 2017 23:23:31 +0800 Subject: [PATCH] Extract TagAttributeCollection with TrailingWhitespace property. This also fixes the bug that TrailingWhitespace and ClosingTagTrailingWhitespace are mistakenly using the same field. --- MwParserFromScratch/Nodes/Inline.cs | 30 ++++---------- .../Nodes/TagAttributeCollection.cs | 39 +++++++++++++++++++ MwParserFromScratch/ParserCore.Expandable.cs | 2 +- UnitTestProject1/Utility.cs | 17 +++++++- 4 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 MwParserFromScratch/Nodes/TagAttributeCollection.cs diff --git a/MwParserFromScratch/Nodes/Inline.cs b/MwParserFromScratch/Nodes/Inline.cs index 18a3de3..f4d9ac3 100644 --- a/MwParserFromScratch/Nodes/Inline.cs +++ b/MwParserFromScratch/Nodes/Inline.cs @@ -484,7 +484,8 @@ public enum TagStyle /// public abstract class TagNode : InlineNode { - private string _TrailingWhitespace; + + private string _ClosingTagTrailingWhitespace; private TagStyle _TagStyle; public TagNode() : this(null) @@ -495,7 +496,7 @@ public TagNode() : this(null) public TagNode(string name) { Name = name; - Attributes = new NodeCollection(this); + Attributes = new TagAttributeCollection(this); } /// @@ -524,35 +525,21 @@ public virtual TagStyle TagStyle } } - /// - /// The trailing whitespace for the opening tag, before > or /> . - /// - /// The string contains non-white-space characters. - public string TrailingWhitespace - { - get { return _TrailingWhitespace; } - set - { - Utility.AssertNullOrWhiteSpace(value); - _TrailingWhitespace = value; - } - } - /// /// The trailing whitespace for the closing tag. /// /// The string contains non-white-space characters. public string ClosingTagTrailingWhitespace { - get { return _TrailingWhitespace; } + get { return _ClosingTagTrailingWhitespace; } set { Utility.AssertNullOrWhiteSpace(value); - _TrailingWhitespace = value; + _ClosingTagTrailingWhitespace = value; } } - public NodeCollection Attributes { get; } + public TagAttributeCollection Attributes { get; } protected abstract string GetContentString(); @@ -573,8 +560,7 @@ public override string ToString() { var sb = new StringBuilder("<"); sb.Append(Name); - sb.Append(string.Join(null, Attributes)); - sb.Append(TrailingWhitespace); + sb.Append(Attributes); switch (TagStyle) { case TagStyle.Normal: @@ -641,7 +627,6 @@ protected override Node CloneCore() Name = Name, ClosingTagName = ClosingTagName, Content = Content, - TrailingWhitespace = TrailingWhitespace, ClosingTagTrailingWhitespace = ClosingTagTrailingWhitespace, }; n.Attributes.Add(Attributes); @@ -721,7 +706,6 @@ protected override Node CloneCore() Name = Name, ClosingTagName = ClosingTagName, Content = Content, - TrailingWhitespace = TrailingWhitespace, ClosingTagTrailingWhitespace = ClosingTagTrailingWhitespace, }; n.Attributes.Add(Attributes); diff --git a/MwParserFromScratch/Nodes/TagAttributeCollection.cs b/MwParserFromScratch/Nodes/TagAttributeCollection.cs new file mode 100644 index 0000000..b0eaf41 --- /dev/null +++ b/MwParserFromScratch/Nodes/TagAttributeCollection.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MwParserFromScratch.Nodes +{ + public class TagAttributeCollection : NodeCollection + { + private string _TrailingWhitespace; + + internal TagAttributeCollection(Node owner) : base(owner) + { + } + + /// + /// The trailing whitespace after the last tag attribute. + /// + /// The string contains non-white-space characters. + public string TrailingWhitespace + { + get { return _TrailingWhitespace; } + set + { + Utility.AssertNullOrWhiteSpace(value); + _TrailingWhitespace = value; + } + } + + /// + public override string ToString() + { + var sb = new StringBuilder(); + foreach (var attr in this) + sb.Append(attr); + sb.Append(_TrailingWhitespace); + return sb.ToString(); + } + } +} diff --git a/MwParserFromScratch/ParserCore.Expandable.cs b/MwParserFromScratch/ParserCore.Expandable.cs index 8ec50c8..9bd9ff0 100644 --- a/MwParserFromScratch/ParserCore.Expandable.cs +++ b/MwParserFromScratch/ParserCore.Expandable.cs @@ -214,7 +214,7 @@ private TagNode ParseTag() ParseSuccessful(attr); node.Attributes.Add(attr); } - node.TrailingWhitespace = ws; + node.Attributes.TrailingWhitespace = ws; if (rbracket == "/>") { node.TagStyle = TagStyle.SelfClosing; diff --git a/UnitTestProject1/Utility.cs b/UnitTestProject1/Utility.cs index bfeb5da..1c957d7 100644 --- a/UnitTestProject1/Utility.cs +++ b/UnitTestProject1/Utility.cs @@ -15,6 +15,8 @@ internal static class Utility { private static readonly Dictionary> dumpHandlers = new Dictionary>(); + private static readonly WikitextParserOptions DefaultParserOptions = new WikitextParserOptions(); + private static void RegisterDumpHandler(Func handler) where T : Node { dumpHandlers.Add(typeof(T), n => handler((T) n)); @@ -84,7 +86,7 @@ static Utility() var sb = new StringBuilder("<"); sb.Append(n.Name); sb.Append(string.Join(null, n.Attributes.Select(Dump))); - sb.Append(n.TrailingWhitespace); + sb.Append(n.Attributes.TrailingWhitespace); switch (n.TagStyle) { case TagStyle.Normal: @@ -147,8 +149,19 @@ public static Wikitext ParseWikitext(string text) /// 1. Whether the parsed AST can be converted back to the same wikitext as input. /// 2. Whether the parsed AST is correct. /// - public static Wikitext ParseAndAssert(string text, string expectedDump, WikitextParserOptions options = null) + public static Wikitext ParseAndAssert(string text, string expectedDump) + { + return ParseAndAssert(text, expectedDump, DefaultParserOptions); + } + + /// + /// Parses wikitext, and asserts + /// 1. Whether the parsed AST can be converted back to the same wikitext as input. + /// 2. Whether the parsed AST is correct. + /// + public static Wikitext ParseAndAssert(string text, string expectedDump, WikitextParserOptions options) { + if (options == null) throw new ArgumentNullException(nameof(options)); var parser = new WikitextParser {Options = options}; var root = parser.Parse(text); var parsedText = root.ToString();