mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix type inference for all scope vars (#18758)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation.Internal;
|
||||
|
||||
namespace System.Management.Automation
|
||||
{
|
||||
@@ -357,22 +358,22 @@ namespace System.Management.Automation
|
||||
// see an assignment to any of these variables so that they get handled properly (either throwing an exception
|
||||
// because they are constant/readonly, or having the value persist in parent scopes where the allscope variable
|
||||
// also exists.
|
||||
internal static readonly string[] AllScopeVariables = {
|
||||
SpecialVariables.Question,
|
||||
SpecialVariables.ExecutionContext,
|
||||
SpecialVariables.False,
|
||||
SpecialVariables.Home,
|
||||
SpecialVariables.Host,
|
||||
SpecialVariables.PID,
|
||||
SpecialVariables.PSCulture,
|
||||
SpecialVariables.PSHome,
|
||||
SpecialVariables.PSUICulture,
|
||||
SpecialVariables.PSVersionTable,
|
||||
SpecialVariables.PSEdition,
|
||||
SpecialVariables.ShellId,
|
||||
SpecialVariables.True,
|
||||
SpecialVariables.EnabledExperimentalFeatures,
|
||||
};
|
||||
internal static readonly Dictionary<string, Type> AllScopeVariables = new(StringComparer.OrdinalIgnoreCase) {
|
||||
{ Question, typeof(bool) },
|
||||
{ ExecutionContext, typeof(EngineIntrinsics) },
|
||||
{ False, typeof(bool) },
|
||||
{ Home, typeof(string) },
|
||||
{ Host, typeof(object) },
|
||||
{ PID, typeof(int) },
|
||||
{ PSCulture, typeof(string) },
|
||||
{ PSHome, typeof(string) },
|
||||
{ PSUICulture, typeof(string) },
|
||||
{ PSVersionTable, typeof(PSVersionHashTable) },
|
||||
{ PSEdition, typeof(string) },
|
||||
{ ShellId, typeof(string) },
|
||||
{ True, typeof(bool) },
|
||||
{ EnabledExperimentalFeatures, typeof(ReadOnlyBag<string>) }
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> s_classMethodsAccessibleVariables = new HashSet<string>
|
||||
(
|
||||
|
||||
@@ -1846,7 +1846,7 @@ namespace System.Management.Automation
|
||||
// We don't need to handle drive qualified variables, we can usually get those values
|
||||
// without needing to "guess" at the type.
|
||||
var astVariablePath = variableExpressionAst.VariablePath;
|
||||
if (!astVariablePath.IsVariable)
|
||||
if (!astVariablePath.IsVariable || astVariablePath.UserPath.EqualsOrdinalIgnoreCase(SpecialVariables.Null))
|
||||
{
|
||||
// Not a variable - the caller should have already tried going to session state
|
||||
// to get the item and hence it's type, but that must have failed. Don't try again.
|
||||
@@ -1961,6 +1961,23 @@ namespace System.Management.Automation
|
||||
var isThis = astVariablePath.UserPath.EqualsOrdinalIgnoreCase(SpecialVariables.This);
|
||||
if (!isThis || (_context.CurrentTypeDefinitionAst == null && _context.CurrentThisType == null))
|
||||
{
|
||||
if (SpecialVariables.AllScopeVariables.TryGetValue(astVariablePath.UserPath, out Type knownType))
|
||||
{
|
||||
if (knownType == typeof(object))
|
||||
{
|
||||
if (_context.TryGetRepresentativeTypeNameFromExpressionSafeEval(variableExpressionAst, out var psType))
|
||||
{
|
||||
inferredTypes.Add(psType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
inferredTypes.Add(new PSTypeName(knownType));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SpecialVariables.AutomaticVariables.Length; i++)
|
||||
{
|
||||
if (!astVariablePath.UserPath.EqualsOrdinalIgnoreCase(SpecialVariables.AutomaticVariables[i]))
|
||||
|
||||
@@ -1366,6 +1366,23 @@ Describe "Type inference Tests" -tags "CI" {
|
||||
$res.Count | Should -Be 2
|
||||
$res.Name -join ' ' | Should -Be "System.IO.FileInfo System.IO.DirectoryInfo"
|
||||
}
|
||||
|
||||
It 'Infers type of $null after variable assignment' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { $null = "Hello";$null }.Ast)
|
||||
$res.Count | Should -Be 0
|
||||
}
|
||||
|
||||
It 'Infers type of all scope variable after variable assignment' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { $true = "Hello";$true }.Ast)
|
||||
$res.Count | Should -Be 1
|
||||
$res.Name | Should -Be 'System.Boolean'
|
||||
}
|
||||
|
||||
It 'Infers type of all scope variable host after variable assignment' {
|
||||
$res = [AstTypeInference]::InferTypeOf( { $Host = "Hello";$Host }.Ast, [TypeInferenceRuntimePermissions]::AllowSafeEval)
|
||||
$res.Count | Should -Be 1
|
||||
$res.Name | Should -Be 'System.Management.Automation.Internal.Host.InternalHost'
|
||||
}
|
||||
}
|
||||
|
||||
Describe "AstTypeInference tests" -Tags CI {
|
||||
|
||||
Reference in New Issue
Block a user