Skip to content

Commit

Permalink
rand string from regex: fix wrongly raising errors
Browse files Browse the repository at this point in the history
  • Loading branch information
molsonkiko committed Aug 24, 2024
1 parent 277e35a commit 9740f63
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 55 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Since v7.0, holding down `Enter` in a multiline textbox (like the [tree viewer query box](/docs/README.md#remespath)) only adds one newline when the key is lifted.
- Maybe use pre-7.1 (dictionary-based rather than indicator-based) [selection remembering](/docs/README.md#working-with-selections) for Notepad++ 8.5.5 and earlier? Indicators are risky with those older NPP's because of the lack of `NPPM_ALLOCATEINDICATOR`.

## [8.2.0] - (UNRELEASED) YYYY-MM-DD

### Added

### Changed

### Fixed

1. Fix issue where [random string from regex](/docs/README.md#random-strings-from-regex-added-in-v81) would incorrectly flag some valid regular expressions (e.g. `(?-i)(?:xy{1,2}){,2}`) as having two consecutive quantifiers.

## [8.1.0] - 2024-08-23

### Added
Expand Down
4 changes: 2 additions & 2 deletions JsonToolsNppPlugin/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@
// Build Number
// Revision
//
[assembly: AssemblyVersion("8.1.0.0")]
[assembly: AssemblyFileVersion("8.1.0.0")]
[assembly: AssemblyVersion("8.1.0.1")]
[assembly: AssemblyFileVersion("8.1.0.1")]
17 changes: 13 additions & 4 deletions JsonToolsNppPlugin/Tests/RandomStringFromRegexTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public static bool Test()
(@"^(?:(fo|ba) ){2}\t\1{1,3}$", new HashSet<string>{ "fo fo \tfo", "fo fo \tfofo", "fo fo \tfofofo",
"ba fo \tfo", "ba fo \tfofo", "ba fo \tfofofo",
"fo ba \tba", "fo ba \tbaba", "fo ba \tbababa",
"ba ba \tba", "ba ba \tbaba", "ba ba \tbababa" })
"ba ba \tba", "ba ba \tbaba", "ba ba \tbababa" }),
(@"(?-i)(?:xy{1,2}){,2}", new HashSet<string>{"", "xy", "xyy", "xyxy", "xyxyy", "xyyxy", "xyyxyy"}),
(@"(b|g{3})?", new HashSet<string>{"", "b", "ggg"}),

};
ii += simpleTestcases.Length * 2;
Expand Down Expand Up @@ -113,7 +115,7 @@ public static bool Test()
}

// ========== verify that the compiler throws an error of the correct type when faced with various invalid regexes ==========
var mustThrowTestcases = new (string rex, RandomStringFromRegexException.ExceptionType extype, bool compileTime)[]
var mustThrowTestcases = new (string rex, RandomStringFromRegexException.ExceptionType extype, bool runTime)[]
{
("(foo", RandomStringFromRegexException.ExceptionType.UnclosedParen, false),
("(?:foo", RandomStringFromRegexException.ExceptionType.UnclosedParen, false),
Expand All @@ -129,6 +131,13 @@ public static bool Test()
(@"(a)$\1", RandomStringFromRegexException.ExceptionType.DollarBeforeEndOfString, false),
(@"b$a", RandomStringFromRegexException.ExceptionType.DollarBeforeEndOfString, false),
("c{32}", RandomStringFromRegexException.ExceptionType.QuantifierExceedsMaxReps, false),
("(?:foo|+)", RandomStringFromRegexException.ExceptionType.NothingToQuantify, false),
("{7}", RandomStringFromRegexException.ExceptionType.NothingToQuantify, false),
("(+|yy|)", RandomStringFromRegexException.ExceptionType.NothingToQuantify, false),
("x+?", RandomStringFromRegexException.ExceptionType.TwoConsecutiveQuantifiers, false),
("(Foo|bar)?{8}", RandomStringFromRegexException.ExceptionType.TwoConsecutiveQuantifiers, false),
("(?:baz(Foo|bar))?{8}", RandomStringFromRegexException.ExceptionType.TwoConsecutiveQuantifiers, false),
("jjjx{,5}{6}(?:fooo)", RandomStringFromRegexException.ExceptionType.TwoConsecutiveQuantifiers, false),
("c{1,32}", RandomStringFromRegexException.ExceptionType.QuantifierExceedsMaxReps, false),
(@"(foo)(bar)\3(baz)", RandomStringFromRegexException.ExceptionType.BadBackReference, false),
(@"a{,\3", RandomStringFromRegexException.ExceptionType.BadCurlybraceQuantifier, false),
Expand All @@ -141,14 +150,14 @@ public static bool Test()

ii += mustThrowTestcases.Length;

foreach ((string rex, RandomStringFromRegexException.ExceptionType extype, bool compileTime) in mustThrowTestcases)
foreach ((string rex, RandomStringFromRegexException.ExceptionType extype, bool runTime) in mustThrowTestcases)
{
string baseErrMsg = $"FAIL: Expected RandomStringFromRegex.GetGenerator({JNode.StrToString(rex, true)}) to throw a RandomStringFromRegexException of type {extype}.\r\nInstead ";
try
{
Func<string> generator = RandomStringFromRegex.GetGenerator(rex);
// most errors occur while compiling, but some are only caught at runtime
if (compileTime)
if (runTime)
generator();
testsFailed++;
Npp.AddLine(baseErrMsg + "did not throw an exception.");
Expand Down
5 changes: 4 additions & 1 deletion JsonToolsNppPlugin/Utils/RandomStringFromRegex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ public enum TokenizerState
private List<Alternation> AlternationStack;
private int maxCaptureNumber = 0;
private RegexOptions Flags = RegexOptions.None;
private Alternation LastClosedAlternation;
/// <summary>
/// iff true, the regex is treated as case-insensitive
/// </summary>
Expand Down Expand Up @@ -424,6 +425,7 @@ private RandomStringFromRegex(string regex)
bool charsetIsNegated = false;
int maxClosedCaptureNumber = 0;
AlternationStack = new List<Alternation> { baseAlternation };
LastClosedAlternation = null;
tokens = new List<object> { baseAlternation };
bool isNegatingFlags = false;
ii = 0;
Expand Down Expand Up @@ -812,7 +814,7 @@ private void AddQuantifier(StartEnd se)
if (AlternationStack.Last().LastOptionIsEmpty(tokens.Count))
throw new RandomStringFromRegexException(Rex, ii, RandomStringFromRegexException.ExceptionType.NothingToQuantify);
// can't allow two consecutive quantifiers
if (tokens.Last() is StartEnd)
if (tokens.Last() is StartEnd && (LastClosedAlternation == null || LastClosedAlternation.End < tokens.Count))
throw new RandomStringFromRegexException(Rex, ii, RandomStringFromRegexException.ExceptionType.TwoConsecutiveQuantifiers);
tokens.Add(se);
}
Expand All @@ -822,6 +824,7 @@ private Alternation CloseTopAlternation()
var topAlternation = AlternationStack.Pop();
AddEmptyStringToEmptyOption(topAlternation);
topAlternation.Close(tokens.Count);
LastClosedAlternation = topAlternation;
return topAlternation;
}

Expand Down
Loading

0 comments on commit 9740f63

Please sign in to comment.