mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Enable completion of variables across ScriptBlock scopes (#19819)
This commit is contained in:
@@ -5375,6 +5375,20 @@ namespace System.Management.Automation
|
||||
"pv"
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> s_localScopeCommandNames = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"Microsoft.PowerShell.Core\\ForEach-Object",
|
||||
"ForEach-Object",
|
||||
"foreach",
|
||||
"%",
|
||||
"Microsoft.PowerShell.Core\\Where-Object",
|
||||
"Where-Object",
|
||||
"where",
|
||||
"?",
|
||||
"BeforeAll",
|
||||
"BeforeEach"
|
||||
};
|
||||
|
||||
private sealed class VariableInfo
|
||||
{
|
||||
internal Type LastDeclaredConstraint;
|
||||
@@ -5616,12 +5630,31 @@ namespace System.Management.Automation
|
||||
|
||||
public override AstVisitAction VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst)
|
||||
{
|
||||
return scriptBlockExpressionAst != Top ? AstVisitAction.SkipChildren : AstVisitAction.Continue;
|
||||
}
|
||||
if (scriptBlockExpressionAst == Top)
|
||||
{
|
||||
return AstVisitAction.Continue;
|
||||
}
|
||||
|
||||
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst)
|
||||
{
|
||||
return scriptBlockAst != Top ? AstVisitAction.SkipChildren : AstVisitAction.Continue;
|
||||
Ast parent = scriptBlockExpressionAst.Parent;
|
||||
// This loop checks if the scriptblock is used as a command, or an argument for a command, eg: ForEach-Object -Process {$Var1 = "Hello"}, {Var2 = $true}
|
||||
while (true)
|
||||
{
|
||||
if (parent is CommandAst cmdAst)
|
||||
{
|
||||
string cmdName = cmdAst.GetCommandName();
|
||||
return s_localScopeCommandNames.Contains(cmdName)
|
||||
|| (cmdAst.CommandElements[0] is ScriptBlockExpressionAst && cmdAst.InvocationOperator == TokenKind.Dot)
|
||||
? AstVisitAction.Continue
|
||||
: AstVisitAction.SkipChildren;
|
||||
}
|
||||
|
||||
if (parent is not CommandExpressionAst and not PipelineAst and not StatementBlockAst and not ArrayExpressionAst and not ArrayLiteralAst)
|
||||
{
|
||||
return AstVisitAction.SkipChildren;
|
||||
}
|
||||
|
||||
parent = parent.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,6 +274,21 @@ switch ($x)
|
||||
$completionText -join ' ' | Should -BeExactly 'Ascending Descending Expression'
|
||||
}
|
||||
|
||||
It 'Should complete variable assigned in other scriptblock' {
|
||||
$res = TabExpansion2 -inputScript 'ForEach-Object -Begin {$Test1 = "Hello"} -Process {$Test'
|
||||
$res.CompletionMatches[0].CompletionText | Should -Be '$Test1'
|
||||
}
|
||||
|
||||
It 'Should complete variable assigned in an array of scriptblocks' {
|
||||
$res = TabExpansion2 -inputScript 'ForEach-Object -Process @({"Block1"},{$Test1="Hello"});$Test'
|
||||
$res.CompletionMatches[0].CompletionText | Should -Be '$Test1'
|
||||
}
|
||||
|
||||
It 'Should not complete variable assigned in an ampersand executed scriptblock' {
|
||||
$res = TabExpansion2 -inputScript '& {$AmpeersandVarCompletionTest = "Hello"};$AmpeersandVarCompletionTes'
|
||||
$res.CompletionMatches.Count | Should -Be 0
|
||||
}
|
||||
|
||||
context TypeConstructionWithHashtable {
|
||||
BeforeAll {
|
||||
class RandomTestType {
|
||||
|
||||
Reference in New Issue
Block a user