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

Code before:
            var helper = new PowerShellExecutionHelper(PowerShell.Create(RunspaceMode.CurrentRunspace));
            var executionContext = helper.CurrentPowerShell.Runspace.ExecutionContext;
            return CompleteVariable(new CompletionContext { WordToComplete = variableName, Helper = helper, ExecutionContext = executionContext });
        }

        private static readonly string[] s_variableScopes = new string[] { "Global:", "Local:", "Script:", "Private:", "Using:" };

        private static readonly SearchValues<char> s_charactersRequiringQuotes = SearchValues.Create("-`&@'\"#{}()$,;|<> .\\/ \t^");

        private static bool ContainsCharactersRequiringQuotes(ReadOnlySpan<char> text)
            => text.ContainsAny(s_charactersRequiringQuotes);

        internal static List<CompletionResult> CompleteVariable(CompletionContext context)
        {
            HashSet<string> hashedResults = new(StringComparer.OrdinalIgnoreCase);
            List<CompletionResult> results = new();
            List<CompletionResult> tempResults = new();

            var wordToComplete = context.WordToComplete;
            var colon = wordToComplete.IndexOf(':');
            string scopePrefix;
            if (colon == -1)
            {
                scopePrefix = string.Empty;
            }
            else
            {
                scopePrefix = wordToComplete.Remove(colon + 1);
                wordToComplete = wordToComplete.Substring(colon + 1);
            }

            var lastAst = context.RelatedAsts?[^1];
            var variableAst = lastAst as VariableExpressionAst;
            if (lastAst is PropertyMemberAst ||
                (lastAst is not null && lastAst.Parent is ParameterAst parameter && parameter.DefaultValue != lastAst))
            {
                // User is adding a new parameter or a class member, variable tab completion is not useful.
                return results;
            }
            var prefix = variableAst != null && variableAst.Splatted ? "@" : "$";
            bool tokenAtCursorUsedBraces = context.TokenAtCursor is not null && context.TokenAtCursor.Text.StartsWith("${");

            // Look for variables in the input (e.g. parameters, etc.) before checking session state - these
            // variables might not exist in session state yet.
            var wildcardPattern = WildcardPattern.Get(wordToComplete + "*", WildcardOptions.IgnoreCase);
            if (lastAst is not null)
            {
                Ast parent = lastAst.Parent;
                var findVariablesVisitor = new FindVariablesVisitor
                {
                    CompletionVariableAst = lastAst,

Review comment (suggestion):
Please use the same pattern as for wordToComplete:
```c#
var wordToComplete = context.WordToComplete;
string scopePrefix = string.Empty;
var colon = wordToComplete.IndexOf(':');
if (colon >= 0)
{
    scopePrefix = wordToComplete.Remove(colon + 1);
    wordToComplete = wordToComplete.Substring(colon + 1);
}
```

Code after:
            var helper = new PowerShellExecutionHelper(PowerShell.Create(RunspaceMode.CurrentRunspace));
            var executionContext = helper.CurrentPowerShell.Runspace.ExecutionContext;
            return CompleteVariable(new CompletionContext { WordToComplete = variableName, Helper = helper, ExecutionContext = executionContext });
        }

        private static readonly string[] s_variableScopes = new string[] { "Global:", "Local:", "Script:", "Private:", "Using:" };

        private static readonly SearchValues<char> s_charactersRequiringQuotes = SearchValues.Create("-`&@'\"#{}()$,;|<> .\\/ \t^");

        private static bool ContainsCharactersRequiringQuotes(ReadOnlySpan<char> text)
            => text.ContainsAny(s_charactersRequiringQuotes);

        internal static List<CompletionResult> CompleteVariable(CompletionContext context)
        {
            HashSet<string> hashedResults = new(StringComparer.OrdinalIgnoreCase);
            List<CompletionResult> results = new();
            List<CompletionResult> tempResults = new();

            var wordToComplete = context.WordToComplete;
            string scopePrefix = string.Empty;
            var colon = wordToComplete.IndexOf(':');
            if (colon >= 0)
            {
                scopePrefix = wordToComplete.Remove(colon + 1);
                wordToComplete = wordToComplete.Substring(colon + 1);
            }

            var lastAst = context.RelatedAsts?[^1];
            var variableAst = lastAst as VariableExpressionAst;
            if (lastAst is PropertyMemberAst ||
                (lastAst is not null && lastAst.Parent is ParameterAst parameter && parameter.DefaultValue != lastAst))
            {
                // User is adding a new parameter or a class member, variable tab completion is not useful.
                return results;
            }
            var prefix = variableAst != null && variableAst.Splatted ? "@" : "$";
            bool tokenAtCursorUsedBraces = context.TokenAtCursor is not null && context.TokenAtCursor.Text.StartsWith("${");

            // Look for variables in the input (e.g. parameters, etc.) before checking session state - these
            // variables might not exist in session state yet.
            var wildcardPattern = WildcardPattern.Get(wordToComplete + "*", WildcardOptions.IgnoreCase);
            if (lastAst is not null)
            {
                Ast parent = lastAst.Parent;
                var findVariablesVisitor = new FindVariablesVisitor
                {
                    CompletionVariableAst = lastAst,
                    StopSearchOffset = lastAst.Extent.StartOffset,
                    Context = context.TypeInferenceContext
                };
                while (parent != null)