From 185779b2b5f16df97160923007edff84ca5a9b40 Mon Sep 17 00:00:00 2001 From: Simon Lindgren Date: Thu, 5 Jul 2012 17:28:43 +0200 Subject: [PATCH] [Utils] Add more error checks to CompositeFormatStringParser. --- .../CompositeFormatStringParserTests.cs | 39 +++++++++++++ .../CompositeFormatStringParser.cs | 56 +++++++++++++------ .../IFormatStringError.cs | 5 ++ 3 files changed, 83 insertions(+), 17 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/Utils/CompositeFormatStringParser/CompositeFormatStringParserTests.cs b/ICSharpCode.NRefactory.Tests/Utils/CompositeFormatStringParser/CompositeFormatStringParserTests.cs index 0896009190..4113dec53d 100644 --- a/ICSharpCode.NRefactory.Tests/Utils/CompositeFormatStringParser/CompositeFormatStringParserTests.cs +++ b/ICSharpCode.NRefactory.Tests/Utils/CompositeFormatStringParser/CompositeFormatStringParserTests.cs @@ -46,6 +46,9 @@ namespace ICSharpCode.NRefactory.Utils Console.WriteLine("Actual format segments:"); foreach (var item in actualFormatSegments) { Console.WriteLine(item.ToString()); + foreach (var error in item.Errors) { + Console.WriteLine("\t{0}", error); + } } Assert.AreEqual(expectedFormatSegments, actualFormatSegments); @@ -264,6 +267,42 @@ namespace ICSharpCode.NRefactory.Utils ErrorTest(errors[1], "", "0", 2, 2); ErrorTest(errors[2], "", "}", 3, 3); } + + [Test] + public void InvalidNumberFormatInIndex() + { + var segments = ParseTest("{0 and then some invalid text}", + new FormatItem(0) { StartLocation = 0, EndLocation = 30 }); + var errors = SegmentTest(1, segments.First()); + ErrorTest(errors[0], "0 and then some invalid text", "0", 1, 29); + } + + [Test] + public void InvalidNumberFormatTextBeforeDigitsInIndex() + { + var segments = ParseTest("{Some text 55}", + new FormatItem(0) { StartLocation = 0, EndLocation = 14 }); + var errors = SegmentTest(1, segments.First()); + ErrorTest(errors[0], "Some text 55", "0", 1, 13); + } + + [Test] + public void InvalidNumberFormatInAlignment() + { + var segments = ParseTest("{0, 100 and then some invalid text}", + new FormatItem(0, 100) { StartLocation = 0, EndLocation = 35 }); + var errors = SegmentTest(1, segments.First()); + ErrorTest(errors[0], " 100 and then some invalid text", "100", 3, 34); + } + + [Test] + public void InvalidNumberFormatTextBeforeDigitsInAlignment() + { + var segments = ParseTest("{0, Some text 55}", + new FormatItem(0, 0) { StartLocation = 0, EndLocation = 17 }); + var errors = SegmentTest(1, segments.First()); + ErrorTest(errors[0], " Some text 55", "0", 3, 16); + } } } diff --git a/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/CompositeFormatStringParser.cs b/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/CompositeFormatStringParser.cs index bc3bb896cd..31c63b310b 100644 --- a/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/CompositeFormatStringParser.cs +++ b/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/CompositeFormatStringParser.cs @@ -127,18 +127,18 @@ namespace ICSharpCode.NRefactory.Utils int ParseIndex (string format, ref int i) { - int? maybeIndex = GetNumber (format, ref i); - if (maybeIndex.HasValue) { - return maybeIndex.Value; + int parsedCharacters; + int? maybeIndex = GetAndCheckNumber (format, ",:}", ref i, i, out parsedCharacters); + if (parsedCharacters == 0) { + AddError (new DefaultFormatStringError { + StartLocation = i, + EndLocation = i, + Message = "Missing index", + OriginalText = "", + SuggestedReplacementText = "0" + }); } - AddError (new DefaultFormatStringError { - StartLocation = i, - EndLocation = i, - Message = "Missing index", - OriginalText = "", - SuggestedReplacementText = "0" - }); - return 0; + return maybeIndex ?? 0; } int? ParseAlignment(string format, ref int i, int length) @@ -153,13 +153,18 @@ namespace ICSharpCode.NRefactory.Utils var message = string.Format ("Unexpected end of string: '{0}'", originalText); AddMissingEndBraceError(alignmentBegin, i, message, originalText); } else { - int? number = GetNumber(format, ref i); - if (number.HasValue) { - return number; - } else { - AddInvalidNumberFormatError(i, "", "0"); - return 0; + int parsedCharacters; + var number = GetAndCheckNumber(format, ",:}", ref i, alignmentBegin + 1, out parsedCharacters); + if (parsedCharacters == 0) { + AddError (new DefaultFormatStringError { + StartLocation = i, + EndLocation = i, + Message = "Missing alignment", + OriginalText = "", + SuggestedReplacementText = "0" + }); } + return number ?? 0; } } return null; @@ -211,6 +216,9 @@ namespace ICSharpCode.NRefactory.Utils int? GetNumber (string format, ref int index) { + if (format.Length == 0) { + return null; + } int sum = 0; int i = index; bool positive = format [i] != '-'; @@ -228,6 +236,20 @@ namespace ICSharpCode.NRefactory.Utils return positive ? sum : -sum; } + int? GetAndCheckNumber(string format, string delimiters, ref int index, int numberFieldStart, out int parsedCharacters) + { + var numberText = GetUntil(format, delimiters, ref index); + parsedCharacters = numberText.Length; + int digitCount = 0; + int? number = GetNumber(numberText, ref digitCount); + if (digitCount != parsedCharacters) { + // Not the entire number field could be parsed + var suggestedNumber = (number ?? 0).ToString (); + AddInvalidNumberFormatError(numberFieldStart, format.Substring(numberFieldStart, index - numberFieldStart), suggestedNumber); + } + return number; + } + public static string UnEscape (string unEscaped) { return unEscaped.Replace ("{{", "{").Replace ("}}", "}"); diff --git a/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/IFormatStringError.cs b/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/IFormatStringError.cs index e01b97dfa3..71cfb7f4e8 100644 --- a/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/IFormatStringError.cs +++ b/ICSharpCode.NRefactory/Utils/CompositeFormatStringParser/IFormatStringError.cs @@ -59,5 +59,10 @@ namespace ICSharpCode.NRefactory.Utils public string SuggestedReplacementText { get; set; } #endregion + + public override string ToString () + { + return string.Format ("[DefaultFormatStringError: StartLocation={0}, EndLocation={1}, Message={2}, OriginalText={3}, SuggestedReplacementText={4}]", StartLocation, EndLocation, Message, OriginalText, SuggestedReplacementText); + } } }