Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wildcard pattern matcher improvement #6919

Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -40,16 +40,14 @@ private sealed class WildcardPattern
private static readonly ConcurrentDictionary<string, WildcardPattern> Cache = new();
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
private readonly Regex pattern;

private WildcardPattern(string pattern, string directorySeparator) =>
this.pattern = new Regex(ToRegexp(pattern, directorySeparator), RegexOptions.Compiled, RegexConstants.DefaultTimeout);
private WildcardPattern(string pattern) =>
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
this.pattern = new Regex(ToRegex(pattern), RegexOptions.None, RegexConstants.DefaultTimeout);

public bool Match(string value)
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
{
value = value.TrimStart('/');
value = value.TrimEnd('/');
try
{
return pattern.IsMatch(value);
return pattern.IsMatch(value.Trim('/'));
}
catch (RegexMatchTimeoutException)
{
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -58,14 +56,11 @@ public bool Match(string value)
}

public static WildcardPattern Create(string pattern) =>
Create(pattern, Path.DirectorySeparatorChar.ToString());
Cache.GetOrAdd(pattern + Path.DirectorySeparatorChar, _ => new WildcardPattern(pattern));
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved

private static WildcardPattern Create(string pattern, string directorySeparator) =>
Cache.GetOrAdd(pattern + directorySeparator, _ => new WildcardPattern(pattern, directorySeparator));

private static string ToRegexp(string wildcardPattern, string directorySeparator)
private static string ToRegex(string wildcardPattern)
{
var escapedDirectorySeparator = '\\' + directorySeparator;
var escapedDirectorySeparator = Regex.Escape(Path.DirectorySeparatorChar.ToString());
var sb = new StringBuilder(wildcardPattern.Length);
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved

sb.Append('^');
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -75,10 +70,10 @@ private static string ToRegexp(string wildcardPattern, string directorySeparator
{
var ch = wildcardPattern[i];

pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
if (SpecialChars.IndexOf(ch) != -1)
if (SpecialChars.Contains(ch))
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
{
// Escape regexp-specific characters
sb.Append('\\').Append(ch);
// Escape regex-specific characters
sb.Append(Regex.Escape(ch.ToString()));
}
else if (ch == '*')
{
Expand All @@ -88,7 +83,7 @@ private static string ToRegexp(string wildcardPattern, string directorySeparator
// Zero or more directories
if (i + 2 < wildcardPattern.Length && IsSlash(wildcardPattern[i + 2]))
{
sb.Append("(?:.*").Append(escapedDirectorySeparator).Append("|)");
sb.Append($"(.*{escapedDirectorySeparator}|)");
i += 2;
}
else
Expand All @@ -101,13 +96,13 @@ private static string ToRegexp(string wildcardPattern, string directorySeparator
{
// Single asterisk
// Zero or more characters excluding directory separator
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
sb.Append("[^").Append(escapedDirectorySeparator).Append("]*?");
sb.Append($"[^{escapedDirectorySeparator}]*?");
}
}
else if (ch == '?')
{
// Any single character excluding directory separator
sb.Append("[^").Append(escapedDirectorySeparator).Append("]");
sb.Append($"[^{escapedDirectorySeparator}]");
}
else if (IsSlash(ch))
{
Expand All @@ -119,13 +114,9 @@ private static string ToRegexp(string wildcardPattern, string directorySeparator
// Single character
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
sb.Append(ch);
}

i++;
}

sb.Append('$');

return sb.ToString();
return sb.Append('$').ToString();
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
}

private static bool IsSlash(char ch) =>
Expand Down