Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4401,9 +4401,9 @@ internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext
var relativePaths = context.GetOption("RelativePaths", @default: defaultRelative);
var useLiteralPath = context.GetOption("LiteralPaths", @default: false);

if (useLiteralPath && LocationGlobber.StringContainsGlobCharacters(wordToComplete))
if (useLiteralPath)
{
wordToComplete = WildcardPattern.Escape(wordToComplete, Utils.Separators.StarOrQuestion);
wordToComplete = WildcardPattern.Escape(wordToComplete, escapeOnlyBrackets: true);
}

if (!defaultRelative && wordToComplete.Length >= 2 && wordToComplete[1] == ':' && char.IsLetter(wordToComplete[0]) && executionContext != null)
Expand Down Expand Up @@ -6137,7 +6137,7 @@ internal static void CompleteMemberByInferredType(
string memberName,
Func<object, bool> filter,
bool isStatic,
HashSet<string> excludedMembers = null,
HashSet<string> excludedMembers = null,
bool addMethodParenthesis = true)
{
bool extensionMethodsAdded = false;
Expand Down
55 changes: 25 additions & 30 deletions src/System.Management.Automation/engine/regex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Management.Automation.Internal;
Expand Down Expand Up @@ -206,25 +205,20 @@ public bool IsMatch(string input)
}

/// <summary>
/// Escape special chars, except for those specified in <paramref name="charsNotToEscape"/>, in a string by replacing them with their escape codes.
/// Escape wildcard characters in a string by replacing them with their escape codes.
/// </summary>
/// <param name="pattern">The input string containing the text to convert.</param>
/// <param name="charsNotToEscape">Array of characters that not to escape.</param>
/// <param name="escapeOnlyBrackets">Escape all wildcard characters if false. Escape only brackets if true.</param>
/// <returns>
/// A string of characters with any metacharacters, except for those specified in <paramref name="charsNotToEscape"/>, converted to their escaped form.
/// A string of characters with any wildcard characters converted to their escaped form.
/// </returns>
internal static string Escape(string pattern, char[] charsNotToEscape)
internal static string Escape(string pattern, bool escapeOnlyBrackets)
{
if (pattern == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(pattern));
}

if (charsNotToEscape == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(charsNotToEscape));
}

if (pattern == string.Empty)
{
return pattern;
Expand All @@ -233,33 +227,34 @@ internal static string Escape(string pattern, char[] charsNotToEscape)
Span<char> temp = pattern.Length < StackAllocThreshold ? stackalloc char[pattern.Length * 2 + 1] : new char[pattern.Length * 2 + 1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a existing bug, the condition should probably have been pattern.Length * 2 < StackAllocThreshold.

I suggest refactoring to the recommended pattern (and in Unescape too):

Suggested change
Span<char> temp = pattern.Length < StackAllocThreshold ? stackalloc char[pattern.Length * 2 + 1] : new char[pattern.Length * 2 + 1];
int lengthRequired = pattern.Length * 2 + 1;
Span<char> temp = lengthRequired <= StackAllocThreshold ? stackalloc char[StackAllocThreshold] : new char[lengthRequired];

int tempIndex = 0;

for (int i = 0; i < pattern.Length; i++)
if (escapeOnlyBrackets)
{
char ch = pattern[i];

//
// if it is a wildcard char, escape it
//
if (IsWildcardChar(ch) && !charsNotToEscape.Contains(ch))
for (int i = 0; i < pattern.Length; i++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (int i = 0; i < pattern.Length; i++)
foreach (char ch in pattern)

{
temp[tempIndex++] = escapeChar;
}

temp[tempIndex++] = ch;
}

string s = null;
char ch = pattern[i];
if (ch == '[' || ch == ']')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ch == '[' || ch == ']')
if (ch is '[' or ']')

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xtqqczze The PR is only for removing Utils.Separators.StarOrQuestion. No plans for style changes.

{
temp[tempIndex++] = escapeChar;
}

if (tempIndex == pattern.Length)
{
s = pattern;
temp[tempIndex++] = ch;
}
}
else
{
s = new string(temp.Slice(0, tempIndex));
for (int i = 0; i < pattern.Length; i++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (int i = 0; i < pattern.Length; i++)
foreach (char ch in pattern)

{
char ch = pattern[i];
if (IsWildcardChar(ch))
{
temp[tempIndex++] = escapeChar;
}

temp[tempIndex++] = ch;
}
}

return s;
return tempIndex == pattern.Length ? pattern : new string(temp.Slice(0, tempIndex));
}

/// <summary>
Expand All @@ -271,7 +266,7 @@ internal static string Escape(string pattern, char[] charsNotToEscape)
/// </returns>
public static string Escape(string pattern)
{
return Escape(pattern, Array.Empty<char>());
return Escape(pattern, escapeOnlyBrackets: false);
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions test/xUnit/csharp/test_WildcardPattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ public void TestEscape_String(string source, string expected)
[Theory]
[InlineData("a", "a")]
[InlineData("a*", "a*")]
[InlineData("*?[]", "*?[]")]
public void TestEscape_String_NotEscape(string source, string expected)
[InlineData("*?[]", "*?`[`]")]
public void TestEscape_String_OnlyBrackets(string source, string expected)
{
Assert.Equal(WildcardPattern.Escape(source, new[] { '*', '?', '[', ']' }), expected);
Assert.Equal(WildcardPattern.Escape(source, true), expected);
}

[Fact]
Expand Down