Fall back to type inference when hashtable key value cannot be retrieved from safe expression (#21184)

This commit is contained in:
MartinGC94
2024-03-04 15:55:23 -08:00
committed by GitHub
parent 1dc2ebe5bc
commit aa97c515c8
2 changed files with 31 additions and 18 deletions
@@ -584,6 +584,20 @@ namespace System.Management.Automation
if (hashtableAst.KeyValuePairs.Count > 0)
{
var properties = new List<PSMemberNameAndType>();
void AddInferredTypes(Ast ast, string keyName)
{
bool foundAnyTypes = false;
foreach (PSTypeName item in InferTypes(ast))
{
foundAnyTypes = true;
properties.Add(new PSMemberNameAndType(keyName, item));
}
if (!foundAnyTypes)
{
properties.Add(new PSMemberNameAndType(keyName, new PSTypeName("System.Object")));
}
}
foreach (var kv in hashtableAst.KeyValuePairs)
{
@@ -615,31 +629,18 @@ namespace System.Management.Automation
_ = SafeExprEvaluator.TrySafeEval(expression, _context.ExecutionContext, out value);
}
PSTypeName valueType;
if (value is null)
{
valueType = new PSTypeName("System.Object");
}
else
{
valueType = new PSTypeName(value.GetType());
AddInferredTypes(expression, name);
continue;
}
PSTypeName valueType = new(value.GetType());
properties.Add(new PSMemberNameAndType(name, valueType, value));
}
else
{
bool foundAnyTypes = false;
foreach (var item in InferTypes(kv.Item2))
{
foundAnyTypes = true;
properties.Add(new PSMemberNameAndType(name, item));
}
if (!foundAnyTypes)
{
properties.Add(new PSMemberNameAndType(name, new PSTypeName("System.Object")));
}
AddInferredTypes(kv.Item2, name);
}
}
}
@@ -1639,7 +1640,7 @@ namespace System.Management.Automation
var memberNameList = new List<string> { memberAsStringConst.Value };
foreach (var type in exprType)
{
if (type.Type == typeof(PSObject))
if (type.Type == typeof(PSObject) && type is not PSSyntheticTypeName)
{
continue;
}
@@ -1379,12 +1379,24 @@ Describe "Type inference Tests" -tags "CI" {
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
}
It 'Falls back to type inference for hashtable assignments with pure expression with no value' {
$res = [AstTypeInference]::InferTypeOf( {$KeyWithNoValue = Get-ChildItem $HOME; (@{RandomKey = $KeyWithNoValue}).RandomKey }.Ast)
$Res.Count | Should -Be 2
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
}
It 'Infers type of index expression on hashtable with synthetic type' {
$res = [AstTypeInference]::InferTypeOf( { (@{RandomKey = Get-ChildItem $HOME})['RandomKey'] }.Ast)
$res.Count | Should -Be 2
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
}
It 'Infers type of member expression on a custom object' {
$res = [AstTypeInference]::InferTypeOf( { ([pscustomobject]@{RandomProp1 = Get-ChildItem $HOME}).RandomProp1 }.Ast)
$res.Count | Should -Be 2
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
}
It 'Infers closest variable type' {
$res = [AstTypeInference]::InferTypeOf( { [string]$TestVar = "";[hashtable]$TestVar = @{};$TestVar }.Ast)
$res.Name | Select-Object -Last 1 | Should -Be "System.Collections.Hashtable"