You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tab completion for Where-Object and Foreach-Object does not escape single quotes in property names #24493
For PSCustomObject's (and likely others) properties containing characters like spaces and quotes, tab completion automatically quotes and escapes them. As example payload, take:
>$employees="ID,Employee's name`n1,Alice`n2,Bob"
While $employees[0].E<TAB> will correctly produce $employees[0].'Employee''s name', doubling single quote to escape it, it is not done for Where-Object and ForEach-Object.
Pressing enter waits for input due to unclosed quote.
Environment data
Name Value
---------
PSVersion 7.4.5
PSEdition Core
GitCommitId 7.4.5
OS Microsoft Windows 10.0.22631
Platform Win32NT
PSCompatibleVersions {1.0,2.0,3.0,4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
changed the title [-]Where-Object and Foreach-object do not escape single quotes in property names[/-][+]Tab completion for Where-Object and Foreach-Object does not escape single quotes in property names[/+]on Oct 25, 2024
Wouldn't it make more sense to try and centralise ilthe code, so that commands use the same escaping as [0].E<YAB>?Otherwise there will be more mismatches
Definitely. What I suggested before was just a quick fix. Ideally someone should do what this PR tried to do: #10226 which is to go through all the completers to make the escaping methods work consistently.
Personally though I don't feel like doing the work because:
1: I have a bunch of other pending PRs that I don't want to risk merge conflicts with.
2: It's rarely something that bothers me because member names are typically simple enough that the current escaping works well enough for me.
varcompletion Text =(memberName.IndexOfAny(s_charactersRequiringQuotes)!=0)?$"'{EscapeSingleQuotedStringContent(memberName)'": memberName;
if (isMethod && addMethodParenthesis)
{
completionText += "(";}
I don't think methods can have a ' (might be mistaken) but also you shouldn't try to add ( when using the -MemberName + -ArgumentList parameter set. ForEach-Object will correctly bind the method arguments using spaces, i.e.:
Activity
dkaszews commentedon Oct 25, 2024
Paging MartinGC94 who I believe is local expert on tab completion
[-]Where-Object and Foreach-object do not escape single quotes in property names[/-][+]Tab completion for Where-Object and Foreach-Object does not escape single quotes in property names[/+]MartinGC94 commentedon Oct 25, 2024
This can be fixed here: https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs#L6882 by changing it from
completionText = $"'{memberName}'";tocompletionText = $"'{memberName.Replace("'", "''")}'";which is how it's done in other places. Though like in those other places it won't work if the member name contains special single quote chars like’.dkaszews commentedon Oct 26, 2024
Wouldn't it make more sense to try and centralise ilthe code, so that commands use the same escaping as
[0].E<YAB>?Otherwise there will be more mismatchesMartinGC94 commentedon Oct 26, 2024
Definitely. What I suggested before was just a quick fix. Ideally someone should do what this PR tried to do: #10226 which is to go through all the completers to make the escaping methods work consistently.
Personally though I don't feel like doing the work because:
1: I have a bunch of other pending PRs that I don't want to risk merge conflicts with.
2: It's rarely something that bothers me because member names are typically simple enough that the current escaping works well enough for me.
dkaszews commentedon Oct 26, 2024
Sure thing, refactors are usually done when there is no other pending work.
santisq commentedon Oct 26, 2024
Wouldn't it make sense to use
CodeGeneration.EscapeSingleQuotedStringContentinstead of.Replace?MartinGC94 commentedon Oct 26, 2024
I didn't know about that method but I don't see any reason why it should be preferred over
.Replace.santisq commentedon Oct 26, 2024
Well, main reason is for what you mentioned in the last comment:
This method handles that:
dkaszews commentedon Oct 27, 2024
Would something like this work?
santisq commentedon Oct 30, 2024
I don't think methods can have a
'(might be mistaken) but also you shouldn't try to add(when using the-MemberName+-ArgumentListparameter set.ForEach-Objectwill correctly bind the method arguments using spaces, i.e.: