From 12a2c82d0e45933d8c9fc80ad44388aa88bf8abe Mon Sep 17 00:00:00 2001 From: MartinGC94 <42123497+MartinGC94@users.noreply.github.com> Date: Thu, 9 Jun 2022 06:41:52 +0200 Subject: [PATCH] Fix various completion issues inside the param block (#17489) --- .../CommandCompletion/CompletionAnalysis.cs | 8 ++++ .../CommandCompletion/CompletionCompleters.cs | 6 +-- .../TabCompletion/TabCompletion.Tests.ps1 | 37 +++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs index d15f8c763a..24a02ac785 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs @@ -155,6 +155,14 @@ namespace System.Management.Automation ast => IsCursorWithinOrJustAfterExtent(positionForAstSearch, ast.Extent), searchNestedScriptBlocks: true).ToList(); + // If the last ast is an unnamed block that starts with "param" the cursor is inside a param block. + // To avoid adding special handling to all the completers that look at the last ast, we remove it here because it's not useful for completion. + if (relatedAsts[^1].Extent.Text.StartsWith("param", StringComparison.OrdinalIgnoreCase) + && relatedAsts[^1] is NamedBlockAst namedBlock && namedBlock.Unnamed) + { + relatedAsts.RemoveAt(relatedAsts.Count - 1); + } + Diagnostics.Assert(tokenAtCursor == null || tokenBeforeCursor == null, "Only one of these tokens can be non-null"); return new AstAnalysisContext(tokenAtCursor, tokenBeforeCursor, relatedAsts, replacementIndex); diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index fce4590aa1..5877cfefba 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -5529,7 +5529,7 @@ namespace System.Management.Automation } Ast lastAst = context.RelatedAsts[^1]; - Ast firstAstAfterComment = lastAst.Find(ast => ast.Extent.StartOffset >= context.TokenAtCursor.Extent.EndOffset, searchNestedScriptBlocks: false); + Ast firstAstAfterComment = lastAst.Find(ast => ast.Extent.StartOffset >= context.TokenAtCursor.Extent.EndOffset && ast is not NamedBlockAst, searchNestedScriptBlocks: false); // Comment-based help can apply to a following function definition if it starts within 2 lines int commentEndLine = context.TokenAtCursor.Extent.EndLineNumber + 2; @@ -5556,9 +5556,7 @@ namespace System.Management.Automation // Helpblock before function if (firstAstAfterComment is not null && firstAstAfterComment.Extent.StartLineNumber <= commentEndLine - && firstAstAfterComment is NamedBlockAst block - && block.Statements.Count > 0 - && block.Statements[0] is FunctionDefinitionAst statement) + && firstAstAfterComment is FunctionDefinitionAst statement) { return statement; } diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index 38856465db..7f22709416 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -454,6 +454,19 @@ switch ($x) $actual | Should -BeExactly $expected } + It 'Should complete parameter in param block' { + $res = TabExpansion2 -inputScript 'Param($Param1=(Get-ChildItem -))' -cursorColumn 30 + $res.CompletionMatches[0].CompletionText | Should -BeExactly '-Path' + } + It 'Should complete member in param block' { + $res = TabExpansion2 -inputScript 'Param($Param1=($PSVersionTable.))' -cursorColumn 31 + $res.CompletionMatches[0].CompletionText | Should -BeExactly 'Count' + } + It 'Should complete attribute argument in param block' { + $res = TabExpansion2 -inputScript 'Param([Parameter()]$Param1)' -cursorColumn 17 + $res.CompletionMatches[0].CompletionText | Should -BeExactly 'Position' + } + Context "Format cmdlet's View paramter completion" { BeforeAll { $viewDefinition = @' @@ -2053,6 +2066,30 @@ function MyFunction ($param1, $param2) { } } +'@ + } + @{ + Intent = 'Complete help keyword PARAMETER argument for function inside advanced function' + Expected = 'param1','param2' + TestString = @' +function Verb-Noun +{ + Param + ( + [Parameter()] + [string[]] + $ParamA + ) + Begin + { + <# + .Parameter ^ + #> + function MyFunction ($param1, $param2) + { + } + } +} '@ } @{