Repository: PowerShell/PowerShell
File: src/System.Management.Automation/engine/CommandCompletion/CompletionAnalysis.cs (C#)

Code before:
                .Where(parameterName => parameterName.StartsWith(wordToComplete, StringComparison.OrdinalIgnoreCase))
                .Select(parameterName => new CompletionResult(
                    parameterName,
                    parameterName,
                    CompletionResultType.ParameterValue,
                    parameterName))
                .ToList();

            return result.Count > 0 ? result : null;
        }

        /// <summary>
        /// Check if we should complete parameter names for $PSBoundParameters access patterns
        /// Supports: $PSBoundParameters.ContainsKey('...'), $PSBoundParameters['...'], $PSBoundParameters.Remove('...')
        /// </summary>
        private static List<CompletionResult> CompleteAgainstPSBoundParametersAccess(CompletionContext completionContext)
        {
            var lastAst = completionContext.RelatedAsts.Last();

            // Must be a string constant
            if (!(lastAst is StringConstantExpressionAst stringAst))
            {
                return null;
            }

            Ast targetAst = null;

            // Check for method invocation: $PSBoundParameters.ContainsKey('...') or $PSBoundParameters.Remove('...')
            if (lastAst.Parent is InvokeMemberExpressionAst invokeMemberAst)
            {
                var memberName = invokeMemberAst.Member as StringConstantExpressionAst;
                if (memberName != null &&
                    (memberName.Value.Equals("ContainsKey", StringComparison.OrdinalIgnoreCase) ||
                     memberName.Value.Equals("Remove", StringComparison.OrdinalIgnoreCase)))
                {
                    targetAst = invokeMemberAst.Expression;
                }
            }
            // Check for indexer: $PSBoundParameters['...']
            else if (lastAst.Parent is IndexExpressionAst indexAst)
            {
                targetAst = indexAst.Target;
            }

            if (targetAst == null)
            {
                return null;
            }

            // Check if target is $PSBoundParameters
            var variableAst = targetAst as VariableExpressionAst;

Review comment (suggestion):
```suggestion
            ExpressionAst targetAst = null;
```

Code after:
            {
                targetAst = indexAst.Target;
            }

            if (targetAst is null)
            {
                return null;
            }

            // Check if target is $PSBoundParameters
            if (targetAst is not VariableExpressionAst variableAst ||
                !variableAst.VariablePath.UserPath.Equals("PSBoundParameters", StringComparison.OrdinalIgnoreCase))
            {
                return null;
            }

            // Find the nearest param block
            var paramBlockAst = FindNearestParamBlock(lastAst.Parent);

            if (paramBlockAst == null || paramBlockAst.Parameters.Count == 0)
            {
                return null;
            }

            // Generate completion results from parameter names
            var wordToComplete = completionContext.WordToComplete ?? string.Empty;

            // Determine quote style based on the string constant type
            string quoteChar = string.Empty;
            if (stringAst.StringConstantType == StringConstantType.SingleQuoted)
            {
                quoteChar = "'";
            }
            else if (stringAst.StringConstantType == StringConstantType.DoubleQuoted)
            {
                quoteChar = "\"";
            }

            return CreateParameterCompletionResults(paramBlockAst, wordToComplete, quoteChar);
        }

        /// <summary>
        /// Finds the nearest ParamBlockAst by traversing up the AST hierarchy.
        /// </summary>
        /// <param name="startAst">The AST node to start searching from.</param>
        /// <returns>The nearest ParamBlockAst if found; otherwise, null.</returns>
        private static ParamBlockAst FindNearestParamBlock(Ast startAst)
        {
            Ast current = startAst;
            while (current != null)
            {