mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Handle type inference for redirected commands (#21131)
This commit is contained in:
@@ -1272,6 +1272,73 @@ namespace System.Management.Automation
|
||||
|
||||
private void InferTypesFrom(CommandAst commandAst, List<PSTypeName> inferredTypes)
|
||||
{
|
||||
if (commandAst.Redirections.Count > 0)
|
||||
{
|
||||
var mergedStreams = new HashSet<RedirectionStream>();
|
||||
bool allStreamsMerged = false;
|
||||
foreach (RedirectionAst streamRedirection in commandAst.Redirections)
|
||||
{
|
||||
if (streamRedirection is FileRedirectionAst fileRedirection)
|
||||
{
|
||||
if (fileRedirection.FromStream is RedirectionStream.All or RedirectionStream.Output)
|
||||
{
|
||||
// command output is redirected so it returns nothing.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (streamRedirection is MergingRedirectionAst mergeRedirection && mergeRedirection.ToStream == RedirectionStream.Output)
|
||||
{
|
||||
if (mergeRedirection.FromStream == RedirectionStream.All)
|
||||
{
|
||||
allStreamsMerged = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
_ = mergedStreams.Add(mergeRedirection.FromStream);
|
||||
}
|
||||
}
|
||||
|
||||
if (allStreamsMerged)
|
||||
{
|
||||
inferredTypes.Add(new PSTypeName(typeof(ErrorRecord)));
|
||||
inferredTypes.Add(new PSTypeName(typeof(WarningRecord)));
|
||||
inferredTypes.Add(new PSTypeName(typeof(VerboseRecord)));
|
||||
inferredTypes.Add(new PSTypeName(typeof(DebugRecord)));
|
||||
inferredTypes.Add(new PSTypeName(typeof(InformationRecord)));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (RedirectionStream value in mergedStreams)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case RedirectionStream.Error:
|
||||
inferredTypes.Add(new PSTypeName(typeof(ErrorRecord)));
|
||||
break;
|
||||
|
||||
case RedirectionStream.Warning:
|
||||
inferredTypes.Add(new PSTypeName(typeof(WarningRecord)));
|
||||
break;
|
||||
|
||||
case RedirectionStream.Verbose:
|
||||
inferredTypes.Add(new PSTypeName(typeof(VerboseRecord)));
|
||||
break;
|
||||
|
||||
case RedirectionStream.Debug:
|
||||
inferredTypes.Add(new PSTypeName(typeof(DebugRecord)));
|
||||
break;
|
||||
|
||||
case RedirectionStream.Information:
|
||||
inferredTypes.Add(new PSTypeName(typeof(InformationRecord)));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PseudoBindingInfo pseudoBinding = new PseudoParameterBinder()
|
||||
.DoPseudoParameterBinding(commandAst, null, null, PseudoParameterBinder.BindingType.ParameterCompletion);
|
||||
|
||||
|
||||
@@ -1492,6 +1492,47 @@ Describe "Type inference Tests" -tags "CI" {
|
||||
$null = [AstTypeInference]::InferTypeOf($FoundAst)
|
||||
}
|
||||
|
||||
It 'Infers type of command with all streams redirected to Success stream' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { Get-PSDrive *>&1 }.Ast)
|
||||
$ExpectedTypeNames = @(
|
||||
[ErrorRecord].FullName
|
||||
[WarningRecord].FullName
|
||||
[VerboseRecord].FullName
|
||||
[DebugRecord].FullName
|
||||
[InformationRecord].FullName
|
||||
[PSDriveInfo].FullName
|
||||
) -join ';'
|
||||
$res.Name -join ';' | Should -Be $ExpectedTypeNames
|
||||
}
|
||||
|
||||
It 'Infers type of command with success stream redirected' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { Get-PSDrive *>&1 1>$null }.Ast)
|
||||
$res.Count | Should -Be 0
|
||||
}
|
||||
|
||||
It 'Infers type of command with some streams redirected to success' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { Get-PSDrive 3>&1 4>&1 }.Ast)
|
||||
$res.Count | Should -Be 3
|
||||
$ExpectedTypeNames = @(
|
||||
[PSDriveInfo].FullName
|
||||
[VerboseRecord].FullName
|
||||
[WarningRecord].FullName
|
||||
) -join ';'
|
||||
($res.Name | Sort-Object) -join ';' | Should -Be $ExpectedTypeNames
|
||||
}
|
||||
|
||||
It 'Infers type of command with other streams redirected to success' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { Get-PSDrive 2>&1 5>&1 6>&1 }.Ast)
|
||||
$res.Count | Should -Be 4
|
||||
$ExpectedTypeNames = @(
|
||||
[DebugRecord].FullName
|
||||
[ErrorRecord].FullName
|
||||
[InformationRecord].FullName
|
||||
[PSDriveInfo].FullName
|
||||
) -join ';'
|
||||
($res.Name | Sort-Object) -join ';' | Should -Be $ExpectedTypeNames
|
||||
}
|
||||
|
||||
It 'Should only consider assignments wrapped in parentheses to be a part of the output in a Named block' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { [string]$Assignment1 = "Hello"; ([int]$Assignment2 = 42) }.Ast)
|
||||
$res.Count | Should -Be 1
|
||||
|
||||
Reference in New Issue
Block a user