Skip to content

Commit 57bf508

Browse files
SeeminglyScienceiSazonov
authored andcommitted
Fix static method invocation type inference (PowerShell#8018)
Fixes type inference for static method invocations (e.g. [powershell]::Create()).
1 parent 0a4f33a commit 57bf508

3 files changed

Lines changed: 47 additions & 16 deletions

File tree

src/System.Management.Automation/engine/parser/TypeInferenceVisitor.cs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,21 +1603,7 @@ private bool TryGetTypeFromMember(
16031603
if (methodCacheEntry[0].method.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase))
16041604
{
16051605
maybeWantDefaultCtor = false;
1606-
if (isInvokeMemberExpressionAst)
1607-
{
1608-
foreach (var method in methodCacheEntry.methodInformationStructures)
1609-
{
1610-
if (method.method is MethodInfo methodInfo && !methodInfo.ReturnType.ContainsGenericParameters)
1611-
{
1612-
result.Add(new PSTypeName(methodInfo.ReturnType));
1613-
}
1614-
}
1615-
1616-
return true;
1617-
}
1618-
1619-
// Accessing a method as a property, we'd return a wrapper over the method.
1620-
result.Add(new PSTypeName(typeof(PSMethod)));
1606+
AddTypesFromMethodCacheEntry(methodCacheEntry, result, isInvokeMemberExpressionAst);
16211607
return true;
16221608
}
16231609

@@ -1667,6 +1653,16 @@ private bool TryGetTypeFromMember(
16671653
ScriptBlock scriptBlock = null;
16681654
switch (memberInfo)
16691655
{
1656+
case PSMethod m:
1657+
{
1658+
if (m.adapterData is DotNetAdapter.MethodCacheEntry methodCacheEntry)
1659+
{
1660+
AddTypesFromMethodCacheEntry(methodCacheEntry, result, isInvokeMemberExpressionAst);
1661+
return true;
1662+
}
1663+
1664+
return false;
1665+
}
16701666
case PSProperty p:
16711667
{
16721668
result.Add(new PSTypeName(p.Value.GetType()));
@@ -1739,6 +1735,28 @@ private bool TryGetTypeFromMember(
17391735
return false;
17401736
}
17411737

1738+
private void AddTypesFromMethodCacheEntry(
1739+
DotNetAdapter.MethodCacheEntry methodCacheEntry,
1740+
List<PSTypeName> result,
1741+
bool isInvokeMemberExpressionAst)
1742+
{
1743+
if (isInvokeMemberExpressionAst)
1744+
{
1745+
foreach (var method in methodCacheEntry.methodInformationStructures)
1746+
{
1747+
if (method.method is MethodInfo methodInfo && !methodInfo.ReturnType.ContainsGenericParameters)
1748+
{
1749+
result.Add(new PSTypeName(methodInfo.ReturnType));
1750+
}
1751+
}
1752+
1753+
return;
1754+
}
1755+
1756+
// Accessing a method as a property, we'd return a wrapper over the method.
1757+
result.Add(new PSTypeName(typeof(PSMethod)));
1758+
}
1759+
17421760
private PSTypeName[] GetExpressionType(ExpressionAst expression, bool isStatic)
17431761
{
17441762
PSTypeName[] exprType;

test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,13 @@ dir -Recurse `
644644
$res.CompletionMatches | Should -HaveCount 1
645645
$res.CompletionMatches[0].CompletionText | Should -BeExactly "-LiteralPath"
646646
}
647+
648+
It "Test member completion of a static method invocation" {
649+
$inputStr = '[powershell]::Create().'
650+
$res = TabExpansion2 -inputScript $inputStr -cursorColumn $inputStr.Length
651+
$res.CompletionMatches | Should -HaveCount 31
652+
$res.CompletionMatches[0].CompletionText | Should -BeExactly "Commands"
653+
}
647654
}
648655

649656
Context "Module completion for 'using module'" {

test/powershell/engine/Api/TypeInference.Tests.ps1

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ Describe "Type inference Tests" -tags "CI" {
242242
$res.Name | Should -Be 'System.Type'
243243
}
244244

245+
It "Infers type from static member method" {
246+
$res = [AstTypeInference]::InferTypeOf( { [powershell]::Create() }.Ast)
247+
$res.Count | Should -Be 1
248+
$res.Name | Should -Be 'System.Management.Automation.PowerShell'
249+
}
250+
245251
It "Infers type from integer * stringliteral" {
246252
$res = [AstTypeInference]::InferTypeOf( { 5 * "5" }.Ast)
247253
$res.Count | Should -Be 1
@@ -412,7 +418,7 @@ Describe "Type inference Tests" -tags "CI" {
412418
It "Infers typeof Select-Object when Parameter is ExcludeProperty" {
413419
$res = [AstTypeInference]::InferTypeOf( { [io.fileinfo]::new("file") | Select-Object -ExcludeProperty *Time*, E* }.Ast)
414420
$res.Count | Should -Be 1
415-
$res[0].Name | Should -Be "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LinkType:Mode:Name:Target"
421+
$res[0].Name | Should -Be "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LinkType:Mode:Name:Target:VersionInfo"
416422
$names = $res[0].Members.Name
417423
$names -contains "BaseName" | Should -BeTrue
418424
$names -contains "Name" | Should -BeTrue

0 commit comments

Comments
 (0)