-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Continuing my investigation of tab completion quoting/escaping failures:
Steps to reproduce
$a = @{ '3hello' = 'a'}
$a.<TAB> # select `3hello` property from list, then execute.Expected behavior
the finished completion to be:
$a.'3hello'Actual behavior
$a.3hello
Which causes an error 'missing property name'.
Environment data
Name Value
---- -----
PSVersion 6.2.2
PSEdition Core
GitCommitId 6.2.2
OS Microsoft Windows 10.0.18941
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Additionally
Tab completion after $a.' switches to file name completion.
The code that handles this appears to be at:
PowerShell/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs
Lines 6586 to 6591 in 48c7e11
| // Handle scenarios like this: $aa | add-member 'a b' 23; $aa.a<tab> | |
| if (completionText.IndexOfAny(s_charactersRequiringQuotes) != -1) | |
| { | |
| completionText = completionText.Replace("'", "''"); | |
| completionText = "'" + completionText + "'"; | |
| } |
The field s_charactersRequiringQuotes is used mostly for variable name checks, but is also inadequate for that purpose (see #10006), but fails here because it doesn't handle the condition of numeric digits in the first character require quoting.
PowerShell/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs
Lines 4565 to 4567 in 48c7e11
| private static readonly char[] s_charactersRequiringQuotes = new char[] { | |
| '-', '`', '&', '@', '\'', '"', '#', '{', '}', '(', ')', '$', ',', ';', '|', '<', '>', ' ', '.', '\\', '/', '\t', '^', | |
| }; |
In PowerShell code, I would use REGEX: ^[\p{L}_][\w]*$. If this regex fails on a non-empty name, the property name must be quoted. However there is probably a quicker method in C# using the [CharExtensions] class using IsIdentifierStart() (first character) and IsIdentifierFollow() (subsequent characters), and quote the property if the response is FALSE.