From b5df6688680036539860b3cb767debe9fe67844a Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 5 Dec 2019 15:21:42 -0800 Subject: [PATCH] Fix NullReferenceException in CompletionCompleters public methods --- .../CommandCompletion/CompletionCompleters.cs | 32 +++++++++++-------- .../Host/TabCompletion/BugFix.Tests.ps1 | 10 ++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 415471362c8..07953a757d5 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -4581,7 +4581,7 @@ internal static List CompleteVariable(CompletionContext contex var wordToComplete = context.WordToComplete; var colon = wordToComplete.IndexOf(':'); - var lastAst = context.RelatedAsts.Last(); + var lastAst = context.RelatedAsts?.Last(); var variableAst = lastAst as VariableExpressionAst; var prefix = variableAst != null && variableAst.Splatted ? "@" : "$"; @@ -5998,19 +5998,22 @@ internal static List CompleteType(CompletionContext context, s } // this is a temporary fix. Only the type defined in the same script get complete. Need to use using Module when that is available. - var scriptBlockAst = (ScriptBlockAst)context.RelatedAsts[0]; - var typeAsts = scriptBlockAst.FindAll(ast => ast is TypeDefinitionAst, false).Cast(); - foreach (var typeAst in typeAsts.Where(ast => pattern.IsMatch(ast.Name))) + if (context.RelatedAsts != null && context.RelatedAsts.Count > 0) { - string toolTipPrefix = string.Empty; - if (typeAst.IsInterface) - toolTipPrefix = "Interface "; - else if (typeAst.IsClass) - toolTipPrefix = "Class "; - else if (typeAst.IsEnum) - toolTipPrefix = "Enum "; + var scriptBlockAst = (ScriptBlockAst)context.RelatedAsts[0]; + var typeAsts = scriptBlockAst.FindAll(ast => ast is TypeDefinitionAst, false).Cast(); + foreach (var typeAst in typeAsts.Where(ast => pattern.IsMatch(ast.Name))) + { + string toolTipPrefix = string.Empty; + if (typeAst.IsInterface) + toolTipPrefix = "Interface "; + else if (typeAst.IsClass) + toolTipPrefix = "Class "; + else if (typeAst.IsEnum) + toolTipPrefix = "Enum "; - results.Add(new CompletionResult(prefix + typeAst.Name + suffix, typeAst.Name, CompletionResultType.Type, toolTipPrefix + typeAst.Name)); + results.Add(new CompletionResult(prefix + typeAst.Name + suffix, typeAst.Name, CompletionResultType.Type, toolTipPrefix + typeAst.Name)); + } } results.Sort((c1, c2) => string.Compare(c1.ListItemText, c2.ListItemText, StringComparison.OrdinalIgnoreCase)); @@ -6019,7 +6022,10 @@ internal static List CompleteType(CompletionContext context, s private static string GetNamespaceToRemove(CompletionContext context, TypeCompletionBase completion) { - if (completion is NamespaceCompletion) { return null; } + if (completion is NamespaceCompletion || context.RelatedAsts == null || context.RelatedAsts.Count == 0) + { + return null; + } var typeCompletion = completion as TypeCompletion; string typeNameSpace = typeCompletion != null diff --git a/test/powershell/Host/TabCompletion/BugFix.Tests.ps1 b/test/powershell/Host/TabCompletion/BugFix.Tests.ps1 index f463d95e8aa..89b91b6cfba 100644 --- a/test/powershell/Host/TabCompletion/BugFix.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/BugFix.Tests.ps1 @@ -34,6 +34,16 @@ Describe "Tab completion bug fix" -Tags "CI" { $result.CompletionMatches[2].CompletionText | Should -BeExactly "-NoOverwrite" } + It "Issue#11227 - [CompletionCompleters]::CompleteVariable and [CompletionCompleters]::CompleteType should work" { + $result = [System.Management.Automation.CompletionCompleters]::CompleteType("CompletionComple") + $result.Count | Should -BeExactly 1 + $result[0].CompletionText | Should -BeExactly 'System.Management.Automation.CompletionCompleters' + + $result = [System.Management.Automation.CompletionCompleters]::CompleteVariable("errorAction") + $result.Count | Should -BeExactly 1 + $result[0].CompletionText | Should -BeExactly '$ErrorActionPreference' + } + Context "Issue#3416 - 'Select-Object'" { BeforeAll { $DatetimeProperties = @((Get-Date).psobject.baseobject.psobject.properties) | Sort-Object -Property Name